當 kubectl 不夠用時:用 Debug 容器深入排查系統問題
建立好一座 Kubernetes / OpenShift 集群後,大部分的疑難排解文章都是教你如何從 Kubernetes / OpenShift 的角度,透過 Kubernetes 的 kubectl 或 OpenShift 的 oc 指令來進行一系列的偵查,而這個查詢的結果都是基於 kube-apiserver 為核心的結果,中間已經抽象過很多層,距離底層資訊已有段距離。
若今天想要特意建立一個 Container 出來,用來進行 OS 或 Kubernetes 層級的 Troubleshooting 該如何實作呢?
這樣做的動機是?
通常在離線環境下,很常在客戶端遇到以下幾種事情
- 客戶家沒有套件,不能臨時下載套件
- 不能亂安裝套件,合規性會有問題
- 想要的版本跟能提供的版本不一樣
當遇到系統問題的時候,但手頭受限於上述問題影響,導致做起事情綁手綁腳,故想要有一個完整可信任的除錯工具包 (容器) 來協助快速定位問題。同一時間這個工具也要能一體適用於 Kubernetes 平台上進行 Pod-Level 的除錯,尤其是針對 Networking 的部分。
當我有一個 OS
在這個狀況下,會有兩個使用情境:
- 容器位於 OS 之上 (Container on OS)
- 容器位於 OS 之內 (Container within OS)

第一個情境比較好理解,畢竟大多數的人用 Container 都是為了這個特性。技術上其實就是直接下載 Container Images 後執行該容器內部的工具,任何的操作都不會跟外部主機 (Host OS)有任何影響。但也因為這個特性,導致如果 Container 內部有一些好用的工具,其實是不能讓外部主機做應用,白話來說就是風馬牛完全不相干。參考指令如下:
| |
若使用 Podman 的話,指令幾乎相同:
| |

第二個情境,是利用 docker volume 的掛載特性,將外部主機的特定幾個路徑,如 /dev、/proc 等掛載到容器裡面,而容器因為需要讀取到系統資訊,所以皆需要 --privileged 權限。這類在容器的操作會影響到外部主機,所以要特別留意,如果有需要特別保護的話針對特定 volume 使用 ro 進行保護,避免人為誤操作。參考指令如下:
| |
⚠️ 安全提醒:
--privileged會賦予容器幾乎等同 root 的完整權限,在生產環境中請謹慎使用。如果只需要特定功能,建議改用--cap-add僅授予需要的 Linux capabilities(如NET_ADMIN、SYS_PTRACE),以遵循最小權限原則。
另外如果想要自己實作屬於自己的 debug container 的話,要留意一下各家 OS 的路徑規則 (man hier) 不盡相同,建議是看外部主機是什麼 OS 就選哪一種 Base Image,譬如說我個人用的主機是 RHEL 9,所以 debug container 的基礎映像檔就選 ubi9 (Universal Base Image) 為主的映像檔,避免路徑不一樣導致神秘的現象發生。
當我有一個容器平台

基本 Kubernetes 的介紹就跳過了,針對網路的部分,Kubernetes 設計致力於解決以下五種網路溝通問題:
- Container to Container
- Pod to Pod in same node
- Pod to Pod in different nodes
- Pod to Service
- Kubernetes to Internet
如果稍微認識到 Kubernetes 的朋友,會了解到 Kubernetes 的最小計算單位是 Pod,而一個 Pod 可以擁有一個或多個以上的 Container,只是大多數狀況下都是一個 Pod 裡面塞一個 Container,所以很容易誤會這兩個是一樣的等級。
針對 Container to Container,基本同一個 Pod 內的 Containers 是不會跨主機的,使用相同的 network namespace,所以視為標準 L2 Bridge 情境即可。而 Pod to Pod 及 Pod to Service 的情況,Kubernetes 都會以 Pod 為基礎,透過 CNI Plugin 指派唯一的 IP 供使用,相互之間是可以溝通的。
有時候遇到一些網路問題,譬如像是不同 Node 之間網路不通或者是本身主機有異常狀況發生,其實透過 Kubernetes 的角度是有點難以辨別到底發生什麼事情,所以類同於上面章節提到的作法,可以將特定的 Container 用 Pod 的形式運行在 namespace (or project) 裡面來協助除錯。
使用 kubectl(標準 Kubernetes)
| |
使用 oc(OpenShift)
| |
倘若想要將 Pod 跑在指定的節點上,則要利用 nodeSelector 的概念指定在特定主機上面
| |
記得自己要把 KEY 和 VALUE 換成自己環境的設定,關於 Label 的資訊可以從 kubectl get node --show-labels=true(或 oc get node --show-labels=true)這邊找

更現代的做法:kubectl debug
自 Kubernetes 1.25 起,kubectl debug 指令已正式 GA (General Available),可以直接建立 Ephemeral Container 附加到既有的 Pod 上或直接對 Node 進行除錯,不需要額外手動建立 Pod。這是目前最推薦的做法:
附加 Debug Container 到現有 Pod
當 Pod 內部沒有 shell 或除錯工具時(例如 distroless images),可以注入一個 ephemeral container:
| |
Node-Level Debug
直接在節點上建立一個具有 host namespace 的除錯 Pod:
| |
進入後會自動 chroot 到 /host,等同於直接操作該節點的檔案系統。
💡 提示:
kubectl debug建立的 ephemeral container 無法被移除或重啟,只能等 Pod 重建時消失。這是設計上的限制。
所以我說那個原始碼和環境呢?
以下是關於本文使用到的原始碼和 Image 位置:
- Container Image: divazone_tw/debug-container - Quay
- Dockerfile: divazone/debug-container - GitHub
而測試環境為以下
- OS: RHEL 9 (亦適用於 RHEL 8)
- Container Runtime: Podman 4.x+ / Docker 24+
- Container Platform: Red Hat OpenShift Container Platform v4.14+
理論上來說,觀念上是適用於其他以 Podman / Docker 及 Kubernetes 為主的容器平台,所以可以自行在家試試看。
備註: 若你仍在使用 RHEL 7 / Docker 1.13 / OpenShift 3.11 等舊版本,上述指令仍然相容,但建議盡早規劃升級,因為這些版本皆已終止支援 (EOL)。
同場加映 Part 1: sysdig
| |
同場加映 Part 2: netshoot
| |