掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流
本文轉(zhuǎn)載自微信公眾號(hào)「云原生百寶箱」

成都創(chuàng)新互聯(lián)主要從事網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)越城,10余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢(xún)建站服務(wù):18982081108
這篇內(nèi)容主要探討了 Kubernetes 的調(diào)試功能,介紹了 kubectl debug 和 kubectl superdebug。它們支持容器掛載并且能夠調(diào)試一些需要排查問(wèn)題的 Pod。文章指出了在 Kubernetes 中使用 kubectl exec 命令的限制,并介紹了 kubectl debug 的作用,它能創(chuàng)建一個(gè)新的容器來(lái)調(diào)試運(yùn)行中的容器,并且能夠在同一個(gè) Pod 內(nèi)共享系統(tǒng)資源。此外,還提到了 ephemeral containers,它們?cè)谡{(diào)試過(guò)程中可以臨時(shí)運(yùn)行在現(xiàn)有的 Pod 中,支持一些排查操作。最后,文章還提及了一些非 Kubernetes 本地調(diào)試容器的方法,包括使用 Docker Engine 或者一些基于 Linux namespaces 的工具。
如果你在 Kubernetes 上運(yùn)行軟件,你有時(shí)會(huì)想要調(diào)試所部署的應(yīng)用。對(duì)于習(xí)慣使用虛擬機(jī)的人來(lái)說(shuō),一種簡(jiǎn)單的調(diào)試方法是連接到正在運(yùn)行的 Pod 并進(jìn)行分享:
kubectl exec -it podname -c containername -- bash這通常有效并且非常有用。然而,至少有兩個(gè) Kubernetes“最佳實(shí)踐”限制了 exec 在現(xiàn)實(shí)世界中的用處:
? 不以 root 身份運(yùn)行。容器以盡可能少的權(quán)限運(yùn)行,甚至可以使用隨機(jī) UID 運(yùn)行。
? 最小鏡像。鏡像盡可能小,極端情況下將二進(jìn)制文件安裝到distroless 鏡像中。[1]
當(dāng)應(yīng)用這些最佳實(shí)踐時(shí),使用kubectl exec連接到容器要么是不可能的,要么會(huì)讓你陷入不適合調(diào)試的貧瘠荒地般的環(huán)境。
調(diào)試正在運(yùn)行的容器的 Kubernetes 原生答案是使用kubectl debug。
debug 命令將一個(gè)新容器附加到正在運(yùn)行的 pod 中。這個(gè)新容器可以以不同的用戶身份從你選擇的任何鏡像運(yùn)行。由于調(diào)試容器與其目標(biāo)容器在同一 Pod 中運(yùn)行(因此在同一節(jié)點(diǎn)上),因此兩個(gè)容器之間的隔離不需要是絕對(duì)的。調(diào)試容器可以與同一 Pod 中運(yùn)行的其他容器共享系統(tǒng)資源。
考慮要檢查pod容器postpod中運(yùn)行的 PostgreSQL 數(shù)據(jù)庫(kù)的 CPU 使用情況。Pod 不以 root 身份運(yùn)行,并且 Postgres 鏡像沒(méi)有類(lèi)似top或htop安裝的工具——換句話說(shuō),該kubectl exec命令沒(méi)什么用處。你可以運(yùn)行以下命令:
kubectl debug -it \
--container=debug-container \
--image=alpine \
--target=postcont \
postpod你將以 root 身份登錄(這是 Alpine 鏡像的默認(rèn)設(shè)置),并且可以輕松安裝你最喜歡的交互式進(jìn)程查看器 htop ( apt add htop)。你與容器postcont共享相同的進(jìn)程命名空間,并且可以查看甚至殺死在那里運(yùn)行的所有進(jìn)程!當(dāng)你退出該進(jìn)程時(shí),臨時(shí)容器也將停止存在。
注意:你可以通過(guò)按 CTRL+P 或 CTRL+D 斷開(kāi)與臨時(shí)容器/bash 會(huì)話的連接,而無(wú)需退出(終止)它。然后你可以稍后使用 重新連接到它kubectl attach。
注意:kubectl debug提供的功能比此處概述的更多,例如使用修改后的啟動(dòng)命令復(fù)制 Pod 或啟動(dòng)可訪問(wèn)節(jié)點(diǎn)文件系統(tǒng)的“節(jié)點(diǎn)”P(pán)od。
上面的命令kubectl debug通過(guò)創(chuàng)建一個(gè)稱(chēng)為臨時(shí)容器[2]東西來(lái)工作。這些容器應(yīng)該在現(xiàn)有Pod 中臨時(shí)運(yùn)行,以支持故障排除等操作。
“普通”容器和臨時(shí)容器之間的區(qū)別很小。沒(méi)有什么能真正阻止臨時(shí)容器長(zhǎng)期運(yùn)行。我認(rèn)為,通過(guò)查看 Kubernetes 在誕生之初所做的基礎(chǔ)架構(gòu)選擇,可以最好地理解擁有臨時(shí)容器的原因:
? Pod 應(yīng)該是一次性且可更換的,并且支持這一點(diǎn),
? Pod 規(guī)范是不可變的。
當(dāng) Kubernetes 主要用于部署無(wú)狀態(tài)工作負(fù)載時(shí)(當(dāng) Pod 本身可以被認(rèn)為是短暫的)時(shí),這非常有意義。在這個(gè) Kubernetes無(wú)所不能的新世界中,它可能會(huì)受到限制。Pod 規(guī)范保持不變,但 Kubernetes 將臨時(shí)容器建模為Pod 的子資源。與“普通”容器不同,臨時(shí)容器不是 Pod規(guī)范的一部分,即使它們是 pod 的一部分。這種微妙的區(qū)別讓每個(gè)人都高興????!
臨時(shí)容器仍然相對(duì)較新;
它們自 Kubernetes v1.25(2022 年 8 月)處于Stable狀態(tài),自 v1.23(2021 年 12 月)是Beta狀態(tài),自 v1.22(2021 年 8 月)是Alpha狀態(tài)。
內(nèi)置命令kubectl debug非常有用。它允許你將臨時(shí)容器添加到正在運(yùn)行的 Pod,可以選擇與正在運(yùn)行的容器共享其進(jìn)程命名空間。但是,如果你希望用于kubectl debug檢查或修改正在運(yùn)行的容器的文件系統(tǒng)的任何部分,那么你就不走運(yùn)了 - 調(diào)試 Pod 的文件系統(tǒng)與你連接到的容器的文件系統(tǒng)是脫節(jié)的。
幸運(yùn)的是,我們可以做得更好。這個(gè)想法很簡(jiǎn)單:
? 檢索正在運(yùn)行的目標(biāo)容器的規(guī)格。
? 將臨時(shí)容器修補(bǔ)到 Pod 中。將其配置為與目標(biāo)容器共享相同的進(jìn)程命名空間,并另外包含相同的卷掛載。
沒(méi)有用于創(chuàng)建臨時(shí)容器的 kubectl 命令,因此我們需要向 K8s API 發(fā)送 PATCH 請(qǐng)求來(lái)創(chuàng)建它。該kubectl proxy命令允許訪問(wèn) K8s API。
這個(gè)過(guò)程并不完全是用戶友好的,因此將過(guò)程包裝到腳本或 kubectl 插件中是有意義的。你可以在此處找到此類(lèi)腳本的示例實(shí)現(xiàn):
https://github.com/JonMerlevede/kubectl-superdebugkubectl debug 的擴(kuò)展將目標(biāo)容器的卷規(guī)格附加到臨時(shí)調(diào)試 pod 中……
請(qǐng)注意,此方法和腳本可以輕松擴(kuò)展以從目標(biāo)容器復(fù)制環(huán)境變量規(guī)范。
如果將此腳本另存為kubectl-superdebug并使其在你的路徑上可用,則可以kubectl superdebug從任何地方運(yùn)行它,如下所示:
kubectl superdebug \
--container=debug-container \
--image=alpine \
--target=postcont \
postpod你可能還想擴(kuò)展此腳本以將目標(biāo)容器的其他方面復(fù)制到調(diào)試容器中,例如對(duì)環(huán)境變量的引用。
這完成了調(diào)試運(yùn)行容器的 Kubernetes 原生方法的概述,應(yīng)該可以滿足大多數(shù)人的需求。
Kubernetes 不提供以 root 身份連接到正在運(yùn)行的容器(除非主進(jìn)程以 root 身份運(yùn)行)或從另一個(gè)容器訪問(wèn)容器的根文件系統(tǒng)的方法。這并不意味著這些事情不可能做到。畢竟,Kubernetes 只是一個(gè)位于容器化引擎之上的容器編排器。如果由于某種原因確實(shí)有必要的話,通??梢酝ㄟ^(guò)刪除抽象層來(lái)做任何你想做的事情。只要確保你必須...
如果你使用 Docker 引擎并且可以直接從節(jié)點(diǎn)或通過(guò)節(jié)點(diǎn)上運(yùn)行的特權(quán)容器訪問(wèn)你的引擎,那么你可以docker exec --user作為你選擇的用戶運(yùn)行和執(zhí)行進(jìn)程。
諸如kubectl ssh和 之類(lèi)的插件kubectl exec-user實(shí)現(xiàn)了這種方法。不幸的是, containerd[3]和CRI-O[4]等現(xiàn)代引擎不再提供--user標(biāo)志功能——這意味著這些插件無(wú)法在現(xiàn)代 Kubernetes 安裝上運(yùn)行。
然而,即使是這些現(xiàn)代引擎通常也只是與 Linux 命名空間交互。你可以通過(guò)輸入適當(dāng)?shù)?Linux 命名空間集在任何你想要的“容器”中運(yùn)行命令。kpexec[5]工具實(shí)現(xiàn)了這種方法。它在與目標(biāo)容器相同的節(jié)點(diǎn)上啟動(dòng)一個(gè)特權(quán) Pod,然后確定要定位的 (Linux) 命名空間,在這些 (Linux) 命名空間中執(zhí)行命令,最后將其輸出流式傳輸?shù)侥愕慕K端。作為一個(gè)額外的好處,它可以在目標(biāo)容器的文件系統(tǒng)之上覆蓋一組可用于調(diào)試的工具。
與 kubectl exec 不同,kpexec 可以運(yùn)行具有不同 uid/gid 甚至不同功能的命令作為容器的主進(jìn)程。它與containerd和cri-o兼容。kpexec 采用某種重量級(jí)且脆弱的方法,可能與你的集群的安全配置不兼容。如果 kubectl (super)debug 無(wú)法滿足你的需求,則值得考慮。
請(qǐng)注意,kpexec 使用nsenter命令直接執(zhí)行到命名空間中。它與無(wú)處不在的容器運(yùn)行時(shí) runc 兼容,但與Kata Containers[6]等運(yùn)行時(shí)不兼容。
在這篇文章中,我們研究了兩種調(diào)試運(yùn)行容器的 Kubernetes 原生方法:kubectl exec和kubectl debug。我們研究了kubectl debug工作原理,并提出了kubectl superdebug一種變體,kubectl debug它啟動(dòng)一個(gè)與目標(biāo)容器共享相同卷和相同進(jìn)程命名空間的臨時(shí)容器。最后,我們回顧了一些非 Kubernetes 原生的容器調(diào)試方法。
[1] distroless 鏡像中。: https://github.com/GoogleContainerTools/distroless
[2] 臨時(shí)容器: https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/
[3] containerd: https://containerd.io/
[4] CRI-O: https://cri-o.io/
[5] kpexec: https://github.com/ssup2/kpexec[6] Kata Containers: https://katacontainers.io/

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流