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.