Skip to content

Add support for Windows nodes #45

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 23, 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# kubectl node-shell
*(formerly known as **kubectl-enter**)*

Start a root shell in the node's host OS running.
Start a root shell in the node's host OS running. Uses an alpine pod with nsenter for Linux nodes and a [HostProcess pod](https://kubernetes.io/docs/tasks/configure-pod-container/create-hostprocess-pod/) with PowerShell for Windows nodes.

![demo](https://gist.githubusercontent.com/kvaps/2e3d77975a844654ec297893e21a0829/raw/c778a8405ff8c686e4e807a97e9721b423e7208f/kubectl-node-shell.gif)

Expand Down
83 changes: 44 additions & 39 deletions kubectl-node_shell
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
set -e

kubectl=kubectl
version=1.5.5
version=1.7.0
generator=""
node=""
nodefaultctx=0
nodefaultns=0
cmd='[ "nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--"'
container_cpu="${KUBECTL_NODE_SHELL_POD_CPU:-100m}"
container_memory="${KUBECTL_NODE_SHELL_POD_MEMORY:-256Mi}"
labels="${KUBECTL_NODE_SHELL_LABELS}"

if [ -t 0 ]; then
tty=true
else
Expand Down Expand Up @@ -68,11 +71,42 @@ while [ $# -gt 0 ]; do
esac
done

if [ -z "$node" ]; then
echo "Please specify node name"
exit 1
fi

# Set the default context and namespace to avoid situations where the user switch them during the build process
[ "$nodefaultctx" = 1 ] || kubectl="$kubectl --context=$(${kubectl} config current-context)"
[ "$nodefaultns" = 1 ] || kubectl="$kubectl --namespace=$(${kubectl} config view --minify --output 'jsonpath={.contexts..namespace}')"

# Check the node and retrieve the node OS label
os="$($kubectl get node $node -o jsonpath="{.metadata.labels.kubernetes\.io/os}" || exit 1)"

# Set pod configuration per operating system
if [ "$os" = "windows" ]; then
image="${KUBECTL_NODE_SHELL_IMAGE_WINDOWS:-mcr.microsoft.com/powershell}"
name="pwsh"
pod="${name}-$(env LC_ALL=C tr -dc a-z0-9 </dev/urandom | head -c 6)"
# pwsh has to be launched via cmd.exe because of how containerd 1.6 handles the mount of the container filesystem
# see https://kubernetes.io/docs/tasks/configure-pod-container/create-hostprocess-pod/#volume-mounts
cmd_start='"cmd.exe", "/c", "%CONTAINER_SANDBOX_MOUNT_POINT%\\Program Files\\PowerShell\\latest\\pwsh.exe", "-nol", "-wd", "C:\\"'
cmd_arg_prefix=', "-Command"'
cmd_default=''
security_context='{"privileged":true,"windowsOptions":{"hostProcess":true,"runAsUserName":"NT AUTHORITY\\SYSTEM"}}'
else # If the OS isn't windows, assume linux
image="${KUBECTL_NODE_SHELL_IMAGE:-docker.io/library/alpine}"
name="nsenter"
pod="${name}-$(env LC_ALL=C tr -dc a-z0-9 </dev/urandom | head -c 6)"
cmd_start='"nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid"'
cmd_arg_prefix=', "--"'
cmd_default=', "bash", "-l"'
security_context='{"privileged":true}'
fi

# Build the container command
if [ $# -gt 0 ]; then
cmd="[ $cmd_start $cmd_arg_prefix"
while [ $# -gt 0 ]; do
cmd="$cmd, \"$(echo "$1" | \
awk '{gsub(/["\\]/,"\\\\&");gsub(/\x1b/,"\\u001b");printf "%s",last;last=$0"\\n"} END{print $0}' \
Expand All @@ -81,63 +115,34 @@ if [ $# -gt 0 ]; then
done
cmd="$cmd ]"
else
cmd="$cmd, \"bash\", \"-l\" ]"
fi

if [ -z "$node" ]; then
echo "Please specify node name"
exit 1
cmd="[ $cmd_start $cmd_default ]"
fi

image="${KUBECTL_NODE_SHELL_IMAGE:-docker.io/library/alpine}"
pod="nsenter-$(env LC_ALL=C tr -dc a-z0-9 </dev/urandom | head -c 6)"

# Check the node
$kubectl get node "$node" >/dev/null || exit 1

container_cpu="${KUBECTL_NODE_SHELL_POD_CPU:-100m}"
container_memory="${KUBECTL_NODE_SHELL_POD_MEMORY:-256Mi}"
labels="${KUBECTL_NODE_SHELL_LABELS}"

overrides="$(
cat <<EOT
cat <<EOT
{
"spec": {
"nodeName": "$node",
"hostPID": true,
"hostNetwork": true,
"containers": [
{
"securityContext": {
"privileged": true
},
"securityContext": $security_context,
"image": "$image",
"name": "nsenter",
"name": "$name",
"stdin": true,
"stdinOnce": true,
"tty": $tty,
"command": $cmd,
"resources": {
"limits": {
"cpu": "${container_cpu}",
"memory": "${container_memory}"
},
"requests": {
"cpu": "${container_cpu}",
"memory": "${container_memory}"
}
"limits": { "cpu": "${container_cpu}", "memory": "${container_memory}" },
"requests": { "cpu": "${container_cpu}", "memory": "${container_memory}" }
}
}
],
"tolerations": [
{
"key": "CriticalAddonsOnly",
"operator": "Exists"
},
{
"effect": "NoExecute",
"operator": "Exists"
}
{ "key": "CriticalAddonsOnly", "operator": "Exists" },
{ "effect": "NoExecute", "operator": "Exists" }
]
}
}
Expand Down