Skip to content

Commit c47d258

Browse files
authored
Merge pull request #37 from digitalocean/pyadagiri/slurp
CON-14275: Remove doks-debug Deployment Exists toleration; add debug-node helper
2 parents fcbb64d + 31ba4fd commit c47d258

3 files changed

Lines changed: 151 additions & 2 deletions

File tree

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ The DOKS team provides this image for use as-is and for transparency as the imag
88

99
# Usage
1010

11+
Prefer the **DaemonSet** when you need debug pods on many nodes, or the ephemeral **`debug-node`** helper when you need access to a single node. Avoid leaving a long-lived `doks-debug` Deployment in the cluster.
12+
13+
## DaemonSet
14+
1115
```bash
1216
kubectl apply -f k8s/daemonset.yaml
1317
```
@@ -18,6 +22,7 @@ This DaemonSet manifest will:
1822
2. Use `hostPID`, `hostIPC`, and `hostNetwork`.
1923
3. Mount the entire host filesystem to `/host` in the containers.
2024
4. Mount the `containerd` socket at `/run/containerd/containerd.sock` from the host into the container.
25+
5. Tolerate all taints (`operator: Exists`) so pods can land on cordoned or specially tainted nodes.
2126

2227
In order to make use of these workloads, you can exec into a pod of choice by name:
2328

@@ -33,6 +38,28 @@ POD_NAME=$(kubectl -n kube-system get pods --field-selector spec.nodeName=${NODE
3338
kubectl -n kube-system exec -it ${POD_NAME} bash
3439
```
3540

41+
Clean up when finished:
42+
43+
```bash
44+
kubectl delete -f k8s/daemonset.yaml
45+
```
46+
47+
## Ephemeral single-node access (`debug-node`)
48+
49+
For short-lived access to one node, use `script/debug-node`. It creates a `doks-debug` Deployment pinned with a `nodeSelector`, execs into the host via `chroot /host`, and deletes the Deployment when you exit.
50+
51+
```bash
52+
./script/debug-node <node-name>
53+
```
54+
55+
The Deployment manifest does **not** include a default catch-all toleration. A long-lived Deployment with `tolerations: [{operator: Exists}]` can reschedule onto draining nodes and block scale-down or upgrades. If you need to reach a tainted or cordoned node for a brief session, pass `--tolerate-all`:
56+
57+
```bash
58+
./script/debug-node --tolerate-all <node-name>
59+
```
60+
61+
Requires `kubectl`, `curl` (if the local manifest is unavailable), and [`yq`](https://github.com/mikefarah/yq).
62+
3663
Once you're in, you have access to the set of tools listed in the `Dockerfile`. This includes:
3764

3865
- [`vim`](https://github.com/vim/vim) - is a greatly improved version of the good old UNIX editor Vi.

k8s/deployment.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ spec:
2222
hostPID: true
2323
hostIPC: true
2424
hostNetwork: true
25-
tolerations:
26-
- operator: Exists
2725
containers:
2826
- name: doks-debug
2927
securityContext:

script/debug-node

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#!/usr/bin/env bash
2+
# Ephemeral node access via a doks-debug Deployment.
3+
# Pins to one node, execs in, and deletes the Deployment on exit.
4+
#
5+
# Usage: debug-node [--tolerate-all] <node-name>
6+
#
7+
# --tolerate-all Inject tolerations: operator: Exists so the pod can land on
8+
# tainted/cordoned nodes. Use only for short-lived sessions;
9+
# long-lived Deployments with this toleration can block drains
10+
# and upgrades.
11+
12+
set -euo pipefail
13+
14+
tolerate_all=false
15+
node_name=""
16+
17+
usage() {
18+
echo "Usage: $(basename "$0") [--tolerate-all] <node-name>"
19+
echo " connect and chroot into the node using an ephemeral doks-debug Deployment"
20+
}
21+
22+
while [[ $# -gt 0 ]]; do
23+
case "$1" in
24+
-h|--help)
25+
usage
26+
exit 0
27+
;;
28+
--tolerate-all)
29+
tolerate_all=true
30+
shift
31+
;;
32+
-*)
33+
echo "Error: unknown option: $1" >&2
34+
usage >&2
35+
exit 1
36+
;;
37+
*)
38+
if [[ -n "$node_name" ]]; then
39+
echo "Error: unexpected argument: $1" >&2
40+
usage >&2
41+
exit 1
42+
fi
43+
node_name="$1"
44+
shift
45+
;;
46+
esac
47+
done
48+
49+
if [[ -z "$node_name" ]]; then
50+
usage >&2
51+
exit 1
52+
fi
53+
54+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
55+
local_manifest="${script_dir}/../k8s/deployment.yaml"
56+
remote_manifest_url="https://raw.githubusercontent.com/digitalocean/doks-debug/refs/heads/master/k8s/deployment.yaml"
57+
58+
deployment_name="doks-debug"
59+
deployment_namespace="kube-system"
60+
61+
cleanup() {
62+
kubectl delete deployment "${deployment_name}" \
63+
--namespace "${deployment_namespace}" \
64+
--ignore-not-found=true
65+
}
66+
trap cleanup EXIT
67+
68+
if [[ -f "$local_manifest" ]]; then
69+
doks_debug_deployment_yaml="$(cat "$local_manifest")"
70+
else
71+
doks_debug_deployment_yaml="$(curl --silent --fail --location "$remote_manifest_url")"
72+
fi
73+
74+
if [[ -z "$doks_debug_deployment_yaml" ]]; then
75+
echo "Error: failed to load the deployment manifest." >&2
76+
exit 1
77+
fi
78+
79+
if ! command -v yq >/dev/null 2>&1; then
80+
echo "Error: yq is required (https://github.com/mikefarah/yq)." >&2
81+
exit 1
82+
fi
83+
84+
modified_yaml="$(
85+
echo "$doks_debug_deployment_yaml" | \
86+
nodeName="$node_name" yq '.spec.template.spec.nodeSelector["kubernetes.io/hostname"] = env(nodeName)'
87+
)"
88+
89+
if [[ "$tolerate_all" == true ]]; then
90+
modified_yaml="$(
91+
echo "$modified_yaml" | \
92+
yq '.spec.template.spec.tolerations = [{"operator": "Exists"}]'
93+
)"
94+
fi
95+
96+
echo "$modified_yaml" | kubectl apply -f -
97+
98+
kubectl wait deployment "${deployment_name}" \
99+
--namespace "${deployment_namespace}" \
100+
--for=condition=Available \
101+
--timeout=120s \
102+
>/dev/null
103+
104+
pod_name="$(
105+
kubectl get pods \
106+
--namespace "${deployment_namespace}" \
107+
-l name=doks-debug \
108+
-o jsonpath='{.items[0].metadata.name}'
109+
)"
110+
111+
if [[ -z "$pod_name" ]]; then
112+
echo "Error: could not find a running pod for the deployment." >&2
113+
exit 1
114+
fi
115+
116+
kubectl wait pod "${pod_name}" \
117+
--namespace "${deployment_namespace}" \
118+
--for=condition=Ready \
119+
--timeout=60s \
120+
>/dev/null
121+
122+
kubectl exec -it "${pod_name}" \
123+
--namespace "${deployment_namespace}" \
124+
-- chroot /host bash

0 commit comments

Comments
 (0)