*maybe more, maybe less, but it’s popular to have some number (preferably
smaller) in a title. I remember tech/programming books with titles such as
“Learn X in 10 days”. After a while, those days in the title changed to
hours and now we are talking in minutes… Second, micro-,nano-seconds next?
Recently, I wrote a post titled From Makefile to Go semantic versioning service on Kubernetes where I talked about creating a simple service in Go that runs on Kubernetes and simply returns you the next semantic version. For example: you send something like this minor/0.1.0
to the service, and the service would respond with 0.1.1
.
In the conclusion of that article I mentioned that most of my time was spent figuring out the Kubernetes deployment files (Helm), Makefile and I wasn’t actually spending a lot of time on the code.
Since I have done some React development I remembered a tool called create-react-app that helps you create a basic React app that you can build and run in the browser in seconds. I thought it would be useful if there was something similar for apps/services one would like to quickly get up and running in Kubernetes.
kapp tool was born — a tool that helps you create a Go service and have it running in Kubernetes in no time!
You can download the first release of the app from here. And full source code is available on the GitHub repo.
Quick overview of kapp
With kapp installed, you can create your first Go service like this:
cd $GOPATH/src/github.com/peterj
kapp create helloworld --package github.com/peterj/helloworld
This will create a folder called helloworld under the current folder with the following files:
helloworld
├── .gitignore
├── Dockerfile
├── Makefile
├── VERSION.txt
├── docker.mk
├── helm
│ └── helloworld
│ ├── Chart.yaml
│ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── values.yaml
├── main.go
└── version
└── version.go
You get a Dockerfile for your service, Helm chart to install it and bunch of useful Makefile targets in the Makefile and docker.mk files.
Check out the gif below that shows you how to create a new app, initialize it, build it and run it locally.
Deploying to Kubernetes
Now that you have your app created, it’s time to deploy and run it in Kubernetes. There are a couple of steps involved to get from an app running locally (as a binary), to an app running in a container on Kubernetes:
- Create a Dockerfile
- Build and tag the Docker image
- Push the image to the registry
- Create Kubernetes deployment file
- Create Kubernetes service file
- Deploy the Kubernetes deployment and service
When you ran kapp
you already got a Dockerfile
and Helm chart (Kubernetes deployment, service file) for your app. And with the Makefile
— you also get the tasks you can run to perform various steps.
Let’s start with setting the Docker registry first:
$ docker login # you can skip this if you're already logged in
$ export DOCKER_REGISTRY=[registry_username]
With Docker registry set, we can build the image:
$ make build.image
Then we can push it to the registry:
$ make push.image
Finally, we can deploy our app to Kubernetes:
$ make install.app
That’s it! Your app is not deployed and running in Kubernetes. At this point you can either create a proxy to the cluster (e.g. kubectl proxy
) or get a terminal running inside the cluster and access your service.
Iterate quickly
With the initial deployment of your service completed, you are all set for quickly iterating on the app.
You can make changes to your code, optionally bump the app version and run:
make upgrade
This will upgrade the existing application that’s already running in Kubernetes.
Conclusion
This was a fun side-project to work on and I can see using it to bootstrap any new (Go) service development. Source code for the project is available on GitHub. All PRs and issues are more than welcome!
Top comments (4)
Great idea, however I would appreciate if you used practically any other tool than Makefiles. Makefiles are a bad idea for a huge amount of reasons, and I really hope the tool just dies and vanishes sooner rather than later.
conifersystems.com/whitepapers/gnu...
Thanks for that link! I skimmed through that article and I don't disagree with points made, but it doesn't seem anything directly applies to my usage of the
Makefile
. I am not worried about performance either as the tasks are fairly straightforward and simple.I was thinking about using a script instead, but a Makefile felt more standard and something users would be more familiar with (e.g. more people know about
make [task_name]
thanmycustomscript.sh [my_command]
).Makefile
seemed the most appropriate tool for this.Did you had any other tools in mind?
In that case I guess the most obvious issue with
make
is poor Windows support, and imo tools of this nature generally should be as cross-platform as possible.I didn't really think of anything specific, Python scripting is one of the most cross-platform options out there with a lot of power to it as well, but if you're writing Go tools, why not write your tools in Go? Afaik it should be rather well suitable for that stuff too, and if your
Makefile
rules are simple, they would likely be ported with minimal effort.goroutines.com/shell seems relevant
gist.github.com/posener/73ffd326d8... seems neat too
Yeah, I specifically mentioned I worked on Mac, so this (probably) won't work on Windows :) I logged an issue on this and if you're interested, I'd love to get more thoughts from you on what the best way to implement cross-platform support would be.
Using Python or Go to implement the tasks I have in the
Makefile
(e.g. build/push docker images, invoke helm, go build, etc.) just seemed to be an overkill.I love Python, but the big downside of Python in this case is that you actually need to have it installed on the machine; that would add an additional dependency (both on MacOS, that has an old version of Python by default, and on Windows that doesn't have any versions :)).
For Go, well the biggest downside would be that I'd either need to build an additional tool and then either drop it into your folder when you run
kapp
OR install that tool for you automatically when you raunkapp
OR havekapp
actually implement all these tasks, so one could dokapp build
orkapp install.app
.The latter sounds the best to me, but as I mentioned previously, I didn't want to load the
kapp
tool with additional commands and have you think about what to run and get used to the syntax :) Another downside of it would be that if you wanted to do certain tasks a bit differently, you'd be stuck - with Makefile (not being perfect), but at least you have access to tasks right there and you can modify them as much as you like :)