如何在没有 ssh 的情况下从主节点访问 k8s 工作节点?
How can i access a k8s worker node from a master node without ssh?
我想构建一个 python 脚本来访问 kubernetes 工作节点,列出网络接口并捕获所选接口的流量(例如使用 tcpdump),然后将 pcap 文件存储在主节点。
我想知道是否可以在没有 ssh 的情况下从我的主节点访问工作节点? (也许直接调用 k8s-apiserver ?)
如果 ssh 是访问工作节点的唯一方式,我如何在不输入工作人员密码(用于身份验证)的情况下建立连接。
或者也许还有其他方法可以做到这一点?
连接节点的一种方法,当 SSH 不是一个选项时,将启动一些特权容器,它将访问您的节点文件系统,禁用 pid 命名空间隔离。
假设我有一些节点“infra1”
$> kubectl get nodes
infra1 Ready infra 728d v1.21.6
我可以使用:
$ kubectl debug node/infra1 -it --image=busybox
Creating debugging pod node-debugger-infra1-s46g6 with container debugger on node infra1.
If you don't see a command prompt, try pressing enter.
/ #
/ # chroot /host
root@infra1:/#
root@infra1:/# crictl ps | head -2
CONTAINER IMAGE CREATED STATE
NAME ATTEMPT POD ID
a36863efe2a2e 3fb5cabb64693 4 minutes ago Running
/host
是一个“卷”,与该调试容器共享我的主机文件系统。使用 chroot,您现在可以在节点运行时工作。
$ k get pods
NAME READY STATUS RESTARTS AGE
node-debugger-infra1-g5nwg 0/1 Error 0 71s
node-debugger-infra1-s46g6 1/1 Running 0 55s
实际上,创建一个 Pod 就完成了,如下所示:
apiVersion: v1
kind: Pod
metadata:
annotations:
kubernetes.io/psp: hostaccess
name: node-debugger-infra1-s46g6
namespace: default
spec:
containers:
- image: busybox
...
volumeMounts:
- mountPath: /host
name: host-root
...
dnsPolicy: ClusterFirst
enableServiceLinks: true
hostIPC: true
hostNetwork: true
hostPID: true
nodeName: infra1
nodeSelector:
kubernetes.io/os: linux
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- operator: Exists
volumes:
- hostPath:
path: /
type: ""
name: host-root
...
回答您的 follow-up 问题,关于 caliXXX 接口。这些是特定于 calico SDN 的,尽管相同的评论可能适用于其他实现:没有简单的方法来解析来自那些的 pods IP。
但是我们可以检查 pods 配置,找出它们使用的接口:
# crictl pods
...
b693b9ff6487c 3 hours ago Ready controller-6b78bff7d9-5b7vr metallb-system 2 (default)
# crictl inspectp b693b9ff6487c | jq '.info.cniResult'
{
"Interfaces": {
"cali488d4aeb0e6": {
"IPConfigs": null,
"Mac": "",
"Sandbox": ""
},
"eth0": {
"IPConfigs": [
{
"IP": "10.233.105.55",
"Gateway": ""
}
],
"Mac": "",
"Sandbox": ""
},
"lo": {
"IPConfigs": [
{
"IP": "127.0.0.1",
"Gateway": ""
},
{
"IP": "::1",
"Gateway": ""
}
],
"Mac": "00:00:00:00:00:00",
"Sandbox": "/var/run/netns/cni-55322514-e37a-2913-022a-9f7488df8ca5"
}
},
"DNS": [
{},
{}
],
"Routes": null
}
然后,解析给定 IP 的接口名称,我们可以这样:
# MATCH_IP="10\.233\.105\.55"
# crictl pods | awk '/Ready/{print }' | while read pod
do
crictl inspectp $pod | grep $MATCH_IP >/dev/null 2>&1 || continue
echo found pod $pod
crictl inspectp $pod \
| jq '.info.cniResult.Interfaces | with_entries(select(.key|match("cali"))) | to_entries[] | .key'
break
done
found pod b693b9ff6487c
"cali488d4aeb0e6"
我想构建一个 python 脚本来访问 kubernetes 工作节点,列出网络接口并捕获所选接口的流量(例如使用 tcpdump),然后将 pcap 文件存储在主节点。
我想知道是否可以在没有 ssh 的情况下从我的主节点访问工作节点? (也许直接调用 k8s-apiserver ?) 如果 ssh 是访问工作节点的唯一方式,我如何在不输入工作人员密码(用于身份验证)的情况下建立连接。
或者也许还有其他方法可以做到这一点?
连接节点的一种方法,当 SSH 不是一个选项时,将启动一些特权容器,它将访问您的节点文件系统,禁用 pid 命名空间隔离。
假设我有一些节点“infra1”
$> kubectl get nodes
infra1 Ready infra 728d v1.21.6
我可以使用:
$ kubectl debug node/infra1 -it --image=busybox
Creating debugging pod node-debugger-infra1-s46g6 with container debugger on node infra1.
If you don't see a command prompt, try pressing enter.
/ #
/ # chroot /host
root@infra1:/#
root@infra1:/# crictl ps | head -2
CONTAINER IMAGE CREATED STATE
NAME ATTEMPT POD ID
a36863efe2a2e 3fb5cabb64693 4 minutes ago Running
/host
是一个“卷”,与该调试容器共享我的主机文件系统。使用 chroot,您现在可以在节点运行时工作。
$ k get pods
NAME READY STATUS RESTARTS AGE
node-debugger-infra1-g5nwg 0/1 Error 0 71s
node-debugger-infra1-s46g6 1/1 Running 0 55s
实际上,创建一个 Pod 就完成了,如下所示:
apiVersion: v1
kind: Pod
metadata:
annotations:
kubernetes.io/psp: hostaccess
name: node-debugger-infra1-s46g6
namespace: default
spec:
containers:
- image: busybox
...
volumeMounts:
- mountPath: /host
name: host-root
...
dnsPolicy: ClusterFirst
enableServiceLinks: true
hostIPC: true
hostNetwork: true
hostPID: true
nodeName: infra1
nodeSelector:
kubernetes.io/os: linux
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- operator: Exists
volumes:
- hostPath:
path: /
type: ""
name: host-root
...
回答您的 follow-up 问题,关于 caliXXX 接口。这些是特定于 calico SDN 的,尽管相同的评论可能适用于其他实现:没有简单的方法来解析来自那些的 pods IP。
但是我们可以检查 pods 配置,找出它们使用的接口:
# crictl pods
...
b693b9ff6487c 3 hours ago Ready controller-6b78bff7d9-5b7vr metallb-system 2 (default)
# crictl inspectp b693b9ff6487c | jq '.info.cniResult'
{
"Interfaces": {
"cali488d4aeb0e6": {
"IPConfigs": null,
"Mac": "",
"Sandbox": ""
},
"eth0": {
"IPConfigs": [
{
"IP": "10.233.105.55",
"Gateway": ""
}
],
"Mac": "",
"Sandbox": ""
},
"lo": {
"IPConfigs": [
{
"IP": "127.0.0.1",
"Gateway": ""
},
{
"IP": "::1",
"Gateway": ""
}
],
"Mac": "00:00:00:00:00:00",
"Sandbox": "/var/run/netns/cni-55322514-e37a-2913-022a-9f7488df8ca5"
}
},
"DNS": [
{},
{}
],
"Routes": null
}
然后,解析给定 IP 的接口名称,我们可以这样:
# MATCH_IP="10\.233\.105\.55"
# crictl pods | awk '/Ready/{print }' | while read pod
do
crictl inspectp $pod | grep $MATCH_IP >/dev/null 2>&1 || continue
echo found pod $pod
crictl inspectp $pod \
| jq '.info.cniResult.Interfaces | with_entries(select(.key|match("cali"))) | to_entries[] | .key'
break
done
found pod b693b9ff6487c
"cali488d4aeb0e6"