調(diào)試 Kubernetes 最簡單方法
本文介紹了 Kubectl debug 和臨時容器等調(diào)試方法。
作者:Martin Heinz 翻譯:Bach (K8sMeetup)
校對:星空下的文仔 來源:K8sMeetup社區(qū)
kubectl logs 或者 kubectl describe pod 便足以找到問題所在,但有時候,一些問題會特別難查。這種情況下,大家可能會嘗試使用 kubectl exec,但有時候這樣也還不行,因為 Distroless 等容器甚至不允許通過 SSH 進入 shell。那么,如果以上所有方法都失敗了,我們要怎么辦?kubectl debug。這是不久前添加的一個新命令(v1.18),允許調(diào)試正在運行的 pod。它會將名為 EphemeralContainer(臨時容器)的特殊容器注入到問題 Pod 中,讓我們查看并排除故障。kubectl debug 看起來非常不錯,但要使用它需要臨時容器,臨時容器到底是什么?container。但與普通容器不同的是,臨時容器不用于構(gòu)建應(yīng)用程序,而是用于檢查。我們不會在創(chuàng)建 Pod 時定義它們,而使用特殊的 API 將其注入到運的行 Pod 中,來運行命令并檢查 Pod 環(huán)境。除了這些不同,臨時容器還缺少一些基本容器的字段,例如 ports、resources。kubectl debug,那么如何啟用臨時容器的功能門?這取決于集群設(shè)置。例如,現(xiàn)在使用kubeadm啟動創(chuàng)建集群,那么可以使用以下集群配置來啟用臨時容器:apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.20.2
apiServer:
extraArgs:
feature-gates: EphemeralContainers=true
# File: config.yaml
# Run: kind create cluster --config ./config.yaml --name kind --image=kindest/node:v1.20.2
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
EphemeralContainers: true
nodes:
- role: control-plane
~ $ kubectl explain pod.spec.ephemeralContainers
KIND: Pod
VERSION: v1
RESOURCE: ephemeralContainers <[]Object>
DESCRIPTION:
List of ephemeral containers run in this pod....
...
kubectl debug。從簡單的例子開始:~ $ kubectl run some-app --image=k8s.gcr.io/pause:3.1 --restart=Never
~ $ kubectl debug -it some-app --image=busybox --target=some-app
Defaulting debug container name to debugger-tfqvh.
If you don't see a command prompt, try pressing enter.
/ #
# From other terminal...
~ $ kubectl describe pod some-app
...
Containers:
some-app:
Container ID: containerd://60cc537eee843cb38a1ba295baaa172db8344eea59de4d75311400436d4a5083
Image: k8s.gcr.io/pause:3.1
Image ID: k8s.gcr.io/pause@sha256:f78411e19d84a252e53bff71a4407a5686c46983a2c2eeed83929b888179acea
...
Ephemeral Containers:
debugger-tfqvh:
Container ID: containerd://12efbbf2e46bb523ae0546b2369801b51a61e1367dda839ce0e02f0e5c1a49d6
Image: busybox
Image ID: docker.io/library/busybox@sha256:ce2360d5189a033012fbad1635e037be86f23b65cfd676b436d0931af390a2ac
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 15 Mar 2021 20:33:51 +0100
Ready: False
Restart Count: 0
Environment: <none>
Mounts: <none>
some-app 的 Pod 來進行“調(diào)試”。然后針對這個 Pod 運行 kubectl debug,指定 busybox 為臨時容器的鏡像,并作為原始容器的目標。此外,還需要包括 -it 參數(shù),以便我們立即附加到容器獲得 shell 會話。kubectl debug 是非常強大的工具,但有時向 Pod 添加一個容器還不足以獲取 Pod 的另一個容器中運行的應(yīng)用程序相關(guān)信息。當故障容器不包括必要的調(diào)試工具甚至 shell 時,可能就是這種情況。在這種情況下,我們可以使用 Process Sharing(進程共享)來使用注入的臨時容器檢查 Pod 的原有容器。spec.shareProcessNamespace 設(shè)置為 true,并將一個臨時容器注入其中。這樣有點麻煩,尤其是需要調(diào)試多個 Pod 或容器,亦或者需要重復(fù)執(zhí)行該操作時。幸運的是,kubectl debug 可以使用 --share-processes 做到:~ $ kubectl run some-app --image=nginx --restart=Never
~ $ kubectl debug -it some-app --image=busybox --share-processes --copy-to=some-app-debug
Defaulting debug container name to debugger-tkwst.
If you don't see a command prompt, try pressing enter.
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
38 101 0:00 nginx: worker process
39 root 0:00 sh
46 root 0:00 ps ax
~ $ cat /proc/8/root/etc/nginx/conf.d/default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
...
--share-processes 還包括了 --copy-to=new-pod-name,這是因為我們需要創(chuàng)建一個新的 Pod,其名稱由該 flag 指定。如果我們從另一個終端列出正在運行的 Pod,我們將看到以下內(nèi)容:# From other terminal:
~ $ kubectl get pods
NAME READY STATUS RESTARTS AGE
some-app 1/1 Running 0 23h
some-app-debug 2/2 Running 0 20s
~ $ kubectl get pod some-app-debug -o json | jq .spec.shareProcessNamespace
true
kubectl debug:~ $ kubectl run distroless-python --image=martinheinz/distroless-python --restart=Never
~ $ kubectl exec -it distroless-python -- /bin/sh
# id
/bin/sh: 1: id: not found
# ls
/bin/sh: 2: ls: not found
# env
/bin/sh: 3: env: not found
#
...
kubectl debug -it distroless-python --image=praqma/network-multitool --target=distroless-python -- sh
Defaulting debug container name to debugger-rvtd4.
If you don't see a command prompt, try pressing enter.
/ # ping localhost
PING localhost(localhost (::1)) 56 data bytes
64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from localhost (::1): icmp_seq=2 ttl=64 time=0.044 ms
64 bytes from localhost (::1): icmp_seq=3 ttl=64 time=0.027 ms
praqma/network-multitool 將臨時容器注入到 Pod 中,該鏡像包含了 curl、ping、telnet 等工具,現(xiàn)在我們可以進行所有必要的故障排除。~ $ kubectl run distroless-python --image=martinheinz/distroless-python --restart=Never
~ $ kubectl debug -it distroless-python --image=busybox --share-processes --copy-to=distroless-python-debug
Defaulting debug container name to debugger-l692h.
If you don't see a command prompt, try pressing enter.
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 /usr/bin/python3.5 sleep.py # Original container is just sleeping forever
14 root 0:00 sh
20 root 0:00 ps ax
/ # cat /proc/8/root/app/sleep.py
import time
print("sleeping for 1 hour")
time.sleep(3600)
kubectl debug 以及 --share-processes --copy-to=...,它創(chuàng)建了一個新的 Pod,帶有額外的臨時容器,可以訪問所有進程。當我們列出正在運行的進程時,能看到應(yīng)用程序容器的進程有 PID 8,可以用它來探索文件和環(huán)境。為此,我們需要通過 /proc/<PID>/... 目錄,這個例子中是 /proc/8/root/app/...。~ $ kubectl get pods
NAME READY STATUS RESTARTS AGE
crashing-app 0/1 CrashLoopBackOff 1 8s
~ $ kubectl debug crashing-app -it --copy-to=crashing-app-debug --container=crashing-app -- sh
If you don't see a command prompt, try pressing enter.
# id
uid=0(root) gid=0(root) groups=0(root)
#
...
# From another terminal
~ $ kubectl get pods
NAME READY STATUS RESTARTS AGE
crashing-app 0/1 CrashLoopBackOff 3 2m7s
crashing-app-debug 1/1 Running 0 16s
kubectl debug 允許通過創(chuàng)建 Pod 來調(diào)試節(jié)點,該 Pod 將在指定節(jié)點上運行,節(jié)點的根文件系統(tǒng)安裝在 /root 目錄中。我們甚至可以用 chroot 訪問主機二進制文件,這本質(zhì)上充當了節(jié)點的 SSH 連接:~ $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane,master 25h v1.20.2
~ $ kubectl debug node/kind-control-plane -it --image=ubuntu
Creating debugging pod node-debugger-kind-control-plane-hvljt with container debugger on node kind-control-plane.
If you don't see a command prompt, try pressing enter.
root@kind-control-plane:/# chroot /host
# head kind/kubeadm.conf
apiServer:
certSANs:
- localhost
- 127.0.0.1
extraArgs:
feature-gates: EphemeralContainers=true
runtime-config: ""
apiVersion: kubeadm.k8s.io/v1beta2
clusterName: kind
controlPlaneEndpoint: kind-control-plane:6443
node/... 作為參數(shù)顯式運行 kubectl debug 以訪問我們集群的節(jié)點。在那之后,當連接到Pod后,我們使用 chroot /host 突破 chroot,并完全進入主機。最后,為了驗證是否真的可以看到主機上的所有內(nèi)容,我們了查看一部分的 kubeadm.conf,最終看到我們在文章開頭配置的內(nèi)容 feature-gates: EphemeralContainers=true。推薦閱讀:
不是你需要中臺,而是一名合格的架構(gòu)師(附各大廠中臺建設(shè)PPT)
企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案
論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?
企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!
評論
圖片
表情
