Debugging Go applications in TILT
One of the biggest challenges when working with a microservice system is spinning up all of your services locally during development. In recent years, Docker Compose has been widely used, simplifying the management of your entire application stack and making it easy to manage services, networks, and volumes.
However, in some scenarios, it may not be enough, and this is where TILT can help us. Using TILT, our application runs on a local Kubernetes cluster with the specific peculiarities of this scenario. In this post, we will see how to efficiently debug a Go application that runs using the package tilt-enhancements.
When docker-compose is not enough
Docker Compose is a great tool for managing multi-container applications in development, but it falls short when your environment starts to mimic production setups, especially those involving Kubernetes. If your application consists of numerous microservices that need to interact within a Kubernetes cluster, or if you require real-time feedback and streamlined debugging, TILT becomes the better choice.
Unlike Docker Compose, TILT is specifically designed to handle the complexities of Kubernetes-based microservices, offering features like automated rebuilds, redeployments, and an integrated UI for monitoring and debugging. This makes it ideal for developers who need a more robust, production-like environment during development, where Docker Compose's capabilities are limited. And if you're looking for a fancy UI for your microservices, TILT has you covered!
For more insights, please check the official doc
TILT for GO Applications
Imagine you have a API Rest implemented in Go, and you want to develop it using TILT. First, you need a Dockerfile to build the image (in addition to Kubernetes manifests to deploy the application and other resources):
Now you can run the application using TILT with the following Tiltfile
This is a basic configuration that is enough for this section, but you can take advantage of more features such as compilation optimizations and live updates on changes. More info here
With this configuration you can run your application in local k8s cluster using TILT but... who doesn't need to debug something while developing?
How to debug a Go application running with TILT
Since the application is not running on your host you need to add delve to your Dockerfile and expose a port to allow remote debugging connections.
After that, you should tell Tilt that execute the binary with delve and export the port to be forwarded as well to the cluster. Modify your Tiltfile
to do so:
And finally you only need to configure your IDE - or whatever tool you use - to connect to the remote debugger. For example the following configuration for VSCode:
Voilà! Now you can debug the remote application just like you would debug a local application... right? Well, not exactly. The debugger isn't ready to connect until the container and the application have fully started. So, how do you know when to start debugging? Do you just take a chance each time and hope you get lucky?
For example, if you are developing a REST API, you can debug the endpoints as they are called due to the nature of the application. However, if you need to debug the application from the moment it starts, you need to pause the process until a specific signal is received.
How to debug a Go application on TILT from startup
Here is a simple way to stop the application until the debugger is connected using the await
package from tilt-enhancements repository:
By default the await package is disabled, to enable it you should set the environment variable TILT_AWAIT_DEBUGGER_ENABLED=true
as environment variable.
Now you have the control since the first line of the main function 🐛
Conclusion
TILT provides a powerful environment for running and managing applications within a local Kubernetes cluster but it can make debugging complex and challenging. The await
package from the tilt-enhancements
repository offers an effective solution by allowing developers to pause the application startup until the debugger is connected. This feature provides precise control over the debugging process from the very first line of code, making it easier to troubleshoot and manage complex microservices environments.
Remember to keep the local environment for development as simple as possible as long as it works for everyone in the team and meets the organization's standard with the minimum feedback loop