除錯Kubernetes工作負載的最簡單方法 - Martin

banq發表於2021-05-28

對於每個使用Kubernetes的開發人員和DevOps工程師來說, 除錯容器化的工作負載和Pod都是日常工作。通常很簡單,kubectl logs或者kubectl describe pod足以找到某些問題的根源,但是有些問題很難找到。
在這些情況下,您可能會嘗試使用,kubectl exec但甚至可能還不夠用,因為某些容器(例如Distroless)甚至不包含您可以透過SSH進入的外殼。那麼,如果以上所有方法都失敗了,我們還剩下什麼呢?...
 

可能會有更好的方法...
有時您需要抓住更大的錘子,或者只是使用更合適的工具來完成手頭的任務。
如果要在Kubernetes上除錯工作負載,則該工具將是kubectl debug,這是不久前新增的新命令(v1.18),可用於除錯正在執行的Pod。
它將名為EphemeralContainer的特殊型別的容器注入有問題的Pod中,從而使您可以四處尋找問題並進行故障排除。對於前面描述的情況或在互動除錯更可取或更有效的任何其他情況下,這可能非常有用。
因此,kubectl debug看起來像要走的路,但是要使用它,我們將需要短暫的臨時Ephemeral容器,那麼這些到底是什麼?
臨時容器是類似於正常容器的Pod子資源。與常規容器不同,臨時容器不是用於架構應用,而是用於檢查它們。
我們不是在Pod的建立時定義它們,而是使用特殊的API將它們注入到執行Pod中以執行故障排除命令並檢查Pod的環境。
除了這些差異之外,臨時容器還缺少基本容器的某些欄位,例如ports或resources。
但是,為什麼我們需要它們?我們不能只使用基本容器嗎?好吧,您不能將容器新增到Pod中,因為它們應該是一次性的(或換句話說,可以隨時刪除並重新建立),這可能使得很難對難以重現需要檢查Pod的bug進行故障排除。這就是將臨時容器新增到API的原因:它們使您可以將容器新增到現有的容器中,從而更容易檢查正在執行的容器。
考慮到臨時容器是Pod規範的一部分,而Pod規範是Kubernetes的核心,那麼您(可能)還沒有聽說過它呢?這些幾乎都是未知功能的原因是,臨時容器處於Alpha早期階段,這意味著預設情況下未啟用它們。此階段的資源和功能可能會發生重大變化,或者在以後的Kubernetes版本中會被完全刪除。因此,使用它們,你必須在kubelet使用Feature Gates明確啟用它們。
 

配置Feature Gates
我們已經確定要嘗試kubectl debug,那麼如何啟用臨時容器功能?好吧,這取決於您的叢集設定。例如,如果您kubeadm用於啟動建立叢集,則可以使用以下ClusterConfiguration啟用臨時容器:

apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.20.2
apiServer:
  extraArgs:
    feature-gates: EphemeralContainers=true


但是,在以下示例中,出於簡化和測試目的,我們將使用KinD(Docker中的Kubernetes)叢集,這也允許我們指定要啟用的功能門。因此,要建立我們的遊樂場叢集:

# 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

在叢集執行的情況下,我們應驗證其確實有效。檢視是否已應用此配置的最簡單方法是檢查Pod API,該API現在應在常規容器旁邊包括ephemeralContainers部分:

~ $ 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<


我們首先啟動一個Pod,Pod名為 some-app,以便我們可以“debug”某些東西。然後kubectl debug,我們針對此Pod執行,將其指定busybox為臨時容器的映象Image,以及作為原始容器的目標。此外,我們還包含-it引數,以便我們立即附加到容器並獲得Shell會話。
在上面的程式碼段中,您還可以看到,如果在執行Pod之後kubectl debug我們對其進行了描述,則其描述將包括“臨時容器”部分,其中包含我們之前指定為命令選項的值。
更詳細點選標題。

相關文章