github.com/GoogleContainerTools/skaffold/v2@v2.13.2/docs-v2/design_proposals/debug-events.md (about) 1 # Notify when debuggable containers are started and terminated 2 3 * Author(s): Brian de Alwis (@briandealwis) 4 * Design Shepherd: Nick Kubala (@nkubala) 5 * Date: 2019-10-24 6 * Status: *Implemented* (#3609, #3645) 7 * Related: #2211 8 9 Note: implemented but there were some minor name changes. 10 11 ## Background 12 13 Cloud Code for IntelliJ and VS Code currently launch `skaffold debug --port-forward` to start 14 an application in debugging mode. `debug` modifies the podspecs to explicitly expose the debug port used 15 by the underlying language runtime via `containerPort` definitions. Skaffold monitors the cluster 16 and initiated forwards to ports on any newly-started containers, and raises events once the 17 forwards are established. The IDEs establish debug launch configurations by examining these 18 port-forward events for ports with specific names to (e.g., `jdwp` for Java/JVM, 19 `devtools` for NodeJS, or `dap` for connections using the _Debug Adapter Protocol_). 20 When a new debuggable container is created, Skaffold will 21 attempt to forward the remote debug port, which should result in a port-forward event, and thus 22 spare the IDEs from having to actively watch the cluster. 23 24 But relying strictly on port-forward events carries some risk. Although the likelihood of 25 a port-name clash is low, the IDE may require additional configuration information to establish 26 a debugging connection. For example, there may be no indication of the underlying project’s 27 location in the file-system, nor the relative path in the container. 28 29 Although such information is published by `skaffold debug` via pod annotations, obtaining this 30 information would require that the IDEs actively track new pods and containers. This tracking would 31 duplicate functionality already being performed by Skaffold, and also requiring this functionality to be 32 re-implemented in each IDE. 33 34 This design proposal recommends that Skaffold instead also watch and issue events when debuggable 35 containers are started and terminated. 36 37 ---- 38 ## Design 39 40 This design proposes that Skaffold issue events to inform the IDEs of the following conditions: 41 42 - The appearance of a container that is debuggable. This event will provide: 43 - the namespace 44 - the pod ID 45 - the container ID 46 - the contents of the `debug.cloud.google.com/config` configuration block for the container 47 (a JSON object) including (! indicates new items) 48 - the language runtime type (`go`, `jvm`, `nodejs`, `python`) 49 - ! the image name (which should allow cross-referencing with the `skaffold.yaml`) 50 - the port(s) 51 - ! the container image's working directory 52 - ! (optional) the container image's _remote root_ for source file resolving 53 54 - The disappearance of a container that was debuggable. This event will provide: 55 - the namespace 56 - the pod ID 57 - the container ID 58 - the contents of the `debug.cloud.google.com/config` configuration block for the container 59 (a JSON object) including (! indicates new items) 60 - the language runtime type (`go`, `jvm`, `nodejs`, `python`) 61 - ! the corresponding artifact's `name` (which should allow cross-referencing with the `skaffold.yaml`) 62 - the port(s) 63 - ! the container image's working directory 64 - ! (optional) the container image's _remote root_ for source file resolving 65 66 Skaffold will also maintain state and report on the set of debuggable containers. 67 68 With this information, the IDE should be able to: 69 70 - Identify the corresponding artifact within the `skaffold.yaml` 71 - Identify the corresponding artifact from a port-forward event by correlating the 72 remote port with the debug port from the previously-raised debug event 73 - Establish new debug launch configurations with the forwarded port, 74 and the local source location, and any other necessary information 75 - Tear down existing debug launch configurations when a container is terminated 76 - (*In the future*, *if necessary*) Request port-forward of the debug port for the 77 namespace/pod/container/port on-demand 78 79 ### Example 80 81 #### Events in Action 82 ```json 83 { 84 "result": { 85 "timestamp": "2019-10-23T18:50:38.916931Z", 86 "event": { 87 "deployEvent": { 88 "status": "In Progress" 89 } 90 }, 91 "entry": "Deploy started" 92 } 93 } 94 { 95 "result": { 96 "timestamp": "2019-10-23T18:50:39.629826Z", 97 "event": { 98 "deployEvent": { 99 "status": "Complete" 100 } 101 }, 102 "entry": "Deploy complete" 103 } 104 } 105 { 106 "result": { 107 "timestamp": "2019-10-23T18:50:41.004396Z", 108 "event": { 109 "debugEvent": { 110 "status": "Started", 111 "podName": "npm", 112 "containerName": "web", 113 "namespace": "default", 114 "runtime": "nodejs", 115 "configuration": "{\"name\":\"gcr.io/artifact/name/from/skaffold.yaml\",\"ports\":{\"devtools\":9229},\"runtime\":\"nodejs\",\"workingDir\":\"/app\"}" 116 } 117 }, 118 "entry": "Debuggable container started pod/npm:web (default)" 119 } 120 } 121 { 122 "result": { 123 "timestamp": "2019-10-23T18:50:41.004551Z", 124 "event": { 125 "portEvent": { 126 "localPort": 3000, 127 "remotePort": 3000, 128 "podName": "npm", 129 "containerName": "web", 130 "namespace": "default", 131 "resourceType": "pod", 132 "resourceName": "npm" 133 } 134 }, 135 "entry": "Forwarding container web to local port 3000" 136 } 137 } 138 { 139 "result": { 140 "timestamp": "2019-10-23T18:50:41.004792Z", 141 "event": { 142 "portEvent": { 143 "localPort": 9229, 144 "remotePort": 9229, 145 "podName": "npm", 146 "containerName": "web", 147 "namespace": "default", 148 "portName": "devtools", 149 "resourceType": "pod", 150 "resourceName": "npm" 151 } 152 }, 153 "entry": "Forwarding container web to local port 9229" 154 } 155 } 156 ``` 157 158 #### State in Action 159 160 ```json 161 $ curl -s localhost:50052/v1/state | jq . 162 { 163 "buildState": { 164 "artifacts": { 165 "gcr.io/k8s-skaffold/skaffold-jib": "Complete" 166 } 167 }, 168 "deployState": { 169 "status": "Complete" 170 }, 171 "statusCheckState": { 172 "status": "Not Started" 173 }, 174 "fileSyncState": { 175 "status": "Not Started" 176 }, 177 "debuggingContainers": [ 178 { 179 "status": "Started", 180 "podName": "web-6d7c9db467-gqr5x", 181 "containerName": "web", 182 "namespace": "default", 183 "runtime": "jvm", 184 "configuration": "{\"name\":\"gcr.io/artifact/name/from/skaffold.yaml\",\"ports\":{\"jdwp\":5005},\"runtime\":\"jvm\",\"workingDir\":\"/app\"}" 185 } 186 ] 187 } 188 ``` 189 190 ### Open Issues/Questions 191 192 **\<Why is a new Debug Event necessary?\>** 193 194 One alternative explored was to piggy-back the debug information into the existing port-forward events. 195 This design was eliminated as: 196 197 - There are some language runtimes, like .NET Core, that do not use debug ports and instead 198 require a `kubectl exec` to launch a process in the remote container. 199 - Port-forwards may be dropped and re-established 200 201 There may also be a desire for the IDEs to selectively initiate port-forwards on an as-needed 202 basis. This may be useful for large microservice deployments. Indeed the debugging podspec 203 transformations could be applied on-the-fly too. 204 205 ## Implementation plan 206 207 The idea here is that `skaffold debug` internally configures a watcher that looks for and notifies 208 of pods with debuggable containers, similar to how the [port-forwarding manager](https://github.com/GoogleContainerTools/skaffold/blob/main/pkg/skaffold/kubernetes/portforward/pod_forwarder.go) 209 listens for pods or services. 210 211 1. `skaffold debug` will set a `DebugMode` option to `true`. This value will be used in 212 `SkaffoldRunner.Dev()` to install the debug container watch manager. 213 1. Add a new `DebugEvent` type to the protobuf definitions. The status field will be one 214 of `"Started"` or `"Terminated"`. 215 1. Add new debuggable container state to the general state. 216 1. Generalize the port-forward manager or create a new parallel debug watcher to notify 217 of pod events. 218 219 ___ 220 ## Integration test plan 221 222 Tests will need to verify that pod- and container-start successfully raise debugging _Started_ events, 223 and container termination and pod-deletion raises _Terminated_ events.