As a fast-moving startup, you don’t have the luxury of spending days figuring out exactly what you need in a Kubernetes cluster. We’ve been there.
To help out, we wrote a whole ebook on the blueprint we followed as we built and deployed our own web app in Kubernetes. This book covers Kubernetes components, how to create a Kubernetes cluster, building and deploying your application to Kubernetes, securing your cluster, and how to use monitoring and logging tools to help you stay on top of your application and cluster.
But since Kubernetes is new, there are tons of related topics, articles, blogs, how-tos, and documentation for all kinds of features that are really exciting... but in our opinion, a lot of this stuff is just not relevant for a startup that's launching with Kubernetes for the first time.
When you are just trying to focus on getting your business going, many of these topics can lead you astray from the primary goal of running your application. Let’s go over a few of these and how and when they can fit into your organization.
Config management: On the fly is OK for now.
When you are just starting up, it is usually easier to just run one-line commands and configure things on the fly. For any projects that you expect to last, you will want to consider how you are organizing and keeping track of changes to your infrastructure, and that includes your Kubernetes components.
All Kubernetes components can be expressed in either JSON or YAML in manifest files. You should organize these in a file structure that makes sense to you and that will allow you to recreate your Kubernetes components in the event of a failure. Kubectl allows you to specify a filename for creating or updating resources using manifest files like so:
kubectl create -f my_app_deployment.yaml
If you need to edit a resource, you can instead edit the YAML manifest file and then update using the file:
kubectl apply -f my_app_deployment.yaml
You can then store these files in a git repository, and commit changes to these files to your git history. In this way, you can easily look at how your environment has changed over time, replicate your entire setup, and eventually create automated workflows based on changes to these files.
Another commonly used tool for managing Kubernetes is Helm. Helm essentially acts as a repository for creating and managing Kubernetes resources from the community, and you can also use it for your own resources. (We wrote an intro to using Helm with Kubernetes that might be helpful.)
A lot of Helm users like the ability to use templates for Kubernetes resources which can speed up deployment for apps across multiple environments such as dev, QA, and production. One criticism is the added complexity and that the tiller process must run to keep configuration in sync. In any case, using either of these methods is better than having no control or history of your Kubernetes configuration changes.
CI/CD: Automate when you're ready and not before.
CI/CD is the ultimate goal of every engineering organization these days. The ability to fully automate the building, testing, and deployment of your application sounds amazing on paper, but for a startup, it can be an early death sentence.
Early on in your application’s lifecycle, you will be creating features, reworking the entire system, and writing bugs daily. Spending hours (which will turn into days) to try and automate a build system for something that is constantly evolving is a poor use of your time early on.
So when should you turn to automation? It depends on your team. When building and deploying is a noticeable drain on your time, and you have a few days of free time to spend on it, you should at least invest in an automatic build system. Recognize that you can do automatic builds without spending even more time on automatic deploys, and you should do so. Until you are extremely confident that your automated tests and builds are 100% trusted, we do not recommend doing automatic deploys into a Kubernetes cluster.
When you do decide to automate your build and deploy system, Jenkins is one of the most popular open-source build tools, and you can integrate it with Docker and Kubernetes to automate your build. If you are already familiar with Jenkins, then this is the approach we recommend. Other people have written detailed guides for integrating Jenkins into a Kubernetes pipeline, so we will defer to them.
If you are not familiar with Jenkins, then you can look at the free offerings of TravisCI and CircleCI. Both of these SaaS products offer ways to build your docker images automatically, and they have reasonable paid plans for when you reach a scale that requires it. Codefresh is another tool we recommend.
It can be convenient to run Jenkins or another open-source solution inside of your production Kubernetes environment, but we recommend you don't do that. If your production cluster is having issues, you do not want to be in a position where you cannot build or deploy your application. Treat your build system as a first-class citizen in the same way you do for your log management and alerting system. At the very least, have a backup method for building and deploying that you test regularly in case your primary method is unavailable.
Autoscaling: Unnecessary and expensive at a small scale.
Another popular feature of Kubernetes is that it allows you to autoscale your pods and nodes both vertically and horizontally. One of the advantages of Kubernetes is definitely the ability to abstractly run your microservices in the cluster without worrying about resources, but autoscaling in the early stages of your application is probably unnecessary and can become expensive.
If your app is not seeing consistent week-over-week growth, then it is likely easier to just slightly over-provision your cluster and pods and monitor things manually until you can put in the time to set up autoscaling. Scaling up in Kubernetes the “manual” way is generally pretty easy, as we describe in the ebook. You can quickly add more nodes and increase the size of your deployment when you need it, you just have to set up some basic alerts to tell you when CPU and memory utilization are high in your cluster.
Service mesh: Better suited to a larger team.
Service meshes are the next big thing after Kubernetes. The idea behind a service mesh is that at a certain scale, it becomes difficult to manage dozens of microservices in production and understand how they interact with each other. A service mesh can provide you with performance metrics, service discovery, load balancing, failure recovery, deployment strategies, end-to-end authentication, and many other features that make life easier for large deployments. However, these features come at a cost.
There is a learning curve to expressing your application as a service mesh and a literal performance cost since it sits between all of your services to gather request metrics. Implementing a service mesh is probably a bad call until you have a team dedicated to DevOps, or infrastructure, or at least SRE that can actually see the value it provides.
Istio is one of the most popular service meshes currently available, and it integrates tightly with Kubernetes. It has all of the features you'd expect from a service mesh, including interesting deployment techniques that allow for canary rollouts, A/B testing, fault injection, and circuit breaker patterns. Keep an eye on istio as you scale your application into multiple regions and achieve CI/CD as a way to help you stay on top of what will likely become a very complex Kubernetes setup.
A very common enemy of startups is pretending you're further along than you are. When your app is an early stage, you simply don't need to spend the time and effort on certain things that you will when you reach a bigger size. For now, set those things aside and focus on growth.
We also wrote a guide for deploying an app to AWS that's in a similar vein. We'll show you how to do it without the extra effort.