During the last interview cycle I did back in early 2019, I spoke to a handful of startups.
I always ask about the deployment pipeline for startups because it helps me have an idea of what stage of technical complexity the company is at. Some businesses can go really far on a simple PHP web app deployed with SCP.
Others hit limits and have to rework the system into several services with infrastructure components like Redis or Kafka used to communicate between them.
When they see Kubernetes on my resume, interviewers often ask about it. There was a lot of interest in dipping toes into Kubernetes but also some anxiety about whether it was appropriate for the particular use case. How did we use it at my last company? Was it difficult to learn? What were the development teams’ experience of working with it? Sometimes there are horror stories of bad implementations and fears that moving to Kubernetes was a mistake. Often I hear some very reasonable skepticism alongside a desire to keep deployments simple and a hesitation to jump on the bandwagon.
So I will jump to the punchline here. If I were starting my own startup from scratch today, I would very likely start with Kubernetes. I’ve used it in two very different companies now, and this is my (admittedly subjective) conclusion.
Quite simply, the few negatives are so greatly outweighed by the positives that I think it’s worth the investment for many startups. Not all startups. Not necessarily your startup. But a lot of them.
Let’s take a look at the reasons why.
What Is Kubernetes?
In short, Kubernetes is an open-source container-orchestration system, originally developed by Google. It has been contributed back to the community, with lots of new libraries and plugins (called operators) contributed by third parties.
Kubernetes is not a cloud platform like Amazon Web Services (AWS) or Google Cloud Platform (GCP). In fact, you could run and deploy Kubernetes on your own hardware in your own data center, if you were so inclined — though, I don’t recommend this for startups.
Think of it more like a language we can use to describe a working system. Once we describe the system in enough detail, Kubernetes can then go and use its compute resources (nodes in Kubernetes parlance — also known as, you know, computers) to run containers that execute our system.
The big benefit for startups is that this process of “describing the working system” serves as documentation and a centralized location in code for defining infrastructure.
Kubernetes Pays for Itself
I’m not going to lie. EKS (the managed Kubernetes solution provided by Amazon) is expensive. It’ll cost you an overhead of $0.20, or $1,753.20 a year, on top of your EC2 costs. It’s not free.
But consider what you would pay to have an engineer manually bring up nodes. The amount of time lost to these purely infrastructural changes is simply taking time away from developing your product. If you’re a startup trying to just hit your next goal, you should be happy to pay a (reasonable) overhead to magically erase an error-prone and time-consuming process from your team.
With the Terraform tool at hand, you can also create a Kubernetes cluster that can be scaled with a simple one-line change. In my last team, our cluster grew from two to four nodes with a Git commit that changed a 2 to a 4. It was literally a one-line change. After the nodes were added, Kubernetes automagically moved resources onto the new nodes, and no further work was required. Then you can move on to solving real problems.
Deployments Are Easy
A traditional Linux production system typically looks like this. You have some code written in Java, Python, or Ruby. The application code is often written by people that don’t know servers very well — or at least aren’t practiced in them.
You have a machine, let’s say in Amazon EC2, which is managed by someone in your ops team who doesn’t know the application code very well. When the application team completes some work, they want to be able to deploy those changes. The ops team wants to ensure those changes don’t break anything.
You also don’t want the system to go offline during a deploy. You want to be able to rollback to a previous version of the code if something goes wrong. And what if your deploy process, from uploading assets to starting the server, takes 30 minutes? Will you take your system offline for 30 minutes?
Probably not. You’ll likely come up with some system for keeping version n-1 running until version n starts up, at which point you’ll switch to point to the new version.
But boy does that seem complicated. It’s a lot to remember — and a lot that can go wrong. Those deploy rules will be written in a series of scripts that need to be versioned and maintained and could very well contain bugs themselves. And when we’re expanding the company in separate teams, all of them trying to deploy multiple times a day. It starts to feel scary. The ops team members start to get overwhelmed with the amount of churn in the system. Deploys start to take longer and longer as the process becomes laden with more and more complexity.
Does this story sound familiar?
Kubernetes does away with much of that complexity. To deploy a new version of a service, we can simply update the container image to point to the new version of code. We can also define a health check that’ll be performed before declaring the new version is working. If it doesn’t pass, the old version of code keeps running.
We can define a service using an internal-only DNS name, like
order_service, which will automatically load balance to running replicas. Nobody has to maintain a list of running instances.
And if we find a problem after the deploy, a simple rollback command looks up the previous container image and applies it. Often this can take just a few seconds, and then we’re back to running the last known stable version of our software.
Doesn’t that sound nice?
You Don’t Need a Separate Ops Team That Does Everything
Kubernetes itself is a complex beast. But using it is achievable for any seasoned developer.
That’s because instead of using a complex series of bash scripts, special deploy tools, and so on, Kubernetes deployments are managed with simple declarative YAML files.
That’s right. The simple XML replacement championed by Ruby enthusiasts is all you need to know to work with Kubernetes.
Using nothing but YAML, we can define a whole working system with autoscaling, replication, and service resolution. Then using the kubectl CLI tool, we can ask the cluster to run our configuration. We never directly tell Kubernetes to do anything. Rather, it reads our declarative YAML and interprets what needs to be done.
Do you think your developers can figure out how to write YAML? I do.
I’ve worked on some complex systems that required the person managing the deploy to understand a) Python, b) Bash, c) some minor intricacies of the OS version we were running, d) JVM flags (God help you), e) SCP commands (can you write a valid SCP command without looking at docs?) … and so on.
There is also an organizational overhead. Often the deploy scripts and infrastructure code are managed by the ops team. But developers often needed to make changes in the deploy code — for example, to set a flag on startup — and to scale up the system. That creates a tension between developers and ops since the two groups create demands on one another but are often beholden to different objectives.
All that complexity and overhead adds a tax to everything you do in your startup. If you want to develop new features quickly and have the ability to easily jump from project to project, then you really want to keep that friction as low as possible. Kubernetes abstracts away a lot of the pain, leaving you to focus on the product.
Situations Where You Probably Don’t Need Kubernetes
Of course, there is no silver bullet, and there are cases where something like Kubernetes is overkill.
Simple WordPress sites, CMSs, etc.
If you’re just running WordPress, you don’t need Kubernetes. If you’re running a CMS that never really gets deployed except once in a while to upgrade libraries or install a plugin, you don’t need Kubernetes. It’s really optimized for managing large, changing systems.
Embedded systems, anything needing access to a real OS
Obviously, if you’re writing low-level embedded systems or software that needs to interface with the Linux kernel, Kubernetes is not for you. That goes for any containerization solution.
Your product is primarily a database
Kubernetes does have a resource type called a “Stateful Set” intended for running things like databases and message brokers that manage state. In theory, running a Stateful Set could allow you to run multiple replicas and scale them up and down — and attach and grow storage.
But doing so always makes me a little nervous. With an application service, I want to make it easy for developers to tweak settings and deploy without trouble. With databases, I want just the opposite. It should be hard to accidentally change a setting or upgrade the system to a new version. I also don’t want my database competing for CPU and memory within the cluster.
I’m especially prone to not use Kubernetes for databases if I’m using AWS and have access to RDS. RDS or its equivalent in your cloud provider of choice is going to be a lot easier for managing automatic backups, scaling, and monitoring.
Kubernetes is perfect for any project that needs to scale and grow over time.
If you’re a startup, you almost certainly fall into that category. You might be small right now, but you want to grow. It’s what you tell your investors, and it’s the reason you’re hiring so many developers. Your system is going to change and expand quickly, and you want to build it in a way that allows this with the least amount of added cost and friction possible.
For that reason alone, I think it makes a lot of sense for any e-commerce, SaaS, or similar company to invest in Kubernetes early on. Even if you’re just deploying a single simple web application within the cluster, planning for the future means building your infrastructure carefully to enable your team to move quickly a year or three down the line.
Thanks for reading, and best of luck!