1. 程式人生 > >kubernetes叢集管理命令(二)

kubernetes叢集管理命令(二)

系列目錄

上一節我們介紹了一些基本的命令,這一節我們介紹一些更為複雜的命令.

pod排序

使用kubectl get pod獲取pod資源預設是以名稱排序的,有些時候我們可能希望按其它順序排序.比如說我們想要按照節點來排序.以便可以看到不同的節點上都執行著哪些pod.

這個需求可以使用linux命令很簡單實現.使用kubectl get pod加上-owide引數就可以顯示pod所在的節點.我們再使用linux sort命令就可以對結果按照特定欄位排序了.以下示例是按節點排序後的結果

[centos@k8s-master ~]$ kubectl get pod -owide|sort -k 7
sagent-b4dd8b5b9-5m2jc                     1/1     Running   0          15h     10.244.5.17   k8s-node1   <none>           <none>
consul-0                                   1/1     Running   0          2d17h   10.244.2.27   k8s-node2   <none>           <none>
consul-2                                   1/1     Running   0          2d17h   10.244.2.28   k8s-node2   <none>           <none>
stodagent-6f47976ccb-8fzmv                 1/1     Running   0          2d17h   10.244.2.23   k8s-node2   <none>           <none>
stodagent-6f47976ccb-vf7kx                 1/1     Running   0          2d17h   10.244.2.22   k8s-node2   <none>           <none>
trackingapi-gateway-dep-79bb86bb57-x9xzp   1/1     Running   0          2d17h   10.244.2.24   k8s-node2   <none>           <none>
sagent-b4dd8b5b9-6mmst                     1/1     Running   0          15h     10.244.6.6    k8s-node3   <none>           <none>
sagent-b4dd8b5b9-zq649                     1/1     Running   0          15h     10.244.7.7    k8s-node4   <none>           <none>
stodagent-6f47976ccb-j7m8b                 1/1     Running   0          2d17h   10.244.3.6    k8s-node5   <none>           <none>
consul-1                                   1/1     Running   0          2d17h   10.244.3.13   k8s-node5   <none>           <none>
easymock-dep-84767b6f75-l84r4              1/1     Running   0          15h     10.244.8.8    k8s-node6   <none>           <none>
NAME                                       READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES

我們可以看到,已經以節點名稱來排序的,這裡不太優雅的是標題被排在了最後面.但是無傷大雅.

其實kubectl get命令有一個--sort-by引數.我們可以通過它來指定要按照資源的哪一個欄位來排序,而不侷限於展示出的欄位.以下是使用--sort-by引數按節點名稱排序後的結果.

[centos@k8s-master ~]$ kubectl get pod --sort-by='{.spec.nodeName}' -owide
NAME                                       READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
sagent-b4dd8b5b9-5m2jc                     1/1     Running   0          15h     10.244.5.17   k8s-node1   <none>           <none>
consul-0                                   1/1     Running   0          2d17h   10.244.2.27   k8s-node2   <none>           <none>
stodagent-6f47976ccb-8fzmv                 1/1     Running   0          2d17h   10.244.2.23   k8s-node2   <none>           <none>
consul-2                                   1/1     Running   0          2d17h   10.244.2.28   k8s-node2   <none>           <none>
stodagent-6f47976ccb-vf7kx                 1/1     Running   0          2d17h   10.244.2.22   k8s-node2   <none>           <none>
trackingapi-gateway-dep-79bb86bb57-x9xzp   1/1     Running   0          2d17h   10.244.2.24   k8s-node2   <none>           <none>
sagent-b4dd8b5b9-6mmst                     1/1     Running   0          15h     10.244.6.6    k8s-node3   <none>           <none>
sagent-b4dd8b5b9-zq649                     1/1     Running   0          15h     10.244.7.7    k8s-node4   <none>           <none>
consul-1                                   1/1     Running   0          2d17h   10.244.3.13   k8s-node5   <none>           <none>
stodagent-6f47976ccb-j7m8b                 1/1     Running   0          2d17h   10.244.3.6    k8s-node5   <none>           <none>
easymock-dep-84767b6f75-l84r4              1/1     Running   0          15h     10.244.8.8    k8s-node6   <none>           <none>

除了展示出來的欄位外,我們還可以按照沒有展示出來的欄位進行排序.比如我們可以按照startTime來排序,看看哪些pod執行的時間較長.

[centos@k8s-master ~]$ kubectl get pod --sort-by='{.status.startTime}'
NAME                                       READY   STATUS             RESTARTS   AGE
stodagent-6f47976ccb-vf7kx                 1/1     Running            0          2d18h
stodagent-6f47976ccb-j7m8b                 1/1     Running            0          2d18h
stodagent-6f47976ccb-8fzmv                 1/1     Running            0          2d18h
trackingapi-gateway-dep-79bb86bb57-x9xzp   1/1     Running            0          2d18h
consul-0                                   1/1     Running            0          2d18h
consul-1                                   1/1     Running            0          2d17h
consul-2                                   1/1     Running            0          2d17h
sagent-b4dd8b5b9-5m2jc                     1/1     Running            0          16h
sagent-b4dd8b5b9-zq649                     1/1     Running            0          16h
sagent-b4dd8b5b9-6mmst                     1/1     Running            0          16h
easymock-dep-84767b6f75-l84r4              1/1     Running            0          15h
redis-cache-f87d8488c-v4zjx                0/1     ErrImagePull       0          57s
redis-cache-f87d8488c-4d9dl                0/1     ImagePullBackOff   0          57s
redis-cache-f87d8488c-kxc89                0/1     ImagePullBackOff   0          57s

看了以後輸出內容以後,大家可能一頭霧水,以上到底是不是按啟動時間排序的?如何直接地看到是按啟動時間排序的呢?其實實際上確實是按照啟動時間排序了,為民展示此示例,我剛剛不久啟動了三個無法執行的redis例項,它們被排在了最下面.

我們能不能把startTime欄位也輸出出來呢,這樣就可以直接地看到輸出時間了,是不是按這個時間排序的也就一目瞭然了.答案是肯定的.

自定義顯示欄位

前面一節我們遇到一個問題,我們有一個需求把pod的startTime顯示出來.其實這個需求是可以實現的,kubectl get的輸入格式引數-o(或--output)接收一個custom-columns自定義列的格式.我們可以通過它來實現自定義輸出格式.

格式為:
-o=custom-columns=列名:欄位值,列名:欄位值

其中欄位值是通過資源的定義檔案選擇出來的.

以下示例我們展示出pod的name和startTime

[centos@k8s-master ~]$  kubectl get pod --sort-by=.status.startTime  -o=custom-columns=name:.metadata.name,startTime:.status.startTime
name                                       startTime
stodagent-6f47976ccb-vf7kx                 2019-05-14T07:19:05Z
stodagent-6f47976ccb-j7m8b                 2019-05-14T07:19:05Z
stodagent-6f47976ccb-8fzmv                 2019-05-14T07:19:05Z
trackingapi-gateway-dep-79bb86bb57-x9xzp   2019-05-14T07:19:06Z
consul-0                                   2019-05-14T07:19:28Z
consul-1                                   2019-05-14T07:25:06Z
consul-2                                   2019-05-14T07:25:16Z
sagent-b4dd8b5b9-5m2jc                     2019-05-16T09:20:17Z
sagent-b4dd8b5b9-zq649                     2019-05-16T17:09:37Z
sagent-b4dd8b5b9-6mmst                     2019-05-16T17:19:59Z
easymock-dep-84767b6f75-l84r4              2019-05-16T18:00:07Z
redis-cache-f87d8488c-v4zjx                2019-05-17T01:21:54Z
redis-cache-f87d8488c-4d9dl                2019-05-17T01:21:54Z
redis-cache-f87d8488c-kxc89                2019-05-17T09:11:11Z

這樣就可以一目瞭解地看到它們是按時間先後順序排序的.但是我們可以看到,命令變得有點複雜了,如果想要和像預設輸出一樣把那些欄位都展示出來,是不是需要定義更多的自定義輸出欄位,能不能在預設的輸出欄位後面追加自定義欄位呢.答案是否定的,目前無法做到.有使用者建議增加--extra-columns引數在預設輸出的基礎上增加額外輸出欄位.但是截至目前這個pr還沒有合併.待正式釋出可有還需要等待數月.

按時間排序kubernetes裡的事件資源

有時候為了排查錯誤,我們可能需要檢視kubernetes裡的事件資源,我們可以按照時間順序以方便檢視

kubectl get events --sort-by=.metadata.creationTimestamp

分別使用go-template,jsonpath,yq,jq來獲取一個pod裡的映象

以下我們使用四個示例來展示如何獲取一個叫作consul-0的pod的image(大家可以使用任意一個pod來做練習)

一句話,條條大路通羅馬,只要能熟悉掌握其中一種方法便可以完成我們日常工作中的任務,大家不必把所有工具都掌握,根據實際情況和自己知識體系來選擇.

使用to-template獲取

命令如下

[centos@k8s-master ~]$ kubectl get pod consul-0 -ogo-template='{{range .spec.containers}}{{.image}}{{end}}'
consul:latest

range函式用來遍歷集合物件.end用於結束遍歷

使用jsonpath

kubectl get pod consul-0 -ojsonpath='{range .spec.containers[*]}{.image}{end}'
consul:latest

這裡和上面的go-template非常類似,不同的是陣列物件後面要跟中括號[]以表明是陣列,中括號裡帶上星號(*)表示索引所有.

jsonpath與go-template不同的是,jsonpath除了可以使用星號*號索引所有的叢集元素以外,還可以使用數字索引(同其它程式語言一樣,0代表第一個元素)或者範圍索引(例如[0:1],[:1])

以上命令都不夠簡潔.使用jsonpath還有一種更為簡潔的方法,那就是遞迴查詢,這樣可以在不知道文件的詳細結構但是知道具體的屬性名的時候進行查詢.示例如下

[centos@k8s-master ~]$ kubectl get pod consul-0 -ojsonpath='{..image}'
consul:latest consul:latest

同上面相比,這裡的結果裡多出了一條記錄.其實這是因為status欄位裡的containerStatuses欄位裡也有image屬性.我們可以通過以下命令來進一步縮小查詢範圍

[centos@k8s-master ~]$ kubectl get pod consul-0 -ojsonpath='{.spec..image}'
consul:latest

使用yq工具

[centos@k8s-master ~]$ kubectl get po consul-0 -oyaml|yq r - spec.containers[*].image
- consul:latest

使用jq工具

示例如下:

[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|jq .spec.containers[].image
"consul:latest"

yq也可以使用遞迴查詢方式,只不不是特別優雅,並且限制也非常大,只適合簡單檢視

[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|jq '..|.image?'
null
null
null
null
null
"consul:latest"
null
null
null
null
null
null
null
null
null
null
null
"consul:latest"
null
null
null

以上輸出了很多null影響觀看,我們可以使用grep管道把它們過濾掉

[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|jq '..|.image?'|grep -v null
"consul:latest"
"consul:latest"

物件輸出

以上示例我們僅僅輸出了某一個欄位的值,但是如果在可程式設計環境中使用,我們需要的可能不僅僅是普通的數值,也有可能是更為複雜的物件類似,常見的為json物件.這裡我們介紹如何使用jq工具把結果輸出為物件型別

以下示例我們把image的名稱和image映象的名稱做為一個json物件輸出

[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|jq '{name:.spec.containers[0].name,image:.spec.containers[0].image}'
{
  "name": "consul",
  "image": "consul:latest"
}

以上僅輸出了一個物件,如果我們想要輸出的是陣列物件呢,這裡有些處理技術,請看以下示例:

[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|jq .status.conditions
[
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:19:28Z",
    "status": "True",
    "type": "Initialized"
  },
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:25:06Z",
    "status": "True",
    "type": "Ready"
  },
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:25:06Z",
    "status": "True",
    "type": "ContainersReady"
  },
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:19:28Z",
    "status": "True",
    "type": "PodScheduled"
  }
]

我們要把以下結果重新組裝,儲存為僅包含lastTransitionTime的叢集型別

以下是一種常見的錯誤操作方法:

[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|jq '.status.conditions[]|{lastTransitionTime:.lastTransitionTime}'
{
  "lastTransitionTime": "2019-05-14T07:19:28Z"
}
{
  "lastTransitionTime": "2019-05-14T07:25:06Z"
}
{
  "lastTransitionTime": "2019-05-14T07:25:06Z"
}
{
  "lastTransitionTime": "2019-05-14T07:19:28Z"
}

我們可以看到,我們實際上是取到了多個物件,但是它們並不是一個數組,想要獲取一個數組物件,正確的操作如下:

[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|jq '[.status.conditions[]|{lastTransitionTime:.lastTransitionTime}]'
[
  {
    "lastTransitionTime": "2019-05-14T07:19:28Z"
  },
  {
    "lastTransitionTime": "2019-05-14T07:25:06Z"
  },
  {
    "lastTransitionTime": "2019-05-14T07:25:06Z"
  },
  {
    "lastTransitionTime": "2019-05-14T07:19:28Z"
  }
]

大家仔細看看其中的差別在哪