提高 K8S 監(jiān)控可觀察性最佳方式實戰(zhàn)教程
當(dāng)談到云原生可觀察性時宫峦,可能每個人都會提到OpenTelemetry (OTEL),因為社區(qū)需要依賴標(biāo)準(zhǔn)來將所有集群組件開發(fā)指向到同一方向隔崎。OpenTelemetry 使我們能夠?qū)⑷罩窘问铩⒅笜?biāo)(metrics)弄捕、跟蹤(traces)和其他上下文信息組合到一個資源中僻孝。集群管理員或軟件工程師可以使用此資源來獲取在定義的時間段內(nèi)集群中正在發(fā)生的事情的視圖。
但是 Kubernetes 本身如何利用這個技術(shù)棧呢守谓?
Kubernetes 由多個組件組成穿铆,其中一些組件是獨立的,而另一些組件則堆疊在一起斋荞。從容器運行時的角度來看架構(gòu)荞雏,那么從上到下有:
- kube-apiserver:驗證和配置 API 對象的數(shù)據(jù)
- kubelet:在每個節(jié)點上運行的代理
- CRI 運行時:容器運行時接口 (CRI) 兼容的容器運行時,如CRI-O或containerd
- OCI 運行時:較低級別的開放容器倡議 (OCI)運行時平酿,如runc或crun
- Linux 內(nèi)核或Microsoft Windows:底層操作系統(tǒng)
這意味著如果我們在 Kubernetes 中運行容器時遇到問題凤优,那么我們就會開始查看其中一個組件。隨著當(dāng)今集群架構(gòu)復(fù)雜性不斷增加蜈彼,查找問題的根本原因是我們面臨的最耗時的操作之一筑辨。即使知道可能導(dǎo)致問題的組件,仍須考慮其他組件柳刮。
我們?nèi)绾巫龅竭@一點挖垛?大多數(shù)人可能會堅持抓取日志,過濾它們并在組件邊界上將它們組裝在一起秉颗。我們也有 metrics 指標(biāo),但是將指標(biāo)值與普通日志相關(guān)聯(lián)使跟蹤正在發(fā)生的事情變得更加困難送矩。一些指標(biāo)也不是為了調(diào)試目的而制定的蚕甥。
OpenTelemetry 應(yīng)運而生。該項目旨在將 traces~跟蹤栋荸、metrics~指標(biāo)和 logs~日志 等信號組合在一起菇怀,以維護(hù)集群狀態(tài)的統(tǒng)一視圖。
Kubernetes 中 OpenTelemetry 跟蹤的當(dāng)前狀態(tài)是什么晌块?從 API server 的角度來看爱沟,自 Kubernetes v1.22 以來,我們對 tracing 提供了 alpha 支持匆背,它將在即將發(fā)布的其中一個版本中升級為 beta呼伸。不幸的是,beta 畢業(yè)錯過了 Kubernetes v1.26 版本钝尸±ㄏ恚可以在 API Server Tracing Kubernetes Enhancement Proposal (KEP)中找到該設(shè)計提案,其中提供了更多相關(guān)信息珍促。
kubelet tracing 部分 在另一個 KEP 中進(jìn)行跟蹤铃辖,該 KEP 在 Kubernetes v1.25 中以 alpha 狀態(tài)實現(xiàn)。撰寫本文時并未計劃進(jìn)行 Beta 畢業(yè)猪叙,但 v1.27 發(fā)布周期中可能會有更多娇斩。除了兩個 KEP 之外還有其他方面的努力仁卷,例如 klog 正在考慮 OTEL 支持,這將通過將日志消息鏈接到現(xiàn)有跟蹤來提高可觀察性犬第。在 SIG Instrumentation 和 SIG Node 中五督,我們還在討論 如何將 kubelet traces 鏈接在一起,因為現(xiàn)在他們專注于 kubelet 和 CRI 容器運行時之間的 gRPC 調(diào)用瓶殃。
CRI-O 從 v1.23.0 開始就支持 OpenTelemetry 跟蹤充包,并致力于不斷改進(jìn)它們,例如通過 將日志附加到跟蹤 或?qū)?spans 擴(kuò)展到應(yīng)用程序的邏輯部分遥椿。這有助于跟蹤的用戶獲得與解析日志相同的信息基矮,但具有增強的范圍界定和過濾其他 OTEL 信號的能力。CRI-O 維護(hù)者還在開發(fā)conmon的容器監(jiān)控替代冠场,稱為 conmon-rs 并且純用 Rust 編寫家浇。使用 Rust 實現(xiàn)的一個好處是能夠添加諸如 OpenTelemetry 支持之類的功能,因為這些功能的庫已經(jīng)存在碴裙。這允許與 CRI-O 緊密集成钢悲,并讓消費者從容器中看到最低級別的跟蹤數(shù)據(jù)。
containerd 從 v1.6.0 開始添加了 tracing 支持舔株,可通過使用插件 獲得莺琳。較低級別的 OCI 運行時,如 runc 或 crun载慈,根本不支持 OTEL惭等,而且似乎不存在這方面的計劃。我們必須考慮到在收集 traces 并將它們導(dǎo)出到數(shù)據(jù)接收器時會產(chǎn)生性能開銷办铡。我仍然認(rèn)為在 OCI 運行時擴(kuò)展的遙測收集看起來是值得評估的辞做。讓我們看看 Rust OCI 運行時 youki 將來是否會考慮類似的事情。
下面我會展示如何做寡具。對于下面演示秤茅,我將堅持使用 runc、conmon-rs童叠、CRI-O 和 kubelet 的單個本地節(jié)點堆棧框喳。要在 kubelet 中啟用跟蹤,需要在KubeletConfiguration
中配置以下內(nèi)容:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
KubeletTracing: true
tracing:
samplingRatePerMillion: 1000000
等于一samplingRatePerMillion
百萬將在內(nèi)部轉(zhuǎn)化為對所有內(nèi)容進(jìn)行采樣拯钻。必須將類似的配置應(yīng)用于 CRI-O帖努;我可以使用 and 啟動二進(jìn)制 crio
文件,或者我們使用這樣的嵌入式配置:--enable-tracing``--tracing-sampling-rate-per-million 1000000
一個 samplingRatePerMillion
等于 100 萬將在內(nèi)部轉(zhuǎn)化為對所有內(nèi)容的抽樣粪般。必須對 CRI-O 應(yīng)用類似的配置拼余;我可以使用參數(shù) --enable-tracing
和 --tracing-sampling-rate-per-million 1000000
啟動 crio 二進(jìn)制文件,或者使用這樣的插入式配置:
cat /etc/crio/crio.conf.d/99-tracing.conf
[crio.tracing]
enable_tracing = true
tracing_sampling_rate_per_million = 1000000
要將 CRI-O 配置為使用 conmon-rs亩歹,至少需要最新的 CRI-O v1.25.x 和 conmon-rs v0.4.0匙监。然后像下面這樣配置插件可以讓 CRI-O 使用 conmon-rs:
cat /etc/crio/crio.conf.d/99-runtimes.conf
[crio.runtime]
default_runtime = "runc"
[crio.runtime.runtimes.runc]
runtime_type = "pod"
monitor_path = "/path/to/conmonrs" # or will be looked up in $PATH
默認(rèn)配置將指向的 OpenTelemetry 收集器 gRPC 端點:localhost:4317
凡橱,它也必須啟動并運行。如文檔中所述 有多種運行 OTLP 的方法亭姥,但也可以通過 kubectl proxy
進(jìn)入在 Kubernetes 中運行的現(xiàn)有實例稼钩。
如果一切都已設(shè)置好,那么收集器應(yīng)該記錄有傳入的跟蹤:
ScopeSpans #0
ScopeSpans SchemaURL:
InstrumentationScope go.opentelemetry.io/otel/sdk/tracer
Span #0
Trace ID : 71896e69f7d337730dfedb6356e74f01
Parent ID : a2a7714534c017e6
ID : 1d27dbaf38b9da8b
Name : github.com/cri-o/cri-o/server.(*Server).filterSandboxList
Kind : SPAN_KIND_INTERNAL
Start time : 2022-11-15 09:50:20.060325562 +0000 UTC
End time : 2022-11-15 09:50:20.060326291 +0000 UTC
Status code : STATUS_CODE_UNSET
Status message :
Span #1
Trace ID : 71896e69f7d337730dfedb6356e74f01
Parent ID : a837a005d4389579
ID : a2a7714534c017e6
Name : github.com/cri-o/cri-o/server.(*Server).ListPodSandbox
Kind : SPAN_KIND_INTERNAL
Start time : 2022-11-15 09:50:20.060321973 +0000 UTC
End time : 2022-11-15 09:50:20.060330602 +0000 UTC
Status code : STATUS_CODE_UNSET
Status message :
Span #2
Trace ID : fae6742709d51a9b6606b6cb9f381b96
Parent ID : 3755d12b32610516
ID : 0492afd26519b4b0
Name : github.com/cri-o/cri-o/server.(*Server).filterContainerList
Kind : SPAN_KIND_INTERNAL
Start time : 2022-11-15 09:50:20.0607746 +0000 UTC
End time : 2022-11-15 09:50:20.060795505 +0000 UTC
Status code : STATUS_CODE_UNSET
Status message :
Events:
SpanEvent #0
-> Name: log
-> Timestamp: 2022-11-15 09:50:20.060778668 +0000 UTC
-> DroppedAttributesCount: 0
-> Attributes::
-> id: Str(adf791e5-2eb8-4425-b092-f217923fef93)
-> log.message: Str(No filters were applied, returning full container list)
-> log.severity: Str(DEBUG)
-> name: Str(/runtime.v1.RuntimeService/ListContainers)
可以看到 spans 有一個 trace ID达罗,并且通常有一個附加 attached坝撑。日志等事件也是輸出的一部分。在上述情況下粮揉,kubelet 的 Pod 生命周期事件生成器 (PLEG) 定期觸發(fā) ListPodSandbox
調(diào)用 CRI-O 的 RPC巡李。可以通過例如 Jaeger 來顯示這些 traces 扶认。在本地運行跟蹤堆棧時侨拦,默認(rèn)情況下應(yīng)公開一個 Jaeger 實例地址為:http://localhost:16686
。
這些ListPodSandbox
請求在 Jaeger UI 中直接可見:
這并不太令人興奮辐宾,所以我將直接通過kubectl
運行工作負(fù)載:
kubectl run -it --rm --restart=Never --image=alpine alpine -- echo hi
hi
pod "alpine" deleted
現(xiàn)在查看 Jaeger狱从,我們可以看到有 conmonrs
,crio
以及kubelet
的RunPodSandbox
和CreateContainer
CRI RPC 的 traces:
kubelet 和 CRI-O spans 相互連接叠纹,使調(diào)查更容易季研。如果我們現(xiàn)在仔細(xì)查看這些 spans,可以看到 CRI-O 的日志正確地包含了相應(yīng)的功能吊洼。例如训貌,可以像這樣從 traces 中提取 container user:
較低級別的 conmon-rs spans 也是此跟蹤的一部分。例如 conmon-rs 維護(hù)一個內(nèi)部 read_loop
處理容器和最終用戶之間的 IO冒窍。讀取和寫入字節(jié)的日志是 spans 的一部分。這同樣適用于 wait_for_exit_code
span豺鼻,它告訴我們?nèi)萜鞒晒ν顺鲎垡海琧ode 為0
:
將所有這些信息與 Jaeger 的過濾功能放在一起,使整個堆棧成為調(diào)試容器問題的絕佳解決方案儒飒!提到“整個堆椕ǎ”也顯示了整體方法的最大缺點:與解析日志相比,它在集群設(shè)置之上增加了明顯的開銷桩了。用戶必須維護(hù)一個像 Elasticsearch 這樣的接收器來持久化數(shù)據(jù)附帽,暴露 Jaeger UI 并可能考慮到性能缺陷。無論如何井誉,它仍然是提高 Kubernetes 可觀察性方面的最佳方法之一蕉扮。
感謝您閱讀這篇博文,我很確定大家正在展望 Kubernetes 對 OpenTelemetry 支持的光明前景颗圣,以簡化故障排除喳钟。
譯自
作者:Sascha Grunert
原文:https://kubernetes.io/blog/2022/12/01/runtime-observability-opentelemetry/
說明
請關(guān)注 危 ? 工中號【進(jìn)擊云原生】屁使,更有free資源供您學(xué)習(xí)
本文由mdnice多平臺發(fā)布