This article explains debugging in Kubernetes using VS Code on the desktop and Node running in IBM Cloud.
Understanding the steps required to debug an application running in Kubernetes can be a complicated task for some developers. Programmers expect debugging to “just work” the same way it does on their desktop, but the application is running remotely in a container. In some cases, IDE’s and code editors obscure the steps needed to debug or provide plugins that fail when misconfigured, leaving developers on their own.
This article explains debugging in Kubernetes using VS Code on the desktop and Node running in IBM Cloud, however, the steps apply to other languages.
Debugging in Kubernetes
Debugging an application in Kubernetes requires the following steps:
Start the program in debug mode.
Port forward the debug port.
Attach the debugger to the running program.
Start the program in debug mode
Every program has a main. In Docker, the main is either an ENTRYPOINT or CMD statement. In order to change the way your program is started, you can either modify the main in your Dockerfile or override the container spec in your Kubernetes YAML. Often, the latter is more convenient as it allows you debug without rebuilding your container.
Here is the main for a container, overridden using an args: statement in a YAML deploy file:
At first glance, examining the statement, it may not be obvious what the debug arguments do.
The --inspect argument tells Node that it is running in debug mode. By default, the debug port is 9229. You can override the port if there is a conflict with a port in your application [--inspect 127.0.0.1:9229], but you must change this number in the appropriate places in the other steps.
The —debug-brk argument tells Node to stop before the first line of your program is executed. This allows you to stop at breakpoints in your main program versus those in callbacks. If you do not specify this flag, your program will run past breakpoints in main because a debugger is required to set a breakpoint and one is not yet running. Callbacks are typically REST entry points that get invoked when you refresh a web page. Most of the time, you will want to stop there.
Note that in versions greater than Node 6, —debug-brk has been replaced with --inspect-brk and you need only to provide one of --inspect or --inspect-brk (but not both, remove --debug-brk).
After you have overridden the main, you’ll need to apply the changes to your running application. If you specify --debug-brk, don’t be surprised that your web pages are not refreshing. Your server will not be serving any HTTP requests because it is halted in main.
If not done already, you’ll need to ensure in your deployment YAML that replicas is set to 1 to force all traffic to go to the container you will be debugging. This is the default, so if you do not have a replicas: statement, you do not need to add one.
Port forward the debug port
When your program is running under debug, it will be serving debug requests on port 9229. You’ll need to attach a debugger in order to set and respond to break points. The debugger will run on your desktop and listen on a port there, so you’ll need to connect to the remote port. Kubernetes supports port forwarding, but first, you’ll need to use kubectl get pods to get the name of the pod that you just deployed that is running under debug.
Here is the port-forward command that sends remote traffic in Kubernetes on port 9229 to the local port 9229 on your desktop for app-1234-abcd:
$ kubectl port-forward app-1234-abcd 9229:9229
Forwarding from 127.0.0.1:9229 -> 9229
Forwarding from [::1]:9229 -> 9229
Handling connection for9229
Handling connecting for9229
Scroll to view full table
Attach the debugger to the running program
At this point, the server is running in debug mode and remote traffic on 9229 is redirected to your desktop. The next step is to attach a debugger. VS Code includes a Node debugger that is easy to understand, use, and configure. If you do not have a launch.json in your .vscode directory in the root of the source for your component, create one.
You can paste in the following entry or use VS Code’s code assist to generate it for you.
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach to remote Node.js (9229)",
"address": "127.0.0.1",
"port": 9229
}
]
}
Scroll to view full table
Once you have saved launch.json, attach the debugger to the remote program:
After the debugger has attached, you should see a screen that looks something like this:
Conclusion
When developing and running in Kubernetes, programs are running in containers, and changing code requires rebuilding and deploying new containers. Deploying, port forwarding, and reattaching a debugger can become tedious during development. Tools such as Skaffold support save and redeploy, and IDE and editor plugins can help, but these tools can obscure the debug steps, which are always helpful to understand should something go wrong.