# Debugging using a copy of the Pod 有時候,Pod 的設定選項會使某些情況下的排查變得困難。例如,如果 container image 不包含 shell,或者應用程式在啟動時崩潰,就無法使用 `kubectl exec` 來排查 container。在這些情況下,可以使用 `kubectl debug` 創建一個 Pod 的副本,並更改設定值以便進行除錯。 ## Copying a Pod while adding a new container 當您的應用程式正在運行但行為不符合預期時,添加一個新 Container 可能會很有用,因為這樣可以向 Pod 添加額外的除錯工具。 例如,您的應用程式 container images 可能基於 `busybox` 構建,但您需要一些 `busybox` 中未包含的除錯工具。您可以使用 `kubectl run` 模擬這種情況: ```! $ kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d ``` 運行此命令以創建一個名為 `myapp-debug` 的 `myapp` 副本,並添加一個新的 Ubuntu container 進行除錯: ```! $ kubectl debug myapp -it --image=ubuntu --share-processes --copy-to=myapp-debug ``` 執行結果 : ```! Defaulting debug container name to debugger-bzgnv. If you don't see a command prompt, try pressing enter. root@myapp-debug:/# ``` - 如果沒有使用 `--container` 標誌選擇 container 名稱,`kubectl debug` 會自動生成一個 container 名稱。 - `myapp`,要排除故障的 Pod 名稱。 - `-i` 標誌使 `kubectl debug` 默認連接到新 container。您可以通過指定 `--attach=false` 來防止這種情況發生。如果會話被斷開連接,可以使用 `kubectl attach` 重新連接。 - `-t`,為 container 分配一個虛擬終端(TTY),使您能夠與 container交互。 - `--image=''`, debug container 使用的 Container image. - `--share-processes` 允許這個 Pod 中的 container 查看其他 container 中的 processes。要了解更多有關其工作原理的信息,請參閱 [Share Process Namespace between Containers in a Pod](https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/)。 - `--copy-to=''`,將原始 Pod `myapp` 複製為一個新的 Pod,名稱為` myapp-debug`。 使用完畢後,別忘了清理 debugging Pod: ``` $ kubectl delete pod myapp myapp-debug ``` ## Copying a Pod while changing its command 有時候更改 container 的命令是很有用的,例如添加 debugging flag 或應用程式崩潰時。 要模擬應用程式崩潰,使用 `kubectl run` 創建一個立即退出的 container : ```! $ kubectl run --image=busybox:1.28 myapp -- false ``` 您可以使用 `kubectl describe pod myapp` 看到這個 container 正在崩潰: ``` Containers: myapp: Image: busybox:1.28 ... Args: false State: Waiting Reason: CrashLoopBackOff Last State: Terminated Reason: Error Exit Code: 1 ``` 您可以使用 `kubectl debug` 創建這個 Pod 的副本,並將命令更改為交互式 shell: ```! $ kubectl debug myapp -it --copy-to=myapp-debug --container=myapp -- sh ``` 執行結果 : ```! If you don't see a command prompt, try pressing enter. / # ``` 現在您有一個交互式的 shell,可以用來執行檢查文件系統路徑或手動執行 container command 等任務。 :::info - 若要更改特定 container 預設執行的命令,您必須使用 `--container` 指定其名稱,否則 `kubectl debug` 會創建一個新的 container 來執行您指定的命令。 - `-i` 標誌使 `kubectl debug` 默認連接到 container。您可以通過指定 `--attach=false` 來防止這種情況。如果會話被斷開連接,可以使用 `kubectl attach` 重新連接。 ::: 使用完畢後,別忘了清理 debugging Pod: ``` $ kubectl delete pod myapp myapp-debug ``` ## Copying a Pod while changing container images 在某些情況下,您可能需要將出現異常行為的 Pod 從其正常的 production container images 更改為包含除錯版本或附加工具的映像。 例如,使用 `kubectl run` 創建一個 Pod: ```! $ kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d ``` 現在使用 `kubectl debug` 創建副本並將其 container image 更改為 Ubuntu: ```! $ kubectl debug myapp --copy-to=myapp-debug --set-image=*=ubuntu ``` `--set-image` 的語法使用與 `kubectl set image` 相同的 `container_name=image` 語法。`*=ubuntu` 表示將所有 containers 的 image 更改為 Ubuntu。 完成後,別忘了清理除錯用的 Pod: ```! $ kubectl delete pod myapp myapp-debug ``` ## Debugging Profiles 當使用 `kubectl debug` 透過除錯 Pod 來對節點進行除錯,或通過 ephemeral container 對 Pod 進行除錯,或者使用 Pod 副本時,可以使用 `--profile` 標誌對它們套用除錯設定檔。通過套用設定檔,可以設置特定的屬性,如 `securityContext`,以適應不同的情境。 可用的設定檔如下: Profile | 描述 --- | --- `legacy` | 一組與 1.22 行為向後相容的屬性 `general` | 為每次除錯過程提供合理的一組通用屬性 `baseline` | 一組與 [PodSecurityStandard baseline policy](https://kubernetes.io/docs/concepts/security/pod-security-standards/#baseline) 相容的屬性 `restricted` | 一組與 [PodSecurityStandard restricted policy](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted) 相容的屬性 `netadmin` | 包含一組網路管理員權限的屬性 `sysadmin` | 包含一組系統管理員(root)權限的屬性集 如果您未指定 `--profile`,則會默認使用 `legacy` 配置檔,但計劃在不久的將來棄用它。因此,建議使用其他配置檔,例如 `general`。 假設您創建一個 Pod 並對其進行除錯。首先,創建一個名為 `myapp` 的 Pod 作為示例: ```! $ kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d ``` 接著,使用 ephemeral container 對該 Pod 進行除錯。如果 ephemeral container 需要具有權限,您可以使用 `sysadmin` 設定檔: ```! $ kubectl debug -it myapp --image=busybox:1.28 --target=myapp --profile=sysadmin ``` 執行結果 : ``` Targeting container "myapp". If you don't see processes from this container it may be because the container runtime doesn't support this feature. Defaulting debug container name to debugger-zdxhp. If you don't see a command prompt, try pressing enter. / # ``` 在 container 內運行以下命令來檢查 ephemeral container process 的 capabilities : ``` $ grep Cap /proc/$$/status ``` 執行結果 : ``` CapInh: 0000000000000000 CapPrm: 000001ffffffffff CapEff: 000001ffffffffff CapBnd: 000001ffffffffff CapAmb: 0000000000000000 ``` 這意味著通過應用 `sysadmin` 設定檔,container process 被授予作為 privileged container 的完整能力。查看有關 [capabilities](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container) 的更多細節。 您也可以檢查該 ephemeral container 是否被創建為 privileged container: ```! $ kubectl get pod myapp -o jsonpath='{.spec.ephemeralContainers[0].securityContext}' ``` 執行結果 : ``` {"privileged":true} ``` 完成後,清理該 Pod: ``` kubectl delete pod myapp ``` ## Ref - [Debugging using a copy of the Pod - Kubernetes Docs](https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/#debugging-using-a-copy-of-the-pod)