搞 K8S 运维的时候,偶尔会遇到一个难题,定位到问题出在某个节点上,而由于权限审批,错误配置等等各种原因,没有办法拿到节点的 SSH 权限,无法进入节点命令行进一步排障。
这个时候,就可以用这个黑魔法,通过在 K8S 集群内创建一个特别的 Pod,直接拿到某个节点的 Shell。
1. 创建并调度一个 Pod 到指定的节点,这里我们用 Deployment
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: maint
spec:
replicas: 1
selector:
matchLabels:
app: maint
template:
metadata:
labels:
app: maint
spec:
nodeName: TARGET_NODE_NAME
containers:
- name: maint
image: debian:12
args:
- sleep
- 999999
securityContext:
privileged: true
hostPID: true
注意以下几点:
- 使用
nodeName
调度这个 Pod 到要调试的节点 - 设置
securityContext.privileged
为true
- 设置
hostPID
为true
2. 在 Pod 中执行以下命令
shell
nsenter -t 1 -m -u -n -i bash
nsenter
命令允许在特定命名空间(此处指 Linux 资源隔离命名空间,而非 Kubernetes 命名空间)上执行命令-t 1
参数指定使用 PID 1 的命名空间,因为设置了hostPID: true
,容器内看到的 PID 1 进程就是宿主机的 PID 1 进程-m -u -n -i
复用命名空间的 挂载,UTS,网络 和 IPC
执行该命令后,就能够拿到一个在节点上运行的 bash
进程,进行进一步工作了。