Skip to content

Commit

Permalink
Rework debug docs (#3875)
Browse files Browse the repository at this point in the history
Separate API and metadata description.
  • Loading branch information
briandealwis authored Mar 26, 2020
1 parent 2a6f2ad commit eaf5b88
Showing 1 changed file with 164 additions and 41 deletions.
205 changes: 164 additions & 41 deletions docs/content/en/docs/workflows/debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,30 @@ aliases: [/docs/how-tos/debug]
`skaffold debug` acts like `skaffold dev`, but it configures containers in pods
for debugging as required for each container's runtime technology.
The associated debugging ports are exposed and labelled so that they can be port-forwarded to the
local machine. Helper metadata is also added to allow IDEs to detect the debugging
configuration parameters.

## How It Works

`skaffold debug` examines the built artifacts to determine the underlying runtime technology.
Any Kubernetes manifest that references these artifacts are transformed to enable the runtime technology's
debugging functions.

`skaffold debug` uses a set of heuristics to identify the runtime technology.
The Kubernetes manifests are transformed on-the-fly such that the on-disk representations
are untouched.

Each Pod will have an `debug.cloud.google.com/config` annotation with a JSON object
describing the debug configurations for the pod's containers (linebreaks for readability):
```
debug.cloud.google.com/config={
"<containerName>":{"runtime":"<runtimeId>",...},
"<containerName>":{"runtime":"<runtimeId>",...},
}
```
local machine. IDEs can use Skaffold's events to automatically configure debug sessions.

For example the following annotation indicates that the container named `web` is a Go application
that is being debugged by a headless Delve session on port `56268` (linebreaks for readability):
```
debug.cloud.google.com/config={
"web":{
"artifact":"gcr.io/random/image",
"runtime":"go",
"ports":{"dlv":56268},
"workingDir":"/some/path"}}
```
## How It Works

`artifact` is the corresponding artifact's image name in the `skaffold.yaml`.
`runtime` is the language runtime detected.
`ports` is a list of debug ports keyed by the language runtime debugging protocol.
`workingDir` is the working directory (if not an empty string).
`skaffold debug` examines the built artifacts to determine the underlying language runtime technology.
Kubernetes manifests that reference these artifacts are transformed on-the-fly to enable the
language runtime's debugging functionality. These transforms add or alter environment variables
and entrypoints, and more.

Some language runtimes require additional support files to enable debugging.
For these languages, a special set of [runtime-specific images](https://github.com/GoogleContainerTools/container-debug-support)
are configured as _init-containers_ to populate a shared-volume that is mounted into
each of the appropriate containers. These images are hosted at `gcr.io/gcp-dev-tools/duct-tape`.


### Supported Language Runtimes

Debugging is currently supported for Go, Java (and JVM languages), NodeJS, and Python.
Debugging is currently supported for:
- Go (runtime ID: `go`)
- NodeJS (runtime ID: `nodejs`)
- Java and JVM languages (runtime ID: `jvm`)
- Python (runtime ID: `python`)

Note that many debuggers may require additional information for the location of source files.
We are looking for ways to identify this information and to pass it back if found.

#### Go

Expand All @@ -67,9 +44,12 @@ Go-based applications are configured to run under [Delve](https://github.com/go-
- Go applications should be built without optimizations, so your build should be capable of building with
`-gcflags='all=-N -l'`. Skaffold [_Profiles_]({{< relref "/docs/environment/profiles.md" >}}) are a useful option.

Note for users of [VS Code's debug adapter for Go](https://github.com/Microsoft/vscode-go): Delve seems
to treat the source location for headless launches as being relative to `/go`. The following
[remote launch configuration](https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code#remote-debugging) was useful:
Note for users of [VS Code's debug adapter for Go](https://github.com/Microsoft/vscode-go):
the source location must be set to the remote source location _during compilation_. For example, the
`golang` images, which are [often used in multi-stage builds](https://github.com/GoogleContainerTools/skaffold/tree/master/examples/getting-started/Dockerfile),
copy the source code to `/go`. The following
[remote launch configuration](https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code#remote-debugging)
works in this case:
```json
{
"name": "Skaffold Debug",
Expand Down Expand Up @@ -108,6 +88,149 @@ The DAP is supported by Visual Studio Code, [Eclipse LSP4e](https://projects.ecl
[and other editors and IDEs](https://microsoft.github.io/debug-adapter-protocol/implementors/tools/).
DAP is not yet supported by JetBrains IDEs like PyCharm.

## IDE Support via Events and Metadata

`debug` provides additional support for IDEs to detect the debuggable containers and to determine
appropriate configuration parameters.

### Workload Annotations

Each transformed workload object carries a `debug.cloud.google.com/config` annotation with
a JSON object describing the debug configurations for the pod's containers (linebreaks for readability):
```
debug.cloud.google.com/config={
"<containerName>":{"runtime":"<runtimeId>",...},
"<containerName>":{"runtime":"<runtimeId>",...},
}
```

For example the following annotation indicates that the container named `web` is a Go application
that is being debugged by a headless Delve session on port `56268` (linebreaks for readability):
```
debug.cloud.google.com/config={
"web":{
"artifact":"gcr.io/random/image",
"runtime":"go",
"ports":{"dlv":56268},
"workingDir":"/some/path"}}
```

`artifact` is the corresponding artifact's image name in the `skaffold.yaml`.
`runtime` is the language runtime detected (one of: `go`, `jvm`, `nodejs`, `python`).
`ports` is a list of debug ports keyed by the language runtime debugging protocol.
`workingDir` is the working directory (if not an empty string).


### API: Events

Each debuggable container being started or stopped raises a _debug-container-event_ through
Skaffold's event mechanism ([gRPC](../references/api/grpc/#debuggingcontainerevent),
[REST](../references/api/swagger/#/SkaffoldService/Events)).

<details>
<summary>`/v1/events` stream of `skaffold debug` within `examples/jib`</summary>

In this example, we do a `skaffold debug`, and then kill the deployed pod. The deployment starts a new pod. We get a terminated event for the container for the killed pod.

```json
{
"result": {
"timestamp": "2020-02-05T03:27:30.114354Z",
"event": {
"debuggingContainerEvent": {
"status": "Started",
"podName": "web-f6d56bcc5-6csgs",
"containerName": "web",
"namespace": "default",
"artifact": "skaffold-jib",
"runtime": "jvm",
"debugPorts": {
"jdwp": 5005
}
}
},
"entry": "Debuggable container started pod/web-f6d56bcc5-6csgs:web (default)"
}
}
```

</details>



### API: State

The API's _state_ ([gRPC](../references/api/grpc/#skaffoldservice), [REST](../references/api/swagger/#/SkaffoldService/GetState)) also includes a list of debuggable containers.

<details>
<summary>The `/v1/state` listing debugging containers</summary>

```json
{
"buildState": {
"artifacts": {
"skaffold-jib": "Complete"
}
},
"deployState": {
"status": "Complete"
},
"forwardedPorts": {
"5005": {
"localPort": 5005,
"remotePort": 5005,
"podName": "web-f6d56bcc5-6csgs",
"containerName": "web",
"namespace": "default",
"portName": "jdwp",
"resourceType": "pod",
"resourceName": "web-f6d56bcc5-6csgs",
"address": "127.0.0.1"
},
"8080": {
"localPort": 8080,
"remotePort": 8080,
"namespace": "default",
"resourceType": "service",
"resourceName": "web",
"address": "127.0.0.1"
},
"8081": {
"localPort": 8081,
"remotePort": 8080,
"podName": "web-f6d56bcc5-6csgs",
"containerName": "web",
"namespace": "default",
"resourceType": "pod",
"resourceName": "web-f6d56bcc5-6csgs",
"address": "127.0.0.1"
}
},
"statusCheckState": {
"status": "Not Started"
},
"fileSyncState": {
"status": "Not Started"
},
"debuggingContainers": [
{
"status": "Started",
"podName": "web-f6d56bcc5-6csgs",
"containerName": "web",
"namespace": "default",
"artifact": "skaffold-jib",
"runtime": "jvm",
"debugPorts": {
"jdwp": 5005
}
}
]
}

```

</details>


## Limitations

Expand All @@ -118,7 +241,7 @@ DAP is not yet supported by JetBrains IDEs like PyCharm.
`skaffold debug` requires being able to examine and alter the
command-line used in the container entrypoint. This transformation
will not work with images that use intermediate launch scripts or
binaries. For example, `debug` cannot work with an image produced
binaries. For example, `debug` currently does not work with an image produced
by the Cloud Native Buildpacks builder as it uses a `launcher`
binary to run commands that are specified in a set of configuration
files.
Expand Down

0 comments on commit eaf5b88

Please sign in to comment.