06 - 优雅的在K8S中Debug容器和主机

点击这里,参考原文。


本文主要介绍一个 K8S 故障排错新手段:kubectl debug

1 kubectl debug 起源

    开发者喜欢在生产部署中使用极致精简的容器镜像,这也是容器技术中的一个最佳实践。这种精简主义有很多好处,而且在大多数情况下运行良好,但是一旦需要在生产中排除一些故障时,这就变得很困难了,因为精简后的容器普遍缺失常用的排障工具,有些甚至连 bash/sh 解释器都没有。


    kubectl debug 是一款 k8s pod 诊断工具,能够帮助进行 Pod 的排障诊断。在 k8s v1.16 ~ v1.22 中是 Alpha 状态,默认关闭。从 k8s v1.23 开始这项功能才逐渐成熟,并成为 Beta 状态,默认开启。


2 kubectl debug 工作原理

    我们知道,容器本质上是带有 cgroup 资源限制和 namespace 隔离的一组进程。因此,我们只要启动一个进程,并且让这个进程加入到目标容器的各种 namespace 中,这个进程就能“进入容器内部”(注意引号),与容器中的进程 “看到” 相同的根文件系统、虚拟网卡、进程空间了 —— 这也正是 docker exec 和 kubectl exec 等命令的运行方式。


    现在的状况是,我们不仅要“进入容器内部”,还希望带一套工具集进去帮忙排查问题。那么,想要高效管理一套工具集,又要可以跨平台,最好的办法就是把工具本身都打包在一个容器镜像当中。接下来,我们只需要通过这个“工具镜像” 启动容器,再指定这个容器加入目标容器的的各种 namespace,自然就实现了 “携带一套工具集进入容器内部”。


3 kubectl debug 怎么用

3.1 开启功能

在 V1.23 及以上版本中,该功能默认开启。针对 1.23 以下的 K8S 版本,需要通过以下方式,手动开启。

第一步:控制面开启 EphemeralContainers featureGate.
进入 master 节点,编辑 /etc/kubernetes/manifests/ 下的 kube-apiserver.yaml,kube-controller-manager.yaml 及 kube-scheduler.yaml,在 command 部分添加 - --feature-gates=EphemeralContainers=true;


第二步:Kubelet 服务开启该功能
在节点上编辑 /var/lib/kubelet/kubeadm-flags.env,添加 --feature-gates=EphemeralContainers=true;或者设置KUBELET_EXTRA_ARGS=“–feature-gates=EphemeralContainers=true”


第三步:重启 Kubelet
systemctl restart kubelet


那么,我们有了Ephemeral Containers能做哪些事情呢?

3.2 使用方式

3.2.1 POD Troubleshooting

最直接简单的就是对一个pod进行调试命令如下:

kubectl debug mypod -it --image=busybox

默认情况下,用户不指定临时容器名称的话,debug容器名称就由kubectl自动生成一个唯一id的名称。如果用户需要自己指定容器名称,则使用:

kubectl debug mypod -c debugger --image=busybox

有了临时容器除了日常debug功能外,我们可以扩展出很多新花样的玩法。比如批量跑某个命名空间下的安全扫描的脚本而不用干扰原容器。

for pod in $(kubectl get -o name pod); 
do
    kubectl debug --image security/pod_scanner -p $pod /sanner.sh
done

3.2.2 POD Troubleshooting by Copy

对于没有开启Ephemeral Containers特性的集群,我们就只能通过复制模式来调试容器。它的原理是复制一个指定pod的新容器,并将debug作为sidecar跟随新容器一起启动(也就是重新创建一个pod,并将debug作为sidecar跟随新容器一起启动)。通过这种方式也能达到曲线救国的目的。此种方式的几个参数还是挺有意思:

–copy-to 指定新pod的名称
–replace=true 是否删除原容器
–same-node=true 是否调度到和原容器一样的node上
–share-processes=true 是否共享容器pid空间

例如,我们就可以启动一个跟需要调试pod一样配置的debug容器如下:

kubectl debug mypod -it 
--container=debug 
--image=busybox 
--copy-to=my-debugger 
--same-node=true 
--share-processes=true 

3.2.3 Node Troubleshooting

对!你没看错!利用Ephemeral Containers还能对Worker节点进行调试。当以节点为目标调用时,kubectl debug 将创建一个带有node名称的pod,并且调度到该节点。同时该容器还具备了hostIPC、hostNetwork和hostPID这些特权模式。不可思议的是Worker节点的根文件系统还被mount到了debug容器下的/host目录下。

直接执行这个命令就能debug主机:

kubectl debug node/mynode -it --image=busybox

3.3 Debug镜像

工欲善其事,必先利其器。不管怎样我们都需要一套工具完善的debug镜像,在处理问题时能够得心应手。虽然网上也有不少debug镜像,不过都还是不如自己构建来的畅快。

这里分享一个Debug镜像的Dockerfile,大家可以根据需要进行修改:

[root@master-01 test]# cat Dockerfile-debug 
FROM golang:alpine as grpcurl
RUN apk update && apk add --virtual build-dependencies git && apk add bash curl jq && go get -u github.com/fullstorydev/grpcurl && go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
FROM alpine:latest
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories && apk update && apk add --no-cache vim bash tcpdump curl wget strace mysql-client iproute2 redis jq iftop tzdata tar nmap bind-tools htop && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN wget -O /usr/bin/httpstat https://github.com/davecheney/httpstat/releases/download/v1.0.0/httpstat-linux-amd64-v1.0.0 && chmod +x /usr/bin/httpstat
COPY --from=grpcurl  /go/bin/grpcurl /usr/bin/grpcurl
ENV TZ=Asia/Shanghai LC_ALL=C.UTF-8 LANG=C.UTF-8 LANGUAGE=C.UTF-8
ENTRYPOINT [ "/bin/bash" ]

你可能感兴趣的:(k8s小知识,kubernetes,容器,云原生,运维,docker)