kubernetes叢集管理命令(三)

周國通發表於2019-06-20

系列目錄

前面兩節我們由淺入深介紹了不少kubernetes管理比較常用的命令.本節我們通過案例講解一些需要更為複雜的操作才能完成的命令.

選擇一個deployment下的所有pod

前面講到過,kubernetes的deployment和pod的命令上有關聯關係,我們可以通過檢視deployment的名稱,然後記下來,然後再查詢所有的pod通過grep輸入deploy的名稱為關鍵字進行過濾.

比如叢集中有以下deployment

[centos@k8s-master ~]$ kubectl get deploy
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
easymock-dep              1/1     1            1           21h
helloworld                1/1     1            1           88m
redis-cache               0/3     3            0           6h5m
sagent                    3/3     3            3           2d1h
stodagent                 3/3     3            3           6d23h
trackingapi-gateway-dep   1/1     1            1           28d

如果我們想要找helloworld所控制的pod,我們就可以通過以下命令來達到效果

[centos@k8s-master ~]$ kubectl get pod|grep helloworld
helloworld-66fc98fd57-lc7tm                1/1     Running            0          89m

但是這種匹配可能是不準確的,如果僅僅是檢視可能沒問題,但是在程式設計環境中這樣做顯然不是好的辦法.前面我們提到過先通過kubectl get deploy helloworld -ojson然後通過jq工具拿到selector,然後使用kubectl get pod -l=查詢到的標籤.這裡標籤需要我們手動輸入,因為選擇器裡過濾到的結果是"key":"value"格式,而-l接受的格式為key=value形式,當然我們也可以通過簡單的命令轉換以上兩種格式.但是選擇器裡也可能包含多個標籤(如下面示例),這樣我們通過簡單命令很難處理了.

[centos@k8s-master ~]$ kubectl get deploy helloworld -ojson|jq .spec.selector.matchLabels
{
  "app": "helloworld",
  "version": "1.0"
}

下面我們一步步講解如何通過可程式設計的方式根據以上資訊選擇名為helloworld的deployment所控制的所有pod

首先,以上的鍵appversion都是由使用者定義的,並且不知道共有多少個,我們沒法直接通過.屬性名的方式獲取到它,我們可以通過jq的to_entries把它轉為鍵值陣列,陣列是可以遍歷的.操作如下:

[centos@k8s-master ~]$ kubectl get deploy helloworld -ojson|jq '.spec.selector.matchLabels|to_entries'
[
  {
    "key": "app",
    "value": "helloworld"
  },
  {
    "key": "version",
    "value": "1.0"
  }
]

這樣陣列裡的所有物件都包含兩個鍵值,且鍵是固定的(分別為key和value),這樣key我們就都全知道了.下面我們把它們組裝成app=helloworld這樣形式,以便kubectl get po-l引數可用

[centos@k8s-master ~]$  kubectl get deploy helloworld -ojson|jq '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value)"'
"app=helloworld"
"version=1.0"

以上的操作有一點很關鍵那就是使用to_entries函式把物件轉為陣列.後面管道跟.[]獲取陣列物件.後面我們把結果放在""把結果拼接為字串這裡\為jq的語法,在字串裡使用""可以把後面跟的括號內的內容識別為命令,而不是普通字串.

這樣基本滿足要求了,但是有多個label時,-l接收的引數形式為lable1=value1,label2=value2這樣形式的.因此我們要刪除這兩個字串的換行符,把它們合併到一行,並且中間加一個逗號.

以上字串外面都包了一層引號(""),雖然-l變數也可以接收帶引號的,但是也可以不要引號,jq裡通過引數-r(aw)來獲取原始字串,要把結果合併為一行則使用-j(oin),改造後的命令如下

[centos@k8s-master ~]$  kubectl get deploy helloworld -ojson|jq -r -j '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value),"'
app=helloworld,version=1.0,

以上結果基本上達到預期效果,只是最後面多了一個逗號,我們可以接一個sed管道把它去掉

 kubectl get deploy helloworld -ojson|jq -r -j '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value),"'|sed "s/.$//"
app=helloworld,version=1.0

我們把它賦值給一個變數,然後在選擇pod的時候使用它

[centos@k8s-master ~]$ label=$( kubectl get deploy helloworld -ojson|jq -r -j '.spec.selector.matchLabels|to_entries|.[]|"\(.key)=\(.value),"'|sed "s/.$//")
[centos@k8s-master ~]$ kubectl get pod -l=$label
NAME                          READY   STATUS    RESTARTS   AGE
helloworld-66fc98fd57-lc7tm   1/1     Running   0          3h22m

顯示叢集中所有pod的標籤

把叢集中所有的pod全部列出來非常容易.使用kubectl get pod --all-namespace即可.重要的是我們要迴圈遍歷所有的pod,把它們的名稱和標籤資訊過濾出來展示.

前面我們說過,在使用kubectl get pod時如果使用-o=name便可以只列出pod的名稱.它並不是簡單地把kubectl get po命令展示的名稱過濾出來,而是通過資源型別/資源名稱的方式展示.比如有個pod名稱叫作consul-0,使用kubectl get pod -o=name展示出來它的名稱為pod/consul-0,這樣我們就可以直接使用kubectl get來獲取到它

[centos@k8s-master ~]$ kubectl get pod/consul-0
NAME       READY   STATUS    RESTARTS   AGE
consul-0   1/1     Running   0          3d2h

k8s除了支援kubectl get+資源型別+資源名稱外,還支援kubectl get 資源型別/資源名稱這種形式.雖然平時我們不經常這樣寫,但是有特定場景下非常有用.

這樣,我們就可以遍歷kubectl get pod -o=name的結果,在迴圈中取出每個pod的編排資訊,然後從中過濾出我們想要的資訊(即pod的標籤資訊),操作和上面獲取matchLabels有很多類似的地方.

關鍵程式碼如下:

[centos@k8s-master ~]$ for item in $( kubectl get pod --output=name); do kubectl get "$item" --output=json | jq -r '.metadata.labels | to_entries | .[] | " \(.key)=\(.value)"'; done
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-0
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-1
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-2
 app=easymock
 pod-template-hash=84767b6f75
 app=helloworld
 pod-template-hash=d5d5c5866
 version=1.0
 app=helloworld
 pod-template-hash=d5d5c5866
 version=1.0
 app=helloworld
...

以上迴圈獲取到的每一個pod的名稱,然後遍歷他們,取出它們的.metadata.labels欄位,後面是對鍵值的重新組裝,和上面獲取deploy下的pod一節的操作類似.

從輸出結果中可以看出,我們只輸出的所有pod的標籤,這樣可讀性是非常差的,我們也無法確定某一個標籤歸屬於哪一個pod.我們需要把它們的名字也輸出:

[centos@k8s-master ~]$ for item in $( kubectl get pod --output=name); do printf "Labels for %s\n" "$item"; kubectl get "$item" --output=json | jq -r '.metadata.labels | to_entries | .[] | " \(.key)=\(.value)"'; done
Labels for pod/consul-0
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-0
Labels for pod/consul-1
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-1
Labels for pod/consul-2
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-2
Labels for pod/easymock-dep-84767b6f75-l84r4
 app=easymock
 pod-template-hash=84767b6f75
Labels for pod/helloworld-d5d5c5866-24nzr
 app=helloworld
 pod-template-hash=d5d5c5866
 version=1.0
 ...

這查比前面清析一些了,但是仍然不是十分容易識別,我們在遍歷的時候每個item結束後輸出一個空行,這樣把不同的結果用空行隔離開來,可讀性更高.

[centos@k8s-master ~]$ for item in $( kubectl get pod --output=name); do printf "Labels for %s\n" "$item"; kubectl get "$item" --output=json | jq -r '.metadata.labels | to_entries | .[] | " \(.key)=\(.value)"';printf "\n"; done
Labels for pod/consul-0
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-0

Labels for pod/consul-1
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-1

Labels for pod/consul-2
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-2

Labels for pod/easymock-dep-84767b6f75-l84r4
 app=easymock
 pod-template-hash=84767b6f75

這樣基本ok了,我們使用grep把名稱著色顯示,這樣在螢幕上的輸出可讀性就更高了.

[centos@k8s-master ~]$ for item in $( kubectl get pod --output=name); do printf "Labels for %s\n" "$item"|grep --color -E '[^/]+$'; kubectl get "$item" --output=json | jq -r '.metadata.labels | to_entries | .[] | " \(.key)=\(.value)"';printf "\n"; done
Labels for pod/consul-0
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-0

Labels for pod/consul-1
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-1

Labels for pod/consul-2
 app=consul
 controller-revision-hash=consul-744777c4bd
 statefulset.kubernetes.io/pod-name=consul-2

大家從上面文字中可能並看不出差別,但是如果是在linux終端就可以看到pod的名稱都被著色顯示了.

相關文章