kubectl 高效使用技巧

在學習如何更高效地使用 kubectl 之前,你應該對它是如何工作的有個基本的瞭解。kubectl 是 Kubernetes 集羣的控制工具,它可以讓你執行所有可能的 Kubernetes 操作。

從技術角度上看,kubectl 是 Kubernetes API 的客戶端,Kubernetes API 是一個 HTTP REST API,這個 API 是真正的 Kubernetes 用戶界面,Kubernetes 完全受這個 API 控制,這意味着每個 Kubernetes 操作都作爲 API 端點暴露,並且可以由對此端點的 HTTP 請求執行,因此,kubectl 的主要工作是執行對 Kubernetes API 的 HTTP 請求:

Kubernetes 是一個完全以資源爲中心的系統,Kubernetes 維護資源的內部狀態並且所有的 Kubernetes 操作都是針對這些資源的 CRUD(增加、查詢、更新、刪除)操作,你完全可以通過操控這些資源來控制 Kubernetes。

比如我們想要創建一個 ReplicaSet 資源,在一個名爲 replicaset.yaml 的文件中定義 ReplicaSet 資源對象,然後運行以下命令:

kubectl create -f replicaset.yaml

Kubernetes 有一個創建 ReplicaSet 的操作,並且它和其他所有 Kubernetes 操作一樣,都會作爲 API 端點暴露出去,對於我們這裏的操作而言,該 API 端點如下:

POST /apis/apps/v1/namespaces/{namespace}/replicasets

當我們執行上述命令時,kubectl 將向上述 API 端點發出一個 HTTP POST 請求。ReplicaSet 的資源清單內容在請求的 body 中傳遞。這就是 kubectl 與 Kubernetes 集羣交互的所有命令的最基本的工作方式,kubectl 只需向對應的 Kubernetes API 端點發出 HTTP 請求即可。

所以我們完全完全也可以使用 curl、postman 之類的工具來控制 Kubernetes,Kubectl 只是讓我們可以更輕鬆地訪問 Kubernetes API。

執行了上面的資源創建命令之後,API server 將會在 etcd 保存 ReplicaSet 資源定義。然後會觸發 controller manager 中的 ReplicaSet controller,後者會一直 watch ReplicaSet 資源的創建、更新和刪除。ReplicaSet controller 爲每個 ReplicaSet 副本創建了一個 Pod 定義(根據在 ReplicaSet 定義中的 Pod 模板創建)並將它們保存到存儲後端。Pod 創建後會觸發了 scheduler,它一直 watch 尚未被分配給 worker 節點的 Pod。

Scheduler 爲每個 Pod 選擇一個合適的 worker 節點,並在存儲後端中添加該信息到 Pod 定義中。這觸發了在 Pod 所調度到的 worker 節點上的 kubelet,它會監視調度到其 worker 節點上的 Pod。Kubelet 從存儲後端讀取 Pod 定義並指示容器運行時來運行在 worker 節點上的容器。這樣我們的 ReplicaSet 應用程序就運行起來了。

熟悉了這些流程概念後會在很大程度上幫助我們更好地理解 kubectl 並利用它。接下來,我們來看一下具體的技巧,來幫助你提升 kubectl 的生產力。

命令補全

命令補全是提高 kubectl 生產率的最有用但經常被忽略的技巧之一。命令補全功能使你可以使用 Tab 鍵自動完成 kubectl 命令的各個部分。這適用於子命令、選項和參數,包括諸如資源名稱之類難以鍵入的內容。命令補全可用於 Bash 和 Zsh Shell。

官方文檔 https://kubernetes.io/docs/tasks/tools/#enabling-shell-autocompletion 中其實就有關於命令補全的說明。

命令補全是通過補全腳本而起作用的 Shell 功能,補全腳本本質上是一個 shell 腳本,它爲特定命令定義了補全行爲。通過輸入補全腳本可以補全相應的命令。Kubectl 可以使用以下命令爲 Bash 和 Zsh 自動生成並 print out 補全腳本:

kubectl completion bash
# or
kubectl completion zsh

理論上,在合適的 shell(Bash 或 Zsh)中提供此命令的輸出將會啓用 kubectl 的命令補全功能。在 Bash 和 Zsh 之間存在一些細微的差別(包括在 Linux 和 macOS 之間也存在差別)。

Bash

Linux

Bash 的補全腳本主要依賴 bash-completion 項目,所以你需要先安裝它。我們可以使用不同的軟件包管理器安裝 bash-completion,如:

# ubuntu
apt-get install bash-completion
# or centos
yum install bash-completion

你可以使用以下命令測試 bash-completion 是否正確安裝:

type _init_completion

如果輸出的是 shell 的代碼,那麼 bash-completion 就已經正確安裝了。如果命令輸出的是 not found 錯誤,你必須添加以下命令行到你的 ~/.bashrc 文件:

source /usr/share/bash-completion/bash_completion

你是否需要添加這一行到你的 ~/.bashrc 文件中,取決於你用於安裝 bash-completion 的軟件包管理器,對於 APT 來說,這是必要的,對於 yum 則不是。

bash-completion 安裝完成之後,你需要進行一些設置,以便在所有的 shell 會話中獲得 kubectl 補全腳本。一種方法是將以下命令行添加到 ~/.bashrc 文件中:

source <(kubectl completion bash)

另一種是將 kubectl 補充腳本添加到 /etc/bash_completion.d 目錄中(如果不存在,則需要先創建它):

kubectl completion bash  > /etc/bash_completion.d/kubectl

/etc/bash_completion.d 目錄中的所有補全腳本均由 bash-completion 自動提供。

以上兩種方法都是一樣的效果。重新加載 shell 後,kubectl 命令補全就能正常工作了,這個時候我們可以使用 tab 來補全信息了。

Mac

使用 macOS 時,會有些複雜,因爲默認的 Bash 版本是 3.2,而 kubectl 補全腳本至少需要 Bash 4.1,蘋果依舊在 macOS 上默認使用過時的 Bash 版本是因爲更新版本的 Bash 使用的是 GPLv3 license,而蘋果不支持這一 license。

所以要在 macOS 上使用 kubectl 命令補全功能,你必須安裝較新版本的 Bash。我們可以用 Homebrew 安裝 / 升級:

brew install bash

重新加載 shell,並驗證所需的版本已經生效:

echo $BASH_VERSION $SHELL

在繼續剩下的步驟之前,確保你現在已經在使用 Bash 4.1 或更高的版本(可以使用 bash --version 查看版本)。

同上一部分一樣,Bash 的補全腳本主要依賴 bash-completion 項目,所以你需要先安裝它。我們可以使用 Homebrew 安裝  bash-completion:

brew install bash-completion@2

@2 代表 bash-completion v2 版本,Kubectl 補全腳本要求 bash-completion v2,而 bash-completion v2 要求至少是 Bash 4.1,這就是你不能在低於 4.1 的 Bash 版本上使用 kubectl 補全腳本的原因。

brew intall 命令的輸出包括一個 Caveats 部分,其中的說明將以下行添加 ~/.bash_profile 文件:

export BASH_COMPLETION_COMPAT_DIR=/usr/local/etc/bash_completion.d
[[ -r "/usr/local/etc/profile.d/bash_completion.sh"  ]]  &&  .  "/usr/local/etc/profile.d/bash_completion.sh"

必須執行此操作才能完成 bash-completion 的安裝,當然最好將上面的內容添加到 ~/.bashrc 文件中。重新加載 shell 之後,你可以使用以下命令測試 bash-completion 是否正確安裝:

type _init_completion

如果輸出爲 shell 功能的代碼,意味着一切都設置完成。現在,你需要進行一些設置,以便在所有的 shell 會話中獲得 kubectl 補全腳本。一種方法是將以下命令行添加到 ~/.bashrc 文件中:

source <(kubectl completion bash)

另一種方法是將 kubectl 補全腳本添加到 /usr/local/etc/bash_completion.d 目錄中:

kubectl completion bash  >/usr/local/etc/bash_completion.d/kubectl

僅當你使用 Homebrew 安裝了 bash-completion 時,此方法纔有效。在這種情況下,bash-completion 會在此目錄中提供所有補全腳本。如果你還用 Homebrew 安裝了 kubectl,則甚至不必執行上述步驟,因爲補全腳本應該已經由 kubectl Homebrew 放置在 /usr/local/etc/bash_completion.d 目錄中。在這種情況下,kubectl 補全應該在安裝 bash-completion 後就可以生效了。

重新加載 shell 後,kubectl 自動補全也就生效了。

Zsh

Zsh 的補全腳本沒有任何依賴項,所以配置要簡單很多,我們可以通過添加以下命令到你的 ~/.zshrc 文件中來實現這一效果:

source <(kubectl completion zsh)

如果在重新加載你的 shell 之後,你獲得了 command not found: compdef 錯誤,你需要啓動內置的 compdef,你可以在將以下行添加到開始的 ~/.zshrc 文件中:

autoload -Uz compinit
compinit

此外我們還可以爲 kubectl 定義一個別名,比如定義成 k:

echo 'alias k=kubectl' >> ~/.zshrc

如果定義了別名也可以通過擴展 shell 補全來兼容該別名:

echo 'complete -F __start_kubectl k' >> ~/.zshrc

另外還推薦配置 zsh 下面的 zsh-autosuggestions、zsh-syntax-highlighting、kubectl 這幾個插件,可以自動提示之前我們使用過的一些歷史命令,在 ~/.zshrc 中添加插件配置:

plugins=(git zsh-autosuggestions zsh-syntax-highlighting kubectl)

查看資源規範

當你創建 YAML 資源定義時,你需要知道字段以及這些資源的意義,kubectl 提供了 kubectl explain 命令,它可以在終端中正確地輸入所有資源規範。

kubectl explain 的用法如下:

kubectl explain resource[.field]...

該命令輸出所請求資源或字段的規範,默認情況下,kubectl explain 僅顯示單個級別的字段,你可以使用 --recursive 標誌來顯示所有級別的字段:

kubectl explain deployment.spec --recursive

如果你不確定哪個資源名稱可以用於 kubectl explain,你可以使用以下命令查看:

kubectl api-resources

該命令以複數形式顯示資源名稱(如 deployments),它同時顯示資源名稱的縮寫(如 deploy),這些名稱對於 kubectl 都是等效的,我們可以使用它們中的任何一個。例如,以下命令效果都是一樣的:

kubectl explain deployments.spec
# or
kubectl explain deployment.spec
# or
kubectl explain deploy.spec

自定義列輸出格式

kubectl get 命令默認的輸出方式如下(該命令用於讀取資源):

➜  ~ kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-54f4485448-kwr45   1/1     Running   1          67d
nginx-674ff86d-t6gbd                      1/1     Running   0          67d

默認的輸出格式包含有限的信息,我們可以看到每個資源僅顯示了一些字段,而不是完整的資源定義。此時,自定義列輸出格式就非常有用了,它使你可以自由定義列和想在其中顯示的數據,你可以選擇資源的任何字段,使其在輸出中顯示爲單獨的列。自定義列輸出選項的用法如下:

-o custom-columns=<header>:<jsonpath>[,<header>:<jsonpath>]...

你必須將每個輸出列定義爲 <header>:<jsonpath> 對:

讓我們看一個簡單的例子:

➜  ~ kubectl get pods -o custom-columns='NAME:metadata.name'
NAME
nfs-client-provisioner-54f4485448-kwr45
nginx-674ff86d-t6gbd

在這裏,輸出包括顯示所有 Pod 名稱的一列,選擇 Pod 名稱的表達式是 meta.name,因爲 Pod 的名稱是在 Pod 資源的 metadata 屬性下面的 name 字段中定義的(我們可以使用 kubectl explain pod.metadata.name 進行查找)。

現在,假設你想在輸出中添加一個附加列,比如顯示每個 Pod 在其上運行的節點,那麼我們只需在自定義列選項中添加適當的列規範即可:

➜  ~ kubectl get pods -o custom-columns='NAME:metadata.name,NODE:spec.nodeName'
NAME                                      NODE
nfs-client-provisioner-54f4485448-kwr45   172.27.0.2
nginx-674ff86d-t6gbd                      172.27.0.2

選擇節點名稱的表達式是 spec.nodeName,這是因爲已將 Pod 調度的節點保存在 Pod 的 spec.nodeName 字段中了。不過需要請注意的是 Kubernetes 資源字段是區分大小寫的。

我們可以通過這種方式將資源的任何字段設置爲輸出列,只需瀏覽資源規範並嘗試使用任何你喜歡的字段即可。當然我們需要對字段選擇的 JSONPath 表達式要有一定的瞭解。

JSONPath 表達式

用於選擇資源字段的表達式基於 JSONPath 的。JSONPath 是一種用於從 JSON 文檔提取數據的語言(類似於 XPath for XML),選擇單個字段只是 JSONPath 的最基本用法,它還有很多其他功能,例如 list selector、filter 等。

但是,kubectl explain 僅支持 JSONPath 功能的子集,下面我們通過一些示例用法來總結下這些使用規則:

選擇一個列表的所有元素

# 獲取Pod下面的所有容器鏡像
➜  ~ kubectl get pods -o custom-columns='IMAGES:spec.containers[*].image'
IMAGES
cnych/nfs-subdir-external-provisioner:v4.0.2
nginx:latest

選擇一個列表的指定元素

# 獲取Pod下面第一個容器的鏡像
➜  ~ kubectl get pods -o custom-columns='IMAGE:spec.containers[0].image'
IMAGE
cnych/nfs-subdir-external-provisioner:v4.0.2
nginx:latest

選擇匹配過濾表達式的列表元素

➜  ~ kubectl get pods -o custom-columns='DATA:spec.containers[?(@.image!="nginx:latest")].image'
DATA
cnych/nfs-subdir-external-provisioner:v4.0.2
<none>

選擇指定位置下的所有字段

➜  ~ kubectl get pods -o custom-columns='DATA:metadata.*'
DATA
default,[map[apiVersion:apps/v1 blockOwnerDeletion:true controller:true kind:ReplicaSet name:nfs-client-provisioner-54f4485448 uid:39912344-d707-4029-8da8-5269cfcae9e9]],4926994155,map[app:nfs-client-provisioner pod-template-hash:54f4485448],2021-07-06T04:08:48Z,nfs-client-provisioner-54f4485448-,[map[apiVersion:v1 fieldsType:FieldsV1 fieldsV1:map[f:metadata:map[f:generateName:map[] f:labels:map[.:map[] f:app:map[] f:pod-template-hash:map[]] f:ownerReferences:map[.:map[] k:{"uid":"39912344-d707-4029-8da8-5269cfcae9e9"}:map[.:map[] f:apiVersion:map[] f:blockOwnerDeletion:map[] f:controller:map[] f:kind:map[] f:name:map[] f:uid:map[]]]] f:spec:map[f:containers:map[k:{"name":"nfs-client-provisioner"}:map[.:map[] f:env:map[.:map[] k:{"name":"NFS_PATH"}:map[.:map[] f:name:map[] f:value:map[]] k:{"name":"NFS_SERVER"}:map[.:map[] f:name:map[] f:value:map[]] k:{"name":"PROVISIONER_NAME"}:map[.:map[] f:name:map[] f:value:map[]]] f:image:map[] f:imagePullPolicy:map[] f:name:map[] f:resources:map[] f:terminationMessagePath:map[] f:terminationMessagePolicy:map[] f:volumeMounts:map[.:map[] k:{"mountPath":"/persistentvolumes"}:map[.:map[] f:mountPath:map[] f:name:map[]]]]] f:dnsPolicy:map[] f:enableServiceLinks:map[] f:restartPolicy:map[] f:schedulerName:map[] f:securityContext:map[] f:serviceAccount:map[] f:serviceAccountName:map[] f:terminationGracePeriodSeconds:map[] f:volumes:map[.:map[] k:{"name":"nfs-client-root"}:map[.:map[] f:name:map[] f:nfs:map[.:map[] f:path:map[] f:server:map[]]]]]] manager:kube-controller-manager operation:Update time:2021-07-06T04:08:48Z] map[apiVersion:v1 fieldsType:FieldsV1 fieldsV1:map[f:status:map[f:conditions:map[.:map[] k:{"type":"PodScheduled"}:map[.:map[] f:lastProbeTime:map[] f:lastTransitionTime:map[] f:message:map[] f:reason:map[] f:status:map[] f:type:map[]]]]] manager:kube-scheduler operation:Update time:2021-07-06T04:08:49Z] map[apiVersion:v1 fieldsType:FieldsV1 fieldsV1:map[f:metadata:map[f:annotations:map[.:map[] f:tke.cloud.tencent.com/networks-status:map[]]]] manager:multus operation:Update time:2021-07-06T04:09:24Z] map[apiVersion:v1 fieldsType:FieldsV1 fieldsV1:map[f:status:map[f:conditions:map[k:{"type":"ContainersReady"}:map[.:map[] f:lastProbeTime:map[] f:lastTransitionTime:map[] f:status:map[] f:type:map[]] k:{"type":"Initialized"}:map[.:map[] f:lastProbeTime:map[] f:lastTransitionTime:map[] f:status:map[] f:type:map[]] k:{"type":"Ready"}:map[.:map[] f:lastProbeTime:map[] f:lastTransitionTime:map[] f:status:map[] f:type:map[]]] f:containerStatuses:map[] f:hostIP:map[] f:phase:map[] f:podIP:map[] f:podIPs:map[.:map[] k:{"ip":"172.16.0.87"}:map[.:map[] f:ip:map[]]] f:startTime:map[]]] manager:kubelet operation:Update time:2021-08-02T23:00:33Z]],nfs-client-provisioner-54f4485448-kwr45,/api/v1/namespaces/default/pods/nfs-client-provisioner-54f4485448-kwr45,9c445349-42ce-4e38-b20a-41bb47587d7e,map[tke.cloud.tencent.com/networks-status:[{
    "name""tke-bridge",
    "ips"[
        "172.16.0.87"
    ],
    "default": true,
    "dns"{}
}]]
......

選擇所有具有指定名稱的字段,無論其位置如何

➜  ~ kubectl get pods -o custom-columns='IMAGE:..image'
IMAGE
cnych/nfs-subdir-external-provisioner:v4.0.2,cnych/nfs-subdir-external-provisioner:v4.0.2
nginx:latest,nginx:latest

其中的 [ ] 運算符特別重要,Kubernetes 資源的許多字段都是列表,使用此運算符可以選擇這些列表中的某一些元素,它通常與通配符一起使用 [*],以選擇列表中的所有項目。

示例應用程序

使用自定義列輸出格式有無限可能,因爲你可以在輸出中顯示資源的任何字段或字段組合。以下是一些示例應用程序,但你可以自己探索並找到對你有用的應用程序。

提示:如果你經常使用這些命令,則可以爲其創建一個 shell 別名。

顯示 Pod 的容器鏡像

➜  ~ kubectl get pods -o custom-columns='NAME:metadata.name,IMAGES:spec.containers[*].image'
NAME                                      IMAGES
nfs-client-provisioner-54f4485448-kwr45   cnych/nfs-subdir-external-provisioner:v4.0.2
nginx                                     nginx
nginx-674ff86d-t6gbd                      nginx:latest

此命令顯示每個 Pod 的所有容器鏡像的名稱。因爲一個 Pod 可能包含多個容器。在這種情況下,單個 Pod 的容器鏡像在同一列中顯示爲由逗號分隔的列表。

顯示節點的可用區

➜  ~ kubectl get nodes \
  -o custom-columns='NAME:metadata.name,ZONE:metadata.labels.failure-domain\.beta\.kubernetes\.io/zone'
NAME         ZONE
172.27.0.2   160001

如果你的 Kubernetes 集羣部署在公有云上,則此命令很有用,它顯示每個節點所在的可用區。每個節點的可用區均通過特殊的 failure-domain.beta.kubernetes.io/zone 標籤獲得,如果集羣在公有云基礎架構上運行,則將自動創建此標籤,並將其值設置爲節點的可用性區域的名稱。

標籤不是 Kubernetes 資源規範的一部分,但是,如果將節點輸出爲 YAML 或 JSON,則可以看到它的相關信息:

kubectl get nodes -o yaml
# or
kubectl get nodes -o json

多集羣和命名空間切換

當 kubectl 向 Kubernetes API 發出請求時,它將讀取 kubeconfig 文件,以獲取它需要訪問的所有連接參數並向 APIServer 發出請求。默認的 kubeconfig 文件是 ~/.kube/config,在使用多個集羣時,在 kubeconfig 文件中配置了多個集羣的連接參數,所以我們需要一種方法來告訴 kubectl 要將其連接到哪個集羣中。在集羣中,我們可以設置多個命名空間,Kubectl 還可確定 kubeconfig 文件中用於請求的命名空間,所以同樣我們需要一種方法來告訴 kubectl 要使用哪個命名空間。

此外我們還可以通過在 KUBECONFIG 環境變量來設置它們,還可以爲每個 kubectl 命令使用 --kubeconfig 選項覆蓋默認的 kubeconfig 文件。

kubeconfig

kubeconfig 文件由一組上下文組成,上下文包含以下三個元素:

通常大部分用戶在其 kubeconfig 文件中爲每個集羣使用單個上下文,但是,每個集羣也可以有多個上下文,它們的用戶或命名空間不同,但並不太常見,因此集羣和上下文之間通常存在一對一的映射。

在任何指定時間,這些上下文其中之一都可以被設置爲當前上下文:

當 kubectl 讀取 kubeconfig 文件時,它總是使用當前上下文中的信息,所以在上面的示例中,kubectl 將連接到 Hare 集羣。因此,要切換到另一個集羣時,你只需在 kubeconfig 文件中更改當前上下文即可:

這樣 kubectl 現在將連接到 Fox 集羣,並切換到同一集羣中的另一個命名空間,可以更改當前上下文的命名空間元素的值:

在上面的示例中,kubectl 現在將在 Fox 集羣中使用 Prod 命名空間,而不是之前設置的 Test 命名空間了。理論上講,我們可以通過手動編輯 kubeconfig 文件來進行這些更改,kubectl config 也命令提供了用於編輯 kubeconfig 文件的子命令:

比如現在我有兩個 kubeconfig 文件,分別連接兩個集羣,現在我們可以使用下面的命令來合併兩個 kubeconfig 文件:

➜  ~ cp $HOME/.kube/config $HOME/.kube/config.backup.$(date +%Y-%m-%d.%H:%M:%S)
KUBECONFIG=$HOME/.kube/config:$HOME/.kube/ydzs-config kubectl config view --merge --flatten > $HOME/.kube/merged_kubeconfig && mv $HOME/.kube/merged_kubeconfig $HOME/.kube/config
➜  ~ kubectl config get-contexts
CURRENT   NAME                           CLUSTER   AUTHINFO           NAMESPACE
          cls-9kl736yn-context-default   tke       admin
*         kubernetes-admin@kubernetes    local     kubernetes-admin   default

通過上面的命令可以將兩個 kubeconfig 合併到一起,我們可以看到現在有兩個集羣和兩個上下文,在操作資源對象的時候可以通過使用參數 --context 來指定操作的集羣:

➜  ~ kubectl get pods --context=cls-9kl736yn-context-default
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-54f4485448-kwr45   1/1     Running   1          67d
nginx-674ff86d-t6gbd                      1/1     Running   0          67d
➜  ~ kubectl get pods --context=kubernetes-admin@kubernetes
NAME                                      READY   STATUS    RESTARTS   AGE
nginx                                     1/1     Running   0          26d

我們可以看到操作的時候是非常繁瑣的,下面我們使用其他的工具來幫助我們自動進行這些更改。

Kubectx

Kubectx 可以有效幫助我們在集羣和命名空間之間進行切換,該工具提供了 kubectxkubens 命令,使我們可以分別更改當前上下文和命名空間。如果每個集羣只有一個上下文,則更改當前上下文意味着更改集羣。

如果我們已經安裝過 kubectl 插件管理工具 Krew,則直接使用下面的命令來安裝 Kubectx 插件即可:

kubectl krew install ctx
kubectl krew install ns

安裝完成後,可以使用 kubectl ctxkubectl ns 命令進行操作。但是需要注意這種方式不會安裝 shell 自動補全腳本,如果需要,可以使用另外的方式進行安裝,比如 macOS 下面使用 Homebrew 進行安裝:

brew install kubectx

此安裝命令將自動設置 bash/zsh/fish 自動補全腳本,由於經常需要切換不同的集羣,很可能會誤操作集羣,這個時候有個提示就很棒了,我們可以使用 kube-ps1 工具來修改 PS1

不過由於我這裏本地使用的是 oh-my-zsh,所以可以不用安裝,直接在 ~/.zshrc 開啓 plugin 加上 kube-ps1 就可以了,然後自定義一下,重新 source 下即可:

PROMPT='$(kube_ps1)'$PROMPT
KUBE_PS1_PREFIX=""
KUBE_PS1_SYMBOL_DEFAULT=""
KUBE_PS1_DIVIDER="-"
KUBE_PS1_SUFFIX=" "

現在我們只需要輸入 kubectx 命令就可以切換集羣了:

由於我們配置了 kube-ps1,所以在操作的終端前面也直接顯示了當前操作的集羣,防止操作集羣錯誤。

kubectx 的另一個十分有用的功能是交互模式,這需要與 fzf 工具一起工作(安裝 fzf 會自動啓用 kubectx 交互模式)。交互式模式允許你通過交互式模糊搜索界面選擇目標上下文或命名空間。

kubectl 插件

從 1.12 版開始,kubectl 就提供了插件機制,可讓你使用自定義命令擴展 kubectl,Kubectl 插件作爲簡單的可執行文件分發,名稱形式爲 kubectl-x,前綴 kubectl- 是必填項,其後是允許調用插件的新的 kubectl 子命令。

要安裝插件,你只需要將 kubectl-x 文件複製到 PATH 中的任何目錄並使其可執行,之後,你可以立即使用 kubectl x 調用插件。你可以使用以下命令列出系統上當前安裝的所有插件:

kubectl plugin list

Kubectl 插件可以像軟件包一樣共享和重用,但是在哪裏可以找到其他人共享的插件?Krew 項目旨在爲共享、查找、安裝和管理 kubectl 插件提供統一的解決方案。Krew 根據 kubectl 插件進行索引,你可以從中選擇和安裝。當然 krew 本身就是一個 kubectl 插件,這意味着,安裝 krew 本質上就像安裝其他任何 kubectl 插件一樣。你可以在 GitHub 頁面上找到 krew 的詳細安裝說明:https://github.com/kubernetes-sigs/krew。

下面是一些重要的 krew 命令:

# Search the krew index (with an optional search query)
kubectl krew search [<query>]

# Display information about a plugin
kubectl krew info <plugin>

# Install a plugin
kubectl krew install <plugin>

# Upgrade all plugins to the newest versions
kubectl krew upgrade

# List all plugins that have been installed with krew
kubectl krew list

# Uninstall a plugin
kubectl krew remove <plugin>

需要注意 kubectl krew list 命令僅列出已與 krew 一起安裝的插件,而 kubectl plugin list 命令列出了所有插件,即與 krew 一起安裝的插件和以其他方式安裝的插件。

創建插件

我們也可以很方便創建自己的 kubectl 插件,只需要創建一個執行所需操作的可執行文件,將其命名爲 kubectl-x,然後按照如上所述的方式安裝即可。可執行文件可以是任何類型,可以是 Bash 腳本、已編譯的 Go 程序、Python 腳本,這些類型實際上並不重要。唯一的要求是它可以由操作系統直接執行。

讓我們現在創建一個示例插件。前面我們使用 kubectl 命令列出每個 Pod 的容器鏡像,我們可以輕鬆地將此命令轉換爲可以使用 kubectl img 調用的插件。只需創建一個名爲 kubectl-img 的文件,其內容如下:

#!/bin/bash
kubectl get pods -o custom-columns='NAME:metadata.name,IMAGES:spec.containers[*].image'

現在,使用 chmod + x kubectl-img 使該文件可執行,並將其移動到 PATH 中的任何目錄,之後,你可以立即將插件與 kubectl img 一起使用了:

➜  ~ kubectl img
NAME                                      IMAGES
nfs-client-provisioner-54f4485448-kwr45   cnych/nfs-subdir-external-provisioner:v4.0.2
nginx-674ff86d-t6gbd                      nginx:latest

kubectl 插件可以用任何編程或腳本語言編寫,如果使用 Shell 腳本,則具有可以輕鬆從插件調用 kubectl 的優勢。但是,你可以使用真實的編程語言編寫更復雜的插件,例如使用 Kubernetes 客戶端庫,如果使用 Go,還可以使用 cli-runtime 庫,該庫專門用於編寫 kubectl 插件。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-h7ay_-DzBI8ptphHUNw4g