yq は YAML を操作できるコマンドラインツールで、Kubernetes 用のマニフェストの確認やクラスタの状態確認に利用できます。 この記事では yq の基本的な使い方と Kubernetes 環境での応用方法を紹介します。
基本的な使い方
yq eval
に続けて評価式を書くことで YAML の一部を表示したり編集したりすることができます。
$ yq eval [expression] [yaml_file] [flags]
eval
コマンドは e
と書くこともできます。
yq
は構文を色付けするので、次のように書くと kubectl
の出力を色付けできます。
$ kubectl get pod sample -o yaml | yq e . -
値の表示と配列アクセス
評価式にフィールド名を指定すると、そのフィールドだけを抜き出して表示できます。
Kubernetes リソースの .spec
フィールドだけを表示する、といった使い方ができます。
alpine.yaml
apiVersion: v1
kind: Pod
metadata:
name: alpine
spec:
containers:
- command:
- sleep
- inf
image: alpine:3.13.3
name: alpine
$ yq e .spec alpine.yaml
containers:
- command:
- sleep
- inf
image: alpine:3.13.3
name: alpine
$ yq e .spec.containers[0].name alpine.yaml
alpine
パイプとフィルタ
評価式はパイプ |
で連結できます。
$ yq e '.spec.containers | .[0] | .image' alpine.yaml
alpine:3.13.3
[]
を使うと配列の全ての要素に対して後続の処理を実行します。
$ # kind 環境を起動する
$ kind create cluster
$ kubectl get pod -n kube-system -o yaml | yq e '.items[].metadata.name' -
coredns-f9fd979d6-brw2g
coredns-f9fd979d6-mg9vv
etcd-kind-control-plane
kindnet-m4zzj
kube-apiserver-kind-control-plane
kube-controller-manager-kind-control-plane
kube-proxy-bnd47
kube-scheduler-kind-control-plane
select
を使うと条件を満たす要素を取り出せます。
$ kubectl get pod -n kube-system -o yaml | yq e '.items[].metadata.name | select(.=="kube*")' -
kube-apiserver-kind-control-plane
kube-controller-manager-kind-control-plane
kube-proxy-bnd47
kube-scheduler-kind-control-plane
便利なコマンド
Kubernetes クラスタの管理に使える便利なコマンドをまとめました。
特定の種類のリソースだけを表示する
複雑な YAML ファイルに含まれる特定の種類のリソースだけを表示できます。
$ yq e 'select(.kind=="Deployment")' manifest.yaml
一部のフィールドを除いて表示する
CRD を含む大きな YAML ファイルの概略を掴むのに便利です。
$ yq e 'del(.spec)' manifest.yaml
YAML の内容をソートする
YAML の差分を効率的に確認できます。
$ yq e 'sortKeys(..)' manifest.yaml
ラベルやアノテーションのキー一覧を表示する
$ kubectl get pod -n kube-system kube-apiserver-kind-control-plane -o yaml | yq e '.metadata.labels | keys | .[]' -
component
tier
ラベルやアノテーションの値を表示する
$ kubectl get pod -n kube-system kube-apiserver-kind-control-plane -o yaml | yq e '.metadata.labels["component"]' -
kube-apiserver
Pod に付いているラベルをすべて表示する
$ kubectl get pod -A -o yaml | yq e '.items[].metadata | . as $i ireduce({}; . * {$i.namespace: {$i.name: $i.labels}})' -
kube-system:
coredns-f9fd979d6-brw2g:
k8s-app: kube-dns
pod-template-hash: f9fd979d6
coredns-f9fd979d6-mg9vv:
k8s-app: kube-dns
pod-template-hash: f9fd979d6
etcd-kind-control-plane:
component: etcd
tier: control-plane
kindnet-m4zzj:
app: kindnet
controller-revision-hash: 869899dbb6
k8s-app: kindnet
pod-template-generation: "1"
tier: node
kube-apiserver-kind-control-plane:
component: kube-apiserver
tier: control-plane
kube-controller-manager-kind-control-plane:
component: kube-controller-manager
tier: control-plane
kube-proxy-bnd47:
controller-revision-hash: 6fbb4864f
k8s-app: kube-proxy
pod-template-generation: "1"
kube-scheduler-kind-control-plane:
component: kube-scheduler
tier: control-plane
local-path-storage:
local-path-provisioner-78776bfc44-bmtw9:
app: local-path-provisioner
pod-template-hash: 78776bfc44
ireduce
を使うと aggregation が書けます。
$ echo '[1, 2, 3]' | yq e '.[] as $i ireduce(0; . + $i)' -
6
特定の User や ServiceAccount に紐付いた RoleBinding を一覧表示する
$ kubectl get rolebinding -n kube-system -o yaml | yq e '.items[] | select(.subjects[] as $i ireduce(false; . or ($i.kind=="User" and $i.name=="system:kube-controller-manager"))) | .metadata.name' -
system::extension-apiserver-authentication-reader
system::leader-locking-kube-controller-manager
マニアックすぎですがこれは次のコマンドの応用です。
$ echo '[true, false]' | yq e 'select(.[] as $i ireduce(false; . or $i))' -
[true, false]
$ echo '[false, false]' | yq e 'select(.[] as $i ireduce(false; . or $i))' -
$
特定の User や ServiceAccount に紐付いた ClusterRoleBinding を一覧表示する
$ kubectl get clusterrolebinding -o yaml | yq e '.items[] | select(.subjects[] as $i ireduce(false; . or ($i.kind=="User" and $i.name=="system:kube-scheduler"))) | .metadata.name' -
system:kube-scheduler
system:volume-scheduler
roleRef
を参照して ClusterRole
を直接表示することもできます。
$ kubectl get clusterrolebinding -o yaml | yq e '.items[] | select(.subjects[] as $i ireduce(false; . or ($i.kind=="User" and $i.name=="system:kube-scheduler"))) | .roleRef.name' - | sort | uniq
system:kube-scheduler
system:volume-scheduler
全クラスタリソースと全 namespace リソースを表示する
本番環境でやると大変なことになりそう。 小規模なテスト環境で実行すると色々勉強になります。
$ kubectl get $(kubectl api-resources -o name | paste -sd ,) -A -o yaml 2>/dev/null | yq e '.items[] | . as $i ireduce({}; . *+ {$i.metadata.namespace: {$i.kind: [$i.metadata.name]}})' -
APIGroup/Version 付き
$ kubectl get $(kubectl api-resources -o name | paste -sd ,) -A -o yaml 2>/dev/null | yq e '.items[] | . as $i ireduce({}; . *+ {$i.metadata.namespace: {$i.apiVersion: {$i.kind: [$i.metadata.name]}}})' -
特定の namespace の全リソースを表示する
$ kubectl get $(kubectl api-resources --namespaced -o name | paste -sd ,) -n kube-system -o yaml 2>/dev/null | yq e '.items[] | . as $i ireduce({}; . *+ {$i.kind: [$i.metadata.name]})' -
APIGroup/Version 付き
$ kubectl get $(kubectl api-resources --namespaced -o name | paste -sd ,) -n kube-system -o yaml 2>/dev/null | yq e '.items[] | . as $i ireduce({}; . *+ {$i.apiVersion: {$i.kind: [$i.metadata.name]}})' -
複数ドキュメントの操作
YAML ファイルの複数ドキュメントを配列にする
$ echo -e "dog\n---\ncat" | yq ea '. as $i ireduce ([]; . + $i)' -
- dog
- cat
ea
は eval-all
の略で、ファイルに含まれる YAML ドキュメントをまとめて読み込みます。
YAML ファイルに含まれるドキュメントの数を数える
$ echo -e "dog\n---\ncat" | yq ea '. as $i ireduce ([]; . + $i) | length' -
2
配列を複数のドキュメントに分割する
$ echo '["dog", "cat"]' | yq e '.[] | splitDoc' -
echo '["dog", "cat"]' | yq e '.[] | splitDoc' -
dog
---
cat
jsonnet
でリソースの配列を作り、yq
でリソースごとのドキュメントに分割して YAML を出力する、というようなこともできます。
YAML と JSON の相互変換
yq
コマンドは JSON を直接読み込めます。 -P
オプションを付けると YAML に整形して出力します。
$ echo '{"kind": "dog"}' | yq e . - -P
kind: dog
-j
オプションを使うと読み込んだ YAML を JSON に変換します。
$ yq e . sample.yaml -j
{
"animal": {
"type": "word",
"members": [
"dog",
"cat"
]
}
}
yq でマニフェストを JSON に変換し、jq のコマンドを使う
yq
には printf
関数がありませんが、jq
と組み合わせて使うことができます。
$ yq e . manifest.yaml -j | jq -r '"\(.kind): \(.metadata.namespace)/\(.metadata.name)"'
Pod: default/sample
jq
で処理した結果を YAML に変換する
JSON を jq
のフィルタで処理し、結果を YAML で確認できます。
$ kubectl get pod alpine -o json | jq .spec | yq e . - -P
その他のコマンド
yq
には他にも色々なコマンドがあります。 詳細は公式マニュアルの Operators をご確認ください。