JsonPathを変幻自在に操るKubernetes使いになろう
JSONPathとは
何かしらCLIツールでコマンドを実行した時にフォーマットをするようなものである。
たとえば以下のように実行する
kubectl get pods -o json
すると生のJSONが返ってくるので、このjsonにpathを指定することになる。
これに対してjsonpathを指定することによって効率のよく必要な情報が集められたりする。
以下のようにすると、キレイに取得をすることができます。
kubectl get pods hogehoge pod -o json | jq .
JSONPathの使い方
注意点
全体は''
で囲んで、中では""
を使うことに注意をしてください。
使える項目
1. Child Operator
子要素を取得するものである。
以下のように直接指定する。
kubectl get nodes -o=jsonpath="{.kind}"
=> List
kubectl get nodes -o=jsonpath="{.metadata}"
=> map[selfLink: resourceVersion:]
2. Recursive descent
再帰的に合致するものも抽出するものである。
kubectl get nodes -o=jsonpath="{..name}" => gke-locust-cluster-default-pool-8eb6b5df-9hjh gke-locust-cluster-default-pool-8eb6b5df-ctb5
この場合だと
{ name: hoge kind: { name: piyo } }
の場合は
hoge piyo
と返ってきます。
3. Wild card
すべてのオブジェクトを取得するものです。
kubectl get nodes -o=jsonpath="{.items[*].name}"
これをしない場合、つまり以下のように*
を取り除くと
kubectl get nodes -o=jsonpath="{.items[].name}"
最初の一つだけマッチして終了してしまうので注意が必要です。
4. Current Object
以下のFilterのSectionでもあるが、@
でそのレベルでのオブジェクトを取得できます。
kubectl get nodes -o=jsonpath="{@}"
ここでは@に対応するのはルートオブジェクトです。
5. Filter
条件にかけて抽出するものです。
[]
で挟んで?
を前において()
の中に条件を入れます。。Go templateで構成されているので、わからなければGo templateを参照するのがいいでしょう。
kubectl get nodes -o=jsonpath="{.users[?(@.name==“e2e”)].user.password}"
条件が真となるときのみ、ここでいう.users
は取得されます。
6. Range
以下のように特定のArrayを持つようなオブジェクトに対してfor文を行います。{end}
も忘れないでください。
kubectl get nodes -o=jsonpath="{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}"
7. Union
,
で配列などを定義できます。もちろんオブジェクトも可能です。
kubectl get nodes -o=jsonpath="{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}"
ユースケース
特定のNodeをDrainする
公式ページにもあった使い道です。
一般的には
- Node名を確認する
kubectl get nodes
- ひとつひとつDrainする
kubectl drain --force --ignore-daemonsets --delete-local-data --grace-period=10 [NODE1] kubectl drain --force --ignore-daemonsets --delete-local-data --grace-period=10 [NODE2] kubectl drain --force --ignore-daemonsets --delete-local-data --grace-period=10 [NODE3] ....
これをjsonpathを使うと
for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool -o=name); do kubectl drain --force --ignore-daemonsets --delete-local-data --grace-period=10 "$node"; done
このようにすることでNode名を知らなくても一気にdrainすることができます。ここで-lを指定しているのはラベルを使うためです。
Evicted
になったものだけ消す
以下のようにEvictedしていた結果、悲惨なことになっている状況を考えましょう。
spin-front50-8659899b76-v44rv 0/1 Evicted 0 3h42m spin-front50-8659899b76-v4ssm 0/1 Evicted 0 4h8m spin-front50-8659899b76-v4vpc 0/1 Evicted 0 154m spin-front50-8659899b76-vbhss 0/1 Evicted 0 141m spin-front50-8659899b76-vbr4l 0/1 Evicted 0 3h14m spin-front50-8659899b76-vpq62 0/1 Evicted 0 3h55m spin-front50-8659899b76-w5w2c 0/1 Evicted 0 4h8m ... spin-front50-8659899b76-w94rm 1/1 Running 1 20m spin-front50-8659899b76-z8lht 0/1 Evicted 0 19m spin-front50-8659899b76-zbv64 0/1 Evicted 0 166m spin-front50-8659899b76-zcfpz 0/1 Evicted 0 43m spin-front50-8659899b76-zffwd 0/1 Evicted 0 3h55m spin-front50-8659899b76-zgtj9 0/1 Evicted 0 117m spin-front50-8659899b76-zqsrc 0/1 Evicted 0 19m
一つだけRunning
になったので他が必要ないです。
以下のコマンドで消します。
for evictedPod in (kubectl get pods -l cluster=spin-front50 -o=jsonpath="{.items[?(@.status.reason=='Evicted')].metadata.name}" | tr " " "\n") kubectl delete pods $evictedPod end
付録
1. get pods
は一つのオブジェクトである
以下のようにitems
にPodが入るため、すべてを取り出すにはrange
を使うべきです。
{ "items": { Pod情報 } }