1.1 什么是临时容器?
临时容器与其他容器的不同之处在于,它缺少对资源或执行的保证,并且永远不会自动重启,因此不适用于构建应用程序。临时容器使用与常规容器相同的 Container.Spec字段进行描述,但许多字段是不允许使用的。
- 临时容器没有端口配置,因此像 ports,livenessProbe,readinessProbe 这样的字段是不允许的。
- Pod 资源分配是不可变的,因此 resources 配置是不允许的。
临时容器是使用 API 中的一种特殊的 ephemeralcontainers
处理器进行创建的, 而不是直接添加到 pod.spec
段,因此无法使用 kubectledit
来添加一个临时容器。
与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。
1.2 临时容器的用途
当由于容器崩溃或容器镜像不包含调试实用程序而导致 kubectlexec
无用时,临时容器对于交互式故障排查很有用。
1.3 开启特性支持临时容器
需要开启支持临时容器的特性:
修改kube-apiserver.yaml、kube-scheduler.yaml、kubelet配置。
[root@xianchaomaster1]# cat/etc/kubernetes/manifests/kube-apiserver.yaml apiVersion: v1 kind: Pod metadata: annotations: kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint:192.168.40.180:6443 creationTimestamp: null labels: component: kube-apiserver tier: control-plane name: kube-apiserver namespace: kube-system spec: containers: - command: - kube-apiserver - --advertise-address=192.168.40.180 ……… - --feature-gates=RemoveSelfLink=false - --feature-gates=EphemeralContainers=true ……… #新增加--feature-gates=EphemeralContainers=true字段 [root@xianchaomaster1]# cat/etc/kubernetes/manifests/kube-scheduler.yaml apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: component:kube-scheduler tier: control-plane name: kube-scheduler namespace: kube-system spec: containers: - command: - kube-scheduler ---authentication-kubeconfig=/etc/kubernetes/scheduler.conf ---authorization-kubeconfig=/etc/kubernetes/scheduler.conf ---bind-address=192.168.40.180 - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true - --feature-gates=EphemeralContainers=true #新增加--feature-gates=EphemeralContainers=true字段 [root@xianchaomaster1]# cat /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS="--feature-gates=EphemeralContainers=true" [root@xianchaonode1 ~]# cat /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS="--feature-gates=EphemeralContainers=true" #修改之后重启k8s控制节点和工作节点的kubelet [root@xianchaomaster1]# systemctl restart kubelet [root@xianchaonode1 ~]# systemctl restart kubelet #查看kube-system名称空间pod,都是running说明修改正常 [root@xianchaomaster1 test]# kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE calico-kube-controllers-6949477b58-thdxp 1/1 Running 0 22d calico-node-t9bxc 1/1 Running 0 46d calico-node-xr4jj 1/1 Running 0 46d coredns-7f89b7bc75-lb9vn 1/1 Running 0 22d coredns-7f89b7bc75-w4m6r 1/1 Running 0 22d etcd-xianchaomaster1 1/1 Running 0 46d fluentd-elasticsearch-9jbn2 1/1 Running 0 22d fluentd-elasticsearch-n7cc8 1/1 Running 0 22d kube-apiserver-xianchaomaster1 1/1 Running 0 64m kube-controller-manager-xianchaomaster1 1/1 Running 0 46d kube-proxy-8nfx7 1/1 Running 0 46d kube-proxy-zwjjx 1/1 Running 0 46d kube-scheduler-xianchaomaster1 1/1 Running 0 29m
2、使用临时容器
参考:https://kubernetes.io/zh/docs/tasks/debug-application-cluster/debug-running-pod/#ephemeral-container
#创建一个部署tomcat的pod [root@xianchaonode1 ~]# docker load -i xianchao_tomcat.tar.gz [root@xianchaomaster1]# cat pod-tomcat.yaml apiVersion: v1 kind: Pod metadata: name: tomcat-test namespace: default labels: app: tomcat spec: containers: - name: tomcat-java ports: - containerPort: 8080 image:xianchao/tomcat-8.5-jre8:v1 imagePullPolicy:IfNotPresent [root@xianchaomaster1]# kubectl apply -f pod-tomcat.yaml [root@xianchaomaster1]# kubectl get pods NAME READY STATUS RESTARTS AGE tomcat-test 1/1 Running 0 21m #创建临时容器 [root@xianchaomaster1]# kubectl debug -it tomcat-test--image=busybox:1.28 --target=tomcat-java Defaulting debug container name to debugger-6m2s8. If you don't see a command prompt, try pressing enter. / #ps -ef | grep tomcat 1 root 0:09/usr/lib/jvm/java-1.8-openjdk/jre/bin/java-Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager-Djdk.tls.ephemeralDHKeySize=2048-Djava.protocol.handler.pkgs=org.apache.catalina.webresources-Dorg.apache.catalina.security.SecurityListener.UMASK=0027-Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar-Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat-Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrapstart #查看tomcat-test这个pod是否已经有临时容器 [root@xianchaomaster1 test]# kubectl describe pods tomcat-test Name: tomcat-test Namespace: default Containers: tomcat-java: Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-qbgqq(ro) Ephemeral Containers: debugger-6m2s8: State: Terminated Reason: Completed Exit Code: 0 Started: Sun, 18 Jul 2021 11:32:34 +0800 Finished: Sun, 18 Jul 2021 11:34:50 +0800 Ready: False Restart Count: 0 Environment: <none> Mounts: <none>
3、kubectl raw更新临时容器
[root@xianchaomaster1]# kubectl delete -f pod-tomcat.yaml [root@xianchaomaster1]# kubectl apply -f pod-tomcat.yaml [root@xianchaomaster1]# kubectl get pods NAME READY STATUS RESTARTS AGE tomcat-test 1/1 Running 0 21m [root@xianchaomaster1]# cat a.json { "apiVersion": "v1", "kind":"EphemeralContainers", "metadata":{ "name": "tomcat-test" }, "ephemeralContainers": [{ "command": [ "sh" ], "image": "busybox", "imagePullPolicy": "IfNotPresent", "name":"debugger", "stdin": true, "tty":true, "targetContainerName": "tomcat-java", "terminationMessagePolicy": "File" }] } [root@xianchaomaster1]# kubectl replace --raw/api/v1/namespaces/default/pods/tomcat-test/ephemeralcontainers -f a.json #显示如下: {"kind":"EphemeralContainers","apiVersion":"v1","metadata":{"name":"tomcat-test","namespace":"default","selfLink":"/api/v1/namespaces/default/pods/tomcat-test/ephemeralcontainers","uid":"e058969c-f610-4d58-83e5-28f872f16d54","resourceVersion":"548549","creationTimestamp":"2021-07-18T04:43:43Z"},"ephemeralContainers":[{"name":"debugger","image":"busybox","command":["sh"],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"IfNotPresent","stdin":true,"tty":true,"targetContainerName":"tomcat-java"}]}
此时,可以直接attach到临时容器上去:
[root@xianchaomaster1]# kubectl attach -it -c debuggertomcat-test If you don't see a command prompt, try pressing enter. / # ps -ef | grep tomcat 1 root 0:05/usr/lib/jvm/java-1.8-openjdk/jre/bin/java-Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager-Djdk.tls.ephemeralDHKeySize=2048-Djava.protocol.handler.pkgs=org.apache.catalina.webresources-Dorg.apache.catalina.security.SecurityListener.UMASK=0027-Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar-Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat-Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrapstart / #exit
调试完成退出临时容器之后,这个容器会被销毁,无法再次attach:
4、总结
临时容器特别适合包含主容器剥离出来的一些调试工具,在需要的时候临时注入到目标pod中。有个比较尴尬的问题,就是在pod中添加临时容器之后,目前还无法删除,同时如果这时候临时容器已经退出,会导致无法再次attach,也不会被拉起(临时容器不支持probe什么的),相关的issue:https://github.com/kubernetes/kubernetes/issues/84764
5、补充
目前临时容器最大的坑是无法删除,如果attach了临时容器,然后退出了容器主进程(和前面示例中展示的那样),会导致这个容器无法再attach,也无法重新启动。此时,如果要重复上述步骤再次进行调试,需要新创建一个临时容器,同时还需要保留老的配置,否则k8s会拒绝新的配置:
[root@xianchaomaster1]# cat a.json { "apiVersion": "v1", "kind":"EphemeralContainers", "metadata":{ "name": "tomcat-test" }, "ephemeralContainers": [ { "command": [ "sh" ], "image": "busybox", "imagePullPolicy": "IfNotPresent", "name":"debugger", "stdin": true, "tty":true, "targetContainerName": "tomcat-java", "terminationMessagePolicy": "File" }, {"command": [ "sh" ], "image": "busybox", "imagePullPolicy": "IfNotPresent", "name":"debugger1", "stdin": true, "tty":true, "targetContainerName": "tomcat-java", "terminationMessagePolicy": "File" } ] }
配置文件需要做这样的修改,再新增一个临时容器。重新修改后pod的状态(describe结果):
[root@xianchaomaster1]# kubectl replace --raw/api/v1/namespaces/default/pods/tomcat-test/ephemeralcontainers -f a.json
看tomcat-test详细信息,可以看到新增加了一个debugger1临时容器