Debugging a Kubernetes application

Cloud Code lets you easily debug an application deployed to a Kubernetes cluster by leveraging skaffold debug. You can debug your application on a local cluster (like Minikube or Docker Desktop), Google Kubernetes Engine (GKE), or any other cloud provider.

You don't have to complete manual setup like setting up port forwarding or injecting language-specific debug arguments. You simply need a Cloud Code-ready Kubernetes application that includes a skaffold.yaml configuration file and a cloudcode.kubernetes launch configuration.

Debugging an application

  1. From the Cloud Code status bar, choose the Debug on Kubernetes command.
  2. If your application doesn't have the necessary Skaffold configuration or cloudcode.kubernetes launch configuration, Cloud Code helps you set these up.
  3. Confirm whether to use the current Kubernetes context to run the app in (or switch to a preferred one).
  4. If you chose a remote cluster as the context, you're prompted to provide an image registry to push the images to.

    The following samples demonstrate how to specify where container images are stored for some common registries:

    Docker Hub docker.io/{account}
    If you're using a private Docker Hub repository, make sure that you're properly authenticated.
    Google Container Repository (GCR) gcr.io/{project_id}

    To generate the final image repository name, Cloud Code concatenates this image registry with the image name specified in the Kubernetes manifests. This choice is stored in your cloudcode.kubernetes launch configuration (found in .vscode/launch.json).

    For more information, see the image registry handling guide.

    Cloud Code builds your containers, pushes them to the registry, applies Kubernetes configurations to the cluster, and waits for the rollout.

    After the rollout, Cloud Code automatically port-forwards all declared container ports to your machine and displays the URLs in the output window so that you can browse your live application.

    Port-forwards and displays the URLs in the output window

  5. For each debuggable container in your application, confirm or enter the directory in the remote container where the program you want to debug is located.

    Alternatively, you can press ESC to skip debugging the container.

    Remote Root prompt

    Cloud Code attaches a debug session for each debuggable container in the application.

    You can now perform the same tasks you normally do when debugging local code, like setting breakpoints and stepping through code, against a live Kubernetes cluster.

    By default, when a change to your application is autosaved, Cloud Code redeploys your application and sets up a new debug session. You can toggle this feature with the watch flag in your project's launch configuration.

  6. To inspect variables and stack info, use the Debug Sidebar. To interact with the debugging session, use the Debug Console in the bottom pane debugger.

    App paused at breakpoint and variables and call stack sections populated with values in scope

  7. After your session completes, you can use the following contextual menu commands:

    • Open Deployment Logs: Open the application logs of a specific deployment with the Cloud Code Logs Viewer
    • Open Service URL: Open the application service URL of a specific service in a web browser
  8. If have turned off watch mode in your launch configuration and you want to make changes to your application and rebuild and redeploy the application, in the Development sessions pane, pause on the run action and then click Rebuild and redeploy icon Rebuild and redeploy the application.

  9. To end the debugging session, click Debug stop icon Stop in the Debug Toolbar.

    After you end the debugging session, all the deployed Kubernetes resources are deleted from the cluster.

Configuration details

Cloud Code, powered by Skaffold, automatically handles the following configuration details for all supported languages:

  • Port forwarding the debug port so that the debugger can be attached.
  • Attaching a debugger to one or more debuggable containers in your application. If your application has multiple debuggable containers (containers whose language is supported by Cloud Code debug) configured in skaffold.yaml, then a debugger is attached to each of debuggable container.
  • Persisting source mapping definitions across sessions; you can customize these definitions by editing your .vscode/launch.json directly.

Cloud Code also handles the following language-specific configuration details:

Node.js

Rewriting the entrypoint to invoke:

node --inspect=localhost:9229

Python

Installing the ptvsd module using an Init Container and rewriting the entrypoint to invoke:

python -m ptvsd --host localhost --port 5678

Go

Installing the dlv debugger using an Init Container and rewriting the entrypoint such that the launched debug session runs with a debug server only (in headless mode), continues the debugged process on start, accepts multiple client connections, and listens at localhost:56268:

dlv exec --headless --continue --accept-multiclient --listen=localhost:56268 --api-version=2, <app> --

Java

Adding an environment JAVA_TOOLS_OPTIONS with the appropriate Java Debug Wire Protocol (JDWP) configuration such that the JDWP debugging agent listens for a socket connection on port 5005 and allows the VM to begin executing before the debugger is attached:

jdwp=transport=dt_socket,server=y,suspend=n,address=5005,quiet=y

For more details on Skaffold-powered debugging, see the skaffold debug documentation.

Attaching debugger to a Kubernetes Pod

Cloud Code for VS Code also supports attaching a debugger to a Kubernetes Pod. For a comparison, see Attaching to a Kubernetes pod vs Debugging a Kubernetes application.