Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add X-mode for debugging minimal systems #51

Merged
merged 1 commit into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ sudo mv ./kubectl-node_shell /usr/local/bin/kubectl-node_shell
# Get standard bash shell
kubectl node-shell <node>

# Use X-mode (mount /host, and do not enter host namespace)
kubectl node-shell -x <node>

# Execute custom command
kubectl node-shell <node> -- echo 123

Expand All @@ -38,4 +41,38 @@ cat /etc/passwd | kubectl node-shell <node> -- sh -c 'cat > /tmp/passwd'
kubectl node-shell <node> -- sh -c 'cat /tmp/passwd; rm -f /tmp/passwd'
```

## X-mode

X-mode can be useful for debugging minimal systems that do not have a built-in shell (eg. Talos).
Here's an example of how you can debug the network for a rootless kube-apiserver container without a filesystem:

```bash
kubectl node-shell -x <node>

# Download crictl
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.28.0/crictl-v1.28.0-linux-amd64.tar.gz -O- | \
tar -xzf- -C /usr/local/bin/

# Setup CRI endpoint
export CONTAINER_RUNTIME_ENDPOINT=unix:///host/run/containerd/containerd.sock

# Find your container
crictl ps | grep kube-apiserver
#3ff4626a9f10e e7972205b6614 6 hours ago Running kube-apiserver 0 215107b47bd7e kube-apiserver-talos-rzq-nkg

# Find pid of the container
crictl inspect 3ff4626a9f10e | grep pid
# "pid": 2152,
# "pid": 1
# "type": "pid"
# "getpid",
# "getppid",
# "pidfd_open",
# "pidfd_send_signal",
# "waitpid",

# Go to network namespace of the pid, but keep mount namespace of the debug container
nsenter -t 2152 -n
```

*You need to be able to start privileged containers for that.*
33 changes: 27 additions & 6 deletions kubectl-node_shell
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
set -e

kubectl=kubectl
version=1.7.0
version=1.8.0
generator=""
node=""
nodefaultctx=0
nodefaultns=0
container_cpu="${KUBECTL_NODE_SHELL_POD_CPU:-100m}"
container_memory="${KUBECTL_NODE_SHELL_POD_MEMORY:-256Mi}"
volumes="[]"
volume_mounts="[]"
x_mode=0
labels="${KUBECTL_NODE_SHELL_LABELS}"

if [ -t 0 ]; then
Expand Down Expand Up @@ -55,6 +58,12 @@ while [ $# -gt 0 ]; do
kubectl="$kubectl --namespace=${key##*=}"
shift
;;
-x)
x_mode=1
volumes='[{"hostPath":{"path":"/","type":""},"name":"host-root"}]'
volume_mounts='[{"mountPath":"/host","name":"host-root"}]'
shift
;;
--)
shift
break
Expand Down Expand Up @@ -106,16 +115,26 @@ fi

# Build the container command
if [ $# -gt 0 ]; then
cmd="[ $cmd_start $cmd_arg_prefix"
if [ "$x_mode" -eq 1 ]; then
cmd='['
else
cmd="[ $cmd_start $cmd_arg_prefix,"
fi
c=""
while [ $# -gt 0 ]; do
cmd="$cmd, \"$(echo "$1" | \
cmd="${cmd}${c} \"$(echo "$1" | \
awk '{gsub(/["\\]/,"\\\\&");gsub(/\x1b/,"\\u001b");printf "%s",last;last=$0"\\n"} END{print $0}' \
)\""
c=,
shift
done
cmd="$cmd ]"
else
cmd="[ $cmd_start $cmd_default ]"
if [ "$x_mode" = 1 ]; then
cmd='null'
else
cmd="[ $cmd_start $cmd_default ]"
fi
fi

overrides="$(
Expand All @@ -137,13 +156,15 @@ cat <<EOT
"resources": {
"limits": { "cpu": "${container_cpu}", "memory": "${container_memory}" },
"requests": { "cpu": "${container_cpu}", "memory": "${container_memory}" }
}
},
"volumeMounts": $volume_mounts
}
],
"tolerations": [
{ "key": "CriticalAddonsOnly", "operator": "Exists" },
{ "effect": "NoExecute", "operator": "Exists" }
]
],
"volumes": $volumes
}
}
EOT
Expand Down