6 minutes
Unironically Using Kubernetes for my Personal Blog
There’s no shortage of posts like “Let’s use Kubernetes!” Now you have 8 problems, or Do I Really Need Kubernetes?, which tend to argue that unless you’re orchestrating 1000 containers, you’re good without Kubernetes. Also, I thought this tweet was hilarious:
So… Hi, I’m the guy using Kubernetes for my blog and small side projects, here’s why I love it (to the extent one can love a deploy tool).
“You don’t need all that complexity”
Undoubtedly, Kubernetes is doing a lot under the hood. But as an end-user, I’m not exposed to that complexity. After spending a couple hours learning the key concepts through the official tutorial, it really is very easy to use day-to-day.
For example, the entire deployment configuration for this blog is contained in this yml
file:
apiVersion: v1
kind: Service
metadata:
name: blog
spec:
ports:
- port: 80
selector:
app: blog
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: blog
spec:
selector:
matchLabels:
app: blog
replicas: 2
template:
metadata:
labels:
app: blog
spec:
containers:
- image: marcusbuffett/blog:latest
name: blog
ports:
- containerPort: 80
name: blog
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: blog
annotations:
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: letsencrypt
konghq.com/override: "https-only"
spec:
tls:
- secretName: blog-tls
hosts:
- mbuffett.com
rules:
- host: mbuffett.com
http: &http_rules
paths:
- backend:
serviceName: blog
servicePort: 80
Little bit repetitive, granted. But only 50 lines, fully self-contained. So much
nicer than clicking around in AWS console, and easy to grok because everything I
could need is right in that one file. If I need to update anything all I do
is edit that file and run k apply -f deploy.yml
(kubectl
is aliased to k
).
In my project I have a script like this:
#!/bin/bash
docker build -t marcusbuffett/blog:latest .
docker push marcusbuffett/blog:latest
kubectl rollout restart deployment blog
If I want to deploy, I run ./deploy.sh
. Boom, rolling deployment started. If
it fails, the latest working version will be used. For most of my side projects
I can just copy a config and deploy script like this, and have the project up
and running on production quicker than any other solution.
“Just do X, that’s so much simpler”
I’ve been around the block a few times with deployment tech, from Ansible playbooks to Docker Compose to Heroku to AWS to bare metal. I just say this to clarify that I have tried alternatives, I’m not just jumping into Kubernetes on my first round and going “this is the best!”.
The solution I was using for personal projects before Kubernetes involved a bare
git repo on my server, used as an origin, which had a hook to restart docker
compose. A little annoying to set up, but after 10 minutes of work you have a
working CD-esque thing, git push live
to deploy. It’s the kind of solution I see
recommended on /r/programming over Kubernetes. But then I needed to upgrade my
server, alright have to make that bare repo again. And then I wanted my side
project to have rolling deployments, which turns out to be nontrivial with
docker compose. And then I wanted only the server container to restart on
updates, not the database. And then I had to figure out how to manage secrets
without committing them to git…
This is the kind of thing that happens with hand-rolled, “simple” solutions. You’re not whipping up something that does what Kubernetes does in 10 minutes, you’re whipping up 1% of Kubernetes. Then you need to context-switch when you need to get to 2%, or 3%. If you spend that time learning Kubernetes instead, you’ll be able to handle any situation Kubernetes can handle, which is pretty much anything you could think of. I only use some small % of Kubernetes, but it doesn’t hurt me that it can do a whole lot more.
Declarative
The Kubernetes docs describe what a controller does:
A controller tracks at least one Kubernetes resource type. These objects have a spec field that represents the desired state. The controller(s) for that resource are responsible for making the current state come closer to that desired state.
This is the beautiful part of Kubernetes for me. You’re always just describing the desired state, and it’s up to Kubernetes to figure that out for you. Need TLS? All you say in your yml file is “I have this domain that has TLS”, then Kubernetes will go through its paces and go “oh, this doesn’t match, let’s get TLS working on this domain”. Need a persistent, read-only Digital Ocean volume at /mnt/data, with 20GB of space? Just declare that in the yml file and Kubernetes will provision the volume, mount it, etc. It knows not to start your application until that volume is ready too.
This declarative nature makes it super easy to look at existing configs and
modify them too. For example, I was making a rust project recently and thought
“I need a postgres pod like I did for that other project”, all I need to do
is k get pods ${MY_POD_NAME} -o yaml
to get a yml file I can copy and edit for
my new service. I can be assured it’ll work because there’s nothing besides that
one yml file that will control how that pod works. I won’t have to mess with
iptables, or make sure I have the right permission setup for postgres, or do
some initial database setup.
In Closing
I think Kubernetes has fallen into the Vim/Haskell trap. People will try it for 10 minutes to an hour then get fed up. The point where you start to grok stuff just happens too late for most people to stick with it. Those become a vocal minority proclaiming it as too complex for humans to understand, and scare off people that haven’t tried it at all. There is a class of tools that don’t confer any advantage until you spend a few hours with them, and it’s really hard for these tools to gain adoption, even though the people that stick with them become die-hard believers.
I was told Vim was too complex and I should just use Sublime Text or Eclipse, but I bit the bullet and now I fly through code, and feel like I’m moving through molasses when I have to use, e.g. XCode. Since that experience, I give complex tools a bit more of a chance. Sometimes I’m burned (why did I ever switch to Dvorak, total waste), but sometimes I find a Kubernetes.
If you play games, my PSN is mbuffett, always looking for fun people to play with.
If you're into chess, I've made a repertoire builder. It uses statistics from hundreds of millions of games at your level to find the gaps in your repertoire, and uses spaced repetition to quiz you on them.
If you want to support me, you can buy me a coffee.