k8s-nodeshell实现
对于node我们一般会禁止ssh登录,但有时又不得不登录到node节点查看和debug,这时就可以通过node-shell的方式获得对应node的root shell~
安装:
https://github.com/kvaps/kubectl-node-shell/tree/master
使用curl进行安装。
1 2 3
| curl -LO https://github.com/kvaps/kubectl-node-shell/raw/master/kubectl-node_shell chmod +x ./kubectl-node_shell sudo mv ./kubectl-node_shell /usr/local/bin/kubectl-node_shell
|
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # 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
# Use stdin cat /etc/passwd | kubectl node-shell <node> -- sh -c 'cat > /tmp/passwd'
# Run oneliner script kubectl node-shell <node> -- sh -c 'cat /tmp/passwd; rm -f /tmp/passwd'
|
原理:
其实就是一个bash脚本,所做的就是起一个特权容器,然后使用nsenter进入到宿主机,从而获取到root shell。
nsenter就是namespace enter的意思,它可以进入到目标程序所在的namespace中,因此可以用来调试容器程序。我们都知道目前存在的几个namespace,比如网络,用户,pid等,nsenter都有对应的参数可以指定,从而进入该namespace。
对于容器中有bash程序的场景,我们通过exec的方式就能进入容器内部,此时并不需要nsenter,但是对于那些没有bash程序的,就没法通过exec进入容器了,我们首先通过docker inspect获得对应容器的pid,然后通过nsenter进入utc、net、和pid namespace,这样我们就能使用宿主机的调试工具,比如tcpdump,ip等命令。
扩展
创建nodeshell的daemonset:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| apiVersion: apps/v1 kind: DaemonSet metadata: name: nsenter-daemonset namespace: default labels: app: nsenter spec: selector: matchLabels: app: nsenter template: metadata: labels: app: nsenter spec: hostPID: true hostNetwork: true tolerations: - key: "CriticalAddonsOnly" operator: "Exists" - effect: "NoExecute" operator: "Exists" containers: - name: nsenter image: docker.io/library/alpine securityContext: privileged: true stdin: true stdinOnce: true tty: true command: [ "nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "bash", "-l" ] resources: limits: cpu: "100m" memory: "256Mi" requests: cpu: "100m" memory: "256Mi" nodeSelector: kubernetes.io/hostname: node1
|
创建nodeshell的pod:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| kubectl --namespace= xxx run --image docker.io/library/alpine --restart=Never '--overrides={ "spec": { "nodeName": "node1", #更改nodename "hostPID": true, "hostNetwork": true, "containers": [ { "securityContext": { "privileged": true }, "image": "docker.io/library/alpine", "name": "nsenter", "stdin": true, "stdinOnce": true, "tty": true, "command": [ "nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "bash", "-l" ], "resources": { "limits": { "cpu": "100m", "memory": "256Mi" }, "requests": { "cpu": "100m", "memory": "256Mi" } } } ], "tolerations": [ { "key": "CriticalAddonsOnly", "operator": "Exists" }, { "effect": "NoExecute", "operator": "Exists" } ] } }' --labels= -t -i nsenter-h3m5fy
|