如何DEBUG一个正在运行的POD
有些命令例如strace/ptrace需要更高系统权限,因此用上面的kubectl debug命令没用办法使用(目前kubectl debug命令还不支持设置securitycontext),所以可以使用下面的办法。K8S会使用debug镜像在POD里起一个EphemeralContainer,和目标container共享linux namespace,但是注意他们不共享rootfs和mountf
参考文档
https://kubernetes.io/zh-cn/docs/tasks/debug/debug-application/debug-running-pod/
原理
K8S会使用debug镜像在POD里起一个EphemeralContainer,和目标container共享linux namespace,但是注意他们不共享rootfs和mountfs,两者的文件系统是独立的。
想访问目标container的文件系统,需要在EphemeralContainer先cd /proc/1/root/,然后才能看到对方的文件系统,如图访问es的/tmp:
开启方法:
注:K8S1.22以下需要手动开启,1.23默认开启
step1:在master node的/etc/kubernetes/manifests/kube-apiserver.yaml
- –feature-gates=RemoveSelfLink=false,EphemeralContainers=true
step2: 在slave node上
sed -i ‘s/“/ --feature-gates=EphemeralContainers=true”/2’ /var/lib/kubelet/kubeadm-flags.env
systemctl restart kubelet
使用命令进入交互界面:
kubectl debug -it --image= -n --target=
以测试POD为例:
kubectl debug -it function-test-testdaily-XXXX --image=harbor.tsingj.local/re_release/test_debug:v2.4.0rc14-1131-gf2d8127c0 -n chenwei1 --target=function-test
操作举例:
- 抓包/监控流量:网络操作必须使用root用户,用test_debug可以su root, 输入密码qwer1234.
iftop
tcpdump
2)jstack等jdk工具
镜像必须和被debug的container里的用户相同:privpy,然后镜像里的jdk最好与产品版本一致。
高权限调试方法
有些命令例如strace/ptrace需要更高系统权限,因此用上面的kubectl debug命令没用办法使用(目前kubectl debug命令还不支持设置securitycontext),所以可以使用下面的办法
方法1:起一个POD共享k8s node的namespace
Step1: 查找你需要debug的POD所在node,例如:
开发 > Debug a running pod > image2023-4-10_17-55-20.png
Step2: 使用我们的test_debug镜像在这个node上起一个pod然后exec -it进入这个pod,su root,找到你想debug的进程号再使用strace:
kubectl apply -f node_pod.yaml -n chenwei1
kubectl exec -it -n chenwei1 node-debugger – /bin/bash
su root
ps -efH | grep privpy
使用的yaml文件如下,需要改下nodeName为step1中所查得node
apiVersion: v1
kind: Pod
metadata:
name: node-debugger
spec:
containers:
- image: harbor.tsingj.local/re_release/test_debug:v2.4.0rc14-1131-gf2d8127c0
imagePullPolicy: IfNotPresent
name: debugger
resources: {}
stdin: true
tty: true
command: [ "/bin/bash", "-c", "sleep 6000s" ]
securityContext:
privileged: true
allowPrivilegeEscalation: true
volumeMounts:
- mountPath: /host
name: host-root
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-97p2b
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
hostIPC: true
hostNetwork: true
hostPID: true
nodeName: k8sdeploy-node315
preemptionPolicy: PreemptLowerPriority
priority: 1
priorityClassName: low-priority
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- hostPath:
path: /
type: ""
name: host-root
- name: kube-api-access-97p2b
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
方法2: 由于kubectl debug不支持加上securityContext,可以使用go 脚本来加上securityContext,代码如下,但是还没有调通,可能是目前的k8s版本还不支持。
package main
import (
"context"
"fmt"
"log"
"os"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
logger := log.New(os.Stdout, "[Debug] - ", log.Lshortfile)
if len(os.Args) != 4 {
panic("expected three args")
}
podNamespace := os.Args[1]
podName := os.Args[2]
kubeconfigPath := os.Args[3]
// Create the client
client, err := getKubernetesClients(kubeconfigPath)
if err != nil {
panic(fmt.Errorf("could not create client: %w", err))
}
ctx := context.Background()
// Get the Pod
pod, err := client.CoreV1().Pods(podNamespace).Get(ctx, podName, metav1.GetOptions{})
logger.Println(pod.Name)
logger.Println(pod.Spec)
if err != nil {
panic(fmt.Errorf("could not get pod: %w", err))
}
// Add a new ephemeral container
trueValue := true
ephemeralContainer := corev1.EphemeralContainer{
TargetContainerName: "demo",
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
Name: "debug",
Image: "quay.io/iovisor/bpftrace:latest",
TTY: true,
SecurityContext: &corev1.SecurityContext{
Privileged: &trueValue,
AllowPrivilegeEscalation: &trueValue,
},
},
}
pod.Spec.EphemeralContainers = append(pod.Spec.EphemeralContainers, ephemeralContainer)
pod, err = client.CoreV1().Pods(pod.Namespace).UpdateEphemeralContainers(ctx, pod.Name, pod, metav1.UpdateOptions{})
if err != nil {
panic(fmt.Errorf("could not add ephemeral container: %w", err))
}
}
func getKubernetesClients(path string) (kubernetes.Interface, error) {
cfg, err := clientcmd.BuildConfigFromFlags("", path)
if err != nil {
return nil, err
}
client, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, err
}
return client, nil
}
更多推荐
所有评论(0)