宜信容器雲排錯工具集

宜信容器雲是一套基於kubernetes的容器管理平臺。業務線用戶在容器雲上部署應用程序時,經常會遇到容器沒法啓動或者應用程序運行不正常的狀況。爲了方便用戶排查在應用上雲過程當中的問題,咱們在web端集成了一系列的排錯方式,以下圖:前端

1、終端信息

終端信息查看的是容器實例運行時的標準輸出日誌。node

效果等同於:kubectl logs PODNAME [-c CONTAINER]git

基本原理以下圖:github

應用部署時,所屬節點的kubelet經過grpc調用容器運行時接口(container runtime interface),來請求docker守護進程建立容器運行時。web

此時,docker守護進程會建立一個協程來接收容器運行時的標準輸出日誌,這個協程最終將STDOUT(標準輸出)的日誌寫到容器運行時所在節點的對應目錄下:/var/lib/docker/containers/container_id/{container_id-json.log}docker

以下圖:shell

在web端查看對應實例的終端信息時,kubelet將接收的Api-server請求轉化成docker client來請求docker守護進程。Docker守護進程到相應的目錄下讀取對應容器的日誌文件數據,再由kubelet返回日誌數據到Api-server,最終顯示到web端,供用戶查看。json

容器日誌的生命週期與容器的生命週期一致,容器銷燬後,其相關的日誌文件也會銷燬。後端

2、events

events是kubelet用來記錄容器啓動及運行過程當中的事件。安全

效果等同於:kubectl get events

一樣,當使用kubectl describe pod來查看pod時,也同樣能看到與該pod相關的events,從這些信息中能夠很清楚看到事件的狀態變化,從而獲知pod啓動失敗的多種緣由。好比:

1)沒有可用的node供調度,如調度的節點資源不夠;

2)健康狀態檢查失敗;

3)拉取鏡像失敗,以下圖:

events的基本實現以下圖:

events中包含事件相關的類型、緣由、來源、消息等,會在kubelet和controller manager等組件中生成,廣播出去後,通過一系列的函數過濾、聚合等,再發送給Api-server存到etcd中。當web端查看events事件時,請求Api-server讀取etcd中相應的事件,並返回顯示,供用戶查看異常參數、錯誤狀態等。

3、web terminal

web terminal可提供一個交互式的界面shell,可執行各類命令。

效果等同於:kubectl exec -it <podName> -c <containerName> bash

web端顯示如圖:

實現以下:

web terminal主要是經過websocket技術實現的,前端交互界面使用的是開源項目container-terminal(https://github.com/kubernetes-ui/container-terminal),其提供了一個容器的TTY(虛擬終端)。

當查看web terminal時,前端web發起了一個websocket請求,到Api-server。再由所屬節點的kubelet響應該Api-server的請求,並與容器運行時創建鏈接。

之因此kubelet可以與容器運行時創建鏈接,是由於kubelet 定義了一個 CRI 規範中的 RuntimeServiceClient 接口,而容器運行時中的RuntimeServiceServer(即Streaming Server,提供了streaming API)實現了該接口。

kubelet 和容器運行時創建鏈接後,kubelet返回請求,Api-server將請求升級爲SPDY(SPDY容許在單個的TCP請求中複用獨立的STDIN/STDOUT/STDERR),並將WS的流映射到SPDY相應的標準流上,便與目標容器運行時Streaming Server創建了流,Api-server便實現了web與容器運行時的數據交互。

此時,在web端輸入命令,下發執行完後,可看到返回的結果,如此便實現了交互。

web terminal提供了進入容器的便利,用戶能夠執行任何操做,爲了安全,咱們作了必要的安全措施:

1)記錄了用戶的操做命令。

待用戶輸入命令後,記錄操做,做爲安全審計。

2)生產環境使用普通用戶進入容器。

即在exec進入容器時的命令/bin/bash -i更改成/bin/bash –c chmod -R 777 $KUBERNETES_FILELOGS;useradd spider > /dev/null 2>&1;su spider,其中環境變量$KUBERNETES_FILELOGS爲在容器建立時須要賦權的文件目錄。主要是防止用戶誤操做,刪除存儲掛載等。

4、debug容器

debug容器是經過工具容器來對業務容器排障。

在使用web terminal來調試應用程序的過程當中,業務線用戶常常須要各式各樣的命令來調試程序。以前的解決方案要麼是給業務線定製他們所需的基礎鏡像,儘可能涵蓋多的所需命令,要麼就是在業務線用戶構建鏡像時在Dockerfile中添加命令。

可是,由於業務線衆多,定製基礎鏡像工做量過大;而在構建業務鏡像時添加過多命令,又操做繁瑣,並可能會帶來安全隱患。這些解決方案實際上都不符合容器技術的實踐原則--儘量構建最簡容器鏡像,而精簡後的鏡像又極度缺失所需的命令工具。

鑑於存在這樣的矛盾,咱們集成並改造了kubectl-debug(https://github.com/aylei/kubectl-debug)這個插件。容器實質上是由cgroup和namespace限制的一組進程,只要可以加入到這個進程的各項namespace,就可實現交互。所以,debug容器的基本思路是:啓動一個包含衆多排障工具命令的容器,來加入到業務容器的namespace中,便可以在工具容器中實現對業務容器的排障。

效果相似於:

docker run -it --network=container:<container_ID> --pid=container:<container_ID> --ipc=container :<container_ID> -v /log/container _ID:/debugviewlogs <image>

web端顯示以下圖:

debug容器原理以下圖:

將Debug-agent以DaemonSet的形式部署到kubernetes集羣的全部節點中,並掛載了宿主機的/var/docker/docker.sock,實現與docker daemon的通訊。如上圖的步驟:

1)web端提供pod的cluster、namespace、podname信息,向後端服務Backend server發起websocket請求;

2)後端服務Backend server接收到請求後,向Api-server驗證該pod是否存在,並返回pod所在的宿主機Node和pod的容器信息,根據狀態判斷是否能夠debug;

注意:若是pod的狀態reason是CrashLoopBackOff,那麼Backend server將會請求Api-server讓kubelet複製一個pod, 複製的Pod被改寫了啓動命令(sleep)、去掉了label及健康檢查。後續debug操做是對複製後pod進行的。

3)Backend server傳遞debug的pod信息,發起debug請求(升級的SPDY請求,映射了WS的標準流)。

4)Debug-agent收到請求後,開始拉取debug工具鏡像,進而建立一個debug容器,並將debug容器的各個namespace設置爲目標業務容器app的namespace。再將宿主Node的目錄/log/<podname> 掛載到debug容器的目錄/debugviewlogs中,即可實現將debug容器中生成的文件在web端下載。以下兩圖:

建立完debug容器後,Debug-agent將Backend server的SPDY請求中繼到debug容器。debug容器將SPDY的標準流attach到業務容器中。如此,web端即可與debug容器實現交互。在debug操做結束後,Debug-agent便會將debug容器清理回收。一樣的,debug的操做也作了安全審計。

所以,咱們只要構建一個包含衆多排障工具的鏡像,不只實踐了業務鏡像儘量最簡的原則,還提供了調試應用程序所需的各類命令工具。

總結

終端信息、events、web terminal及debug容器都提供了一個可視化的web,讓用戶可以方便快速地實現對pods排錯和對應用程序的排障。

做者:段德華

來源:宜信技術學院

相關文章
相關標籤/搜索