利用 Tmux 和 kubectl 解決 Kubernetes 故障

2020-02-25 12:55:00

一個使用 tmux 的 kubectl 外掛可以使 Kubernetes 疑難問題變得更簡單。

Kubernetes 是一個活躍的開源容器管理平台,它提供了可延伸性、高可用性、健壯性和富有彈性的應用程式管理。它的眾多特性之一是支援通過其主要的二進位制用戶端 kubectl 執行客製化指令碼或可執行程式,kubectl 很強大的,允許使用者在 Kubernetes 叢集上用它直接做很多事情。

使用別名進行 Kubernetes 的故障排查

使用 Kubernetes 進行容器編排的人都知道由於設計上原因帶來了其功能的複雜性。舉例說,迫切需要以更快的速度並且幾乎不需要手動干預的方式來簡化 Kubernetes 中的故障排除(除過特殊情況)。

在故障排查功能方面,有很多場景需要考慮。在一種場景下,你知道你需要執行什麼,但是這個命令的語法(即使作為一個單獨的命令執行)過於複雜,或需要一、兩次互動才能起作用。

例如,如果你需要經常進入一個系統名稱空間中執行的容器,你可能發現自己在重複地鍵入:

kubectl --namespace=kube-system exec -i -t <your-pod-name>

為了簡化故障排查,你可以用這些指令的命令列別名。比如,你可以增加下面命令到你的隱藏組態檔(.bashrc.zshrc):

alias ksysex='kubectl --namespace=kube-system exec -i -t'

這是來自於 Kubernetes 常見別名儲存庫的一個例子,它展示了一種簡化 kubectl 中的功能的方法。像這種場景下的簡單情形,使用別名很有用。

切換到 kubectl 外掛

更複雜的故障排查場景是需要一個一個的執行很多命令,調查環境,最後得出結論。僅僅用別名方法是不能解決這種情況的;你需要知道你所部署的 Kubernetes 之間邏輯和相關性,你真正需要的是自動化,以在更短的時間內輸出你想要的。

考慮到你的叢集有 10 ~ 20 或 50 ~ 100 個名稱空間來提供不同的微服務。一般在進行故障排查時,什麼對你有幫助?

  • 你需要能夠快速分辨出丟擲錯誤的是哪個 名稱空間的哪個 Pod 的東西。
  • 你需要一些可監視一個名稱空間的所有 Pod 紀錄檔的東西。
  • 你可能也需要監視特定名稱空間的出現錯誤的某個 Pod 的紀錄檔。

涵蓋這些要點的解決方案對於定位生產環境的問題有很大的幫助,以及在開發和測試環節中也很有用。

你可以用 kubectl 外掛建立比簡單的別名更強大的功能。外掛類似於其它用任何語言編寫的獨立指令碼,但被設計為可以擴充 Kubernetes 管理員的主要命令。

建立一個外掛,你必須用 kubectl-<your-plugin-name> 的正確的語法來拷貝這個指令碼到 $PATH 中的匯出目錄之一,並需要為其賦予可執行許可權(chmod +x)。

建立外掛之後將其移動到路徑中,你可以立即執行它。例如,我的路徑下有一個 kubectl-krawlkubectl-kmux

$ kubectl plugin listThe following compatible plugins are available:/usr/local/bin/kubectl-krawl/usr/local/bin/kubectl-kmux$ kubectl kmux

現在讓我們見識下帶有 tmux 的 Kubernetes 的有多強大。

駕馭強大的 tmux

Tmux 是一個非常強大的工具,許多管理員和運維團隊都依賴它來解決與易操作性相關的問題:通過將視窗分成多個窗格以便在多台計算機上執行並行的偵錯來監視紀錄檔。它的主要的優點是可在命令列或自動化指令碼中使用。

我建立一個 kubectl 外掛,使用 tmux 使故障排查更加簡單。我將通過註釋來解析外掛背後的邏輯(外掛的完整程式碼留待給你實現):

# NAMESPACE 是要監控的命名空間# POD 是 Pod 名稱# Containers 是容器名稱# 初始化一個計數器 n 以計算回圈計數的數量,# 之後 tmux 使用它來拆分窗格。n=0;# 在 Pod 和容器列表上開始迴圈while IFS=' ' read -r POD CONTAINERSdo    # tmux 為每個 Pod 建立一個新視窗    tmux neww $COMMAND -n $POD 2>/dev/null    # 對執行中的 Pod 中 的所有容器啟動迴圈    for CONTAINER in ${CONTAINERS//,/ }    do        if [ x$POD = x -o x$CONTAINER = x ]; then            # 如果任何值為 null,則退出。                     warn "Looks like there is a problem getting pods data."            break        fi                   # 設定要執行的命令        COMMAND=”kubectl logs -f $POD -c $CONTAINER -n $NAMESPACE”        # 檢查 tmux 對談        if tmux has-session -t <對談名> 2>/dev/null;        then            <設定對談退出>        else            <建立對談>        fi        # 在當前視窗為每個容器切分窗格        tmux selectp -t $n \; \        splitw $COMMAND \; \        select-layout tiled \;        # 終止容器回圈    done        # 用 Pod 名稱重新命名視窗以識別    tmux renamew $POD 2>/dev/null        # 增加計數器    ((n+=1))# 終止 Pod 迴圈done<<(<從 kubernetes  叢集獲取 Pod 和容器的列表>)# 最後選擇視窗並附加對談tmux selectw -t <對談名>:1 \; \attach-session -t <對談名>\;

執行外掛指令碼後,將產生類似於下圖的輸出。每個 Pod 有一個自己的視窗,每個容器(如果有多個)被分割到其視窗中 Pod 窗格中,並在紀錄檔到達時輸出。Tmux 之美如下可見;通過正確的設定,你甚至會看到哪個視窗正處於啟用執行狀態(可看到標籤是白色的)。

總結

別名是在 Kubernetes 環境下常見的也有用的簡易故障排查方法。當環境變得複雜,用高階指令碼生成的kubectl 外掛是一個更強大的方法。至於用哪個程式語言來編寫 kubectl 外掛是沒有限制。唯一的要求是該名字在路徑中是可執行的,並且不能與已知的 kubectl 命令重複。

要閱讀完整的外掛原始碼,或試試我建立的外掛,請檢視我的 kube-plugins-github 儲存庫。歡迎提交提案和修補程式。