kubectl に関する投稿を表示しています

kubectl で Service から Pod の紐づけを一発で確認した

まとめとしては -o json | jq な感じで頑張るのがとりあえずは正解っぽい。

$ kubectl get -o json endpoints | jq '.items[] | [.metadata.name, ([.subsets[].addresses[].targetRef.name] | join(", "))] | @tsv' --raw-output
http-server    http-86d67d8d47-46fm8, http-86d67d8d47-x487n, http-86d67d8d47-nxgdx
http-server-dev    http-dev-58fc975f8f-z2lvw, http-dev-58fc975f8f-tjczr

シェルむけの関数を組んで kubectl にオプション渡せるようにしたら便利、かも、と思ってざっくり書いた。
あたらしく Service を作ったりときにセレクタミスってないかな?とかを見るのに便利、かも。

#!/bin/sh
function kube_lookup_pod() {
    kubectl get -o json endpoints $@ \
    | jq -r \
      '["Service", "Pods"], (.items[] | [.metadata.name, ([.subsets[].addresses[].targetRef.name] | join(", "))]) | @tsv' \
    | column -t
}
$ kube_lookup_pod --namespace foo-namespace
Service               Pods
http-server           http-86d67d8d47-46fm8,      http-86d67d8d47-x487n,      http-86d67d8d47-nxgdx
http-server-dev       http-dev-58fc975f8f-z2lvw,  http-dev-58fc975f8f-tjczr

そこまでの経緯もメモっておく。

Kubernetes の Service の一覧はこうやってみえるが、これはどれに紐付いているかが分からない。

$ kubectl get svc
NAME                   TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE
http-server            ClusterIP   None         <none>        9100/TCP            10h
http-server-dev        ClusterIP   None         <none>        9100/TCP            10h

ワンチャン describe なら Endpoint がでてくるので、ギリギリわかる。

$ kubectl describe svc http-server
Name:              http-server
Namespace:         foo-namespace
Labels:            <none>
Annotations:       <none>
Selector:          app=http-server
Type:              ClusterIP
IP:                None
Port:              http-server  9100/TCP
TargetPort:        9100/TCP
Endpoints:         10.108.30.146:9100,10.108.35.228:9100,10.108.54.229:9100
Session Affinity:  None
Events:            <none>

Endpoint も get できるがこのままではわからない。

$ kubectl get endpoints
NAME                   ENDPOINTS                                                              AGE
http-server            10.108.30.146:9100,10.108.35.228:9100,10.108.54.229:9100               10h
http-server-dev        10.108.30.149:9100,10.108.32.247:9100                                  10h

describe してもだめ。

$ kubectl describe endpoints http-server
Name:         http-server
Namespace:    foo-namespace
Labels:       <none>
Annotations:  <none>
Subsets:
  Addresses:          10.108.30.146,10.108.35.228,10.108.54.229
  NotReadyAddresses:  <none>
  Ports:
    Name         Port  Protocol
    ----         ----  --------
    http-server  9100  TCP

Events:  <none>

おもむろに -o json やったら実はデータとしては取れることがわかった。

$ kubectl get endpoints http-server -o json
{
    "apiVersion": "v1",
    "kind": "Endpoints",
    "metadata": {
        "name": "http-server",
        ...省略...
    },
    "subsets": [
        {
            "addresses": [
                {
                    ...省略...
                    "ip": "10.108.30.146",
                    "nodeName": ".......",
                    "targetRef": {
                        "kind": "Pod",
                        "name": "http-86d67d8d47-46fm8",
                        "namespace": "foo-namespace",
...省略...

あとは jq でがんばったら取れる。

$ kubectl get -o json endpoints | jq '.items[] | [.metadata.name, ([.subsets[].addresses[].targetRef.name] | join(", "))] | @tsv' --raw-output
http-server    http-86d67d8d47-46fm8, http-86d67d8d47-x487n, http-86d67d8d47-nxgdx
http-server-dev    http-dev-58fc975f8f-z2lvw, http-dev-58fc975f8f-tjczr

書いてるときに試行錯誤してたけど jq の使い方について学びを得た

  • Object ならキーを選んで、配列ならインデックスを選ぶか [] で全選択して、というのをパイプしたら概ね抽出できる
  • join は配列に対してしか使えないので、一覧が出てきそうなやつでも配列にしてからパイプする
  • フラットな配列なら末尾で @csv や @tsv すると便利、そのあと column にパイプするとさらに便利
  • そのときは --raw-output オプションもセットでやると OK
  • あとはマニュアルとにらめっこ jq Manual (development version)