Evaluating Kubernetes Development Tooling
Application development with microservices is typically a bit different and at times more complicated than more traditional monolithic architectures. When writing a feature against a single service, you may find that you depend on another running service to test API calls. Debugging and observability can be more difficult as well, due to needing to aggregate logs and traces across multiple services.
Microservices help solve some of the scaling problems inherent with monolithic designs, and Kubernetes helps solve some of the problems with deploying and scaling these microservices. But staying agile when developing microservices can be challenging. With a monolith like Rails, the entire application runs and deploys as one making it straightforward to run locally to develop against, at least for smaller applications. When developing a microservice like in a Golang monorepo, you'll usually need to manually run other services locally or somehow forward requests to a remote (usually shared) instance of the other services.
Putting aside questions of monolith vs microservices and assuming you're already working with microservices on k8s, the question becomes: what is the best way to develop software in this environment? "Best" can of course mean a lot of things to a lot of people, but I'll mostly focus on these criteria:
Developer experience
Scalability
There are a lot of great tools in the Kubernetes development space, ranging from a primarily local development workflow, to hybrid, to fully remote development.
Local
Native
Continuing with the Golang monorepo example, it's fairly straightforward to compile and run Go code natively on your host with go build / go run. This is pretty much the ideal development environment: native integration with the IDE of your choosing, very fast feedback loops and native debugging. This works great until you need more than one service running at a time or need to configure other dependencies like databases. If you do need to interact with other services, you can use a tool like Docker Compose to orchestrate multiple services locally, or kubefwd to forward traffic to services running in a development or staging cluster environment. kubefwd can be annoying to work with though and require frequent restarts. Additionally, shared environments only work well if they are read-only, it won't scale to have multiple engineers deploying to and modifying a single shared development environment.
Docker-compose is great for "composing" multiple services to run together locally and is likely to serve many teams well, but there are a few drawbacks to consider.
Strengths
Weaknesses
Tilt helps make developing against a local Kubernetes cluster easy. It offers hot reloading, and had an especially excellent web UI that you can even add custom buttons to to run tasks like DB migrations for example 🤯.
Unfortunately developers are on their own to configure and operate a local k8s cluster which is usually Docker based, inheriting all of Docker's downsides. Like Compose and other local solutions, memory constrains how many services you can run at a time. Teams with multiple, resource-hungry services will have to configure and operate at least a portion of the stack remotely.
Strengths
Recommended by LinkedIn
Weaknesses
Hybrid
Telepresence offers a hybrid development environment, where you run your code locally (natively or with Docker) and redirect remote cluster traffic to your local service. Telepresence provides a 2-way proxy so your local services can access cluster services much in the same was as with kubefwd, but is also able to proxy or "intercept" cluster traffic to your local service. This lets you bypass the merge/build/deploy cycle and provides a native development experience while operating as if the service was deployed alongside other services in the cluster.
Strengths
Weaknesses
Remote
Garden enables you to code locally while constantly syncing your code to an isolated namespace in a remote cluster and supports hot reloading for fast feedback loops. With this approach you get the local development experience in addition to all the benefits of deploying your code to a proper remote cluster.
Strengths
Garden checked a lot of boxes for me in terms of the original requirements around developer experience and scalability, but no tool is perfect.
Weaknesses
Conclusion
Matt Rickard asks the right question in Don't Use Kubernetes Yet:
How can you choose the right technology now so that you can maximize growth and minimize pain later when you inevitably outgrow it?
For many apps, developing natively or with Docker Compose will get you quite far. But for teams developing microservices on Kubernetes, I think Garden meets the requirements of providing an excellent developer experience while being a tool that can scale to large engineering teams when needed.
Exciting ideas here! Can't wait to see where this goes. 😊