Add debugging support for Skaffold: skaffold debug#1702
Add debugging support for Skaffold: skaffold debug#1702balopat merged 66 commits intoGoogleContainerTools:masterfrom
skaffold debug#1702Conversation
- always attempts to apply debugging transform
- assumes all containers are JVM
- fixed JDWP port of 5005: will only work for a single container
within a podspec
Ensures we don't apply debugging transforms on `skaffold dev`.
| port = portAlloc(5005) | ||
|
|
||
| javaToolOptions := v1.EnvVar{ | ||
| Name: "JAVA_TOOL_OPTIONS", |
There was a problem hiding this comment.
shd we make these constants?
|
Great PR!! Looking forward to see this in. |
- Pod - Deployment - StatefulSet - DaemonSet - Job - ReplicaSet - ReplicationController
balopat
left a comment
There was a problem hiding this comment.
This is looking great!
I tried it and now it works nicely too!
I have mostly nits and some refactoring + docs comments.
Some other observations:
- It is a little bit annoying how the multiple containers can race for ports so sometimes web1 gets the 8081 sometimes web2.
- sync and rebuild would be actually nice - now the iteration requires restarting
skaffold debug- which I usually do by changing the yaml file :)
|
Thanks Brian. The logic lgtm. I’ll defer to the Skaffold folks for the golang specifics. |
|
Thanks @balopat for the thorough review.
IIUC, this is related to the port-forwarding of declared container ports to the local host, right?
+1 |
|
PTAL @balopat |
This PR adds a new command to Skaffold called
debug.debugprovides a zero configuration solution for setting up containers for debugging. It is a mix ofrunanddevin that it builds and deploys artifacts similar torun, but monitors and cleans-up likedev.debugtransforms the Kubernetes manifests to setup a container for debugging as required for the container's runtime technology.Comments and suggestions are welcome. I'm know my Go is terrible and can be improved.
About
skaffold debugskaffold debugis likeskaffold devwith the following differences:JAVA_TOOL_OPTIONSenvironment variable added/adjusted to configure the JDWP agent to listen for a specific port--inspect=portadded to configure a DevTools connectionPodSpecmetadata to describe the JDWP/DevTools port nameddebug.cloud.google.com/configwhich points to a string containing a JSON object mapping container-name → a debug runtime configuration object. Each debug configuration object has at least aruntimefield that points to a simple ID describing the underlying language runtime technology (e.g.,jvm,nodejs); other fields specify any configuration specific to that language runtime technology. For example , a pod with two containers namedmicroserviceandweb(line breaks added for legibility)Example transforms
For NodeJS, involving a PodSpec from
examples/hot-reload. The changes in this example:debug.cloud.google.com/confighas a JSON object that describes the connection configuration details. As Kubernetes container objects don't carry metadata, we have to put this metadata on the container's parent; as a pod/podspec can have multiple containers, we use a key-value map, keyed by the container name.--inspect=9229is added to the node command lineNote that we identify this artifact as Node based on the container attempting to run
nodemon. (npm run xxxis not handled as it doesn't support passing through--inspect.)For Java (a deployment from
examples/jib). The changes in this example:debug.cloud.google.com/confighas a JSON object that describes the connection configuration details. As Kubernetes container objects don't carry metadata, we have to put this metadata on the container's parent; as a pod/podspec can have multiple containers, we use a key-value map, keyed by the container name.JAVA_TOOL_OPTIONSis added; this is picked up by the JVM at launch.Change Overview
This implementation happens entirely at deploy time. When I initially starting writing this code, my plan was to implement it as a mutating admission controller, where the code only had access to the images. So this code walks the manifests to be deployed and examines and transforms any containers referenced in a pod/podspec that use a supported language runtime.
We guess the runtime technology for an image container by examining the referenced image container configuration, specifically looking at the environment variables and command-line. It turns out that most of the language runtime base images define a
XXXX_VERSIONenvironment variable or use a well-known command-name (javaornodeornodemon).pkg/skaffold/debuggingdeploy/kubectl.goto configure a manifest transformer (ManifestList)ApplyDebuggingTransformsinpkg/skaffold/debugging/debug.go) walks the Kubernetes objects and applies changes to podspecs based on the guessed runtime technologyskaffold/build/Artifactalone isn't enough to introspect on the corresponding container image as it may have been loaded into the local docker daemon or pushed to a registry. I changedskaffold/build/Artifactto include aLocationenum, and changed the Builder interface to return an Artifact with the location, rather than just return the built tag.-~~ the container image's config (
go-containerregistry/pkg/v1/config/Config) is contained by re-defining theskaffold/build/Artifactto also provide a configuration retriever function.~~ Update: now entirely hidden inside thedebuggingpackage. There are two retriever implementations, one that fetches from a registry and the other from the Docker daemon. This must be determined at build-time as it depends on the local-push.Follow-ups
I'd prefer to leave these follow-ups to separate PRs:
initContainerthat copies files into anemptyDirvolume.skaffold debug#2173)skaffold debug#2174)skaffold debug#2175)skaffold debugshould allow specifying imagePullPolicy for debug helpers #2191)cmd/debug.go. (Shouldskaffold debugbe configurable per artifact? #2184)skaffold.yamland associated objects? or perhaps just leverage the debug annotations (Provide mechanism to indicate language runtime type for an artifact #2203)