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.