[i18n] readingTime
Cloud Native Development
The use of containers is quickly becoming the de facto standard for application development whether you like it or not. Containers themselves will undoubtedly be considered to be some archaic, shitty technology at some point down the road but their contribution to providing isolation is something that will not be forgotten. There are countless articles on the internet describing how containers work under the hood and how they’re different from VMs, but I haven’t seen much talk of how to actually use the damn things effectively in your everyday developer life. Same thing goes for deployment tools like Helm and much of the cloud native ecosystem.
I’ve often seen guides on
how to write an application for Kubernetes and how it will fix all your problems by allowing “organizations [to] achieve
increased efficiency and agility”. Overall, that guide makes some good points about Kubernetes offering better
scalability and flexibility, but it doesn’t talk about how I’m supposed to use Kubernetes every day as a developer
without wanting to kill myself significant friction.
Problem
Many of the benefits that cloud native applications offer can be a huge disadvantage for traditional application development such as isolation and ephemeral runtime environments. For example, when I make changes to an application using a traditional workflow I need to:
vim app.go
make
./app
This simple set of tasks will happen numerous times throughout the day and I can merrily develop software.
But when I make changes to a cloud native application, I need to:
vim app.go
make
docker build -t localhost/some-app:$(git describe --always) .
docker push localhost/some-app:$(git describe --always)
helm install some-deploy some-chart --set image.tag=$(git describe --always)
Not a huge number of tasks, but you have to run multiple applications and this gets very tiresome having to flip through
your Bash history all day for every single change. If you think this could be simplified by just using the latest tag
you would be wrong because you should never ever use the latest tag. Also, you could write a script to run these
steps which wouldn’t be terrible but, now you have this custom script for each project that’s going to definitely be
slightly different across projects, and you have to worry about that maintenance especially if you want to use that
script for prod deploys.
Plus, if you want to debug your application you’ll have to set up a build stage in the Dockerfile and manually forward
ports out of the cluster.
Sane development
Years ago when I was still fairly new to cloud native development I came across a tool
called skaffold which helps tie all of these tasks together. All you have to do is configure a
skaffold.yaml in your project, then when you make changes it will look like this:
vim app.go
skaffold dev
That’s it! This will:
- compile your application
- build the Docker image
- push the Docker image
- deploy the Helm chart
It will also watch source file and execute these tasks again when it detects changes.
And if you want to debug changes made to your application:
vim app.go
skaffold debug
That will run all the tasks executed by skaffold dev and forward the application’s debug port out of the cluster to
your workstation.
Try it
You’ll probably have some frustrating moments with Skaffold at some point. But for me, it is well worth it to have a unified method for developing, debugging, and deploying cloud native applications and avoiding the hell of having to manually operate a Rube Goldberg machine every time you make code changes.