kubernetesのmanifestにおけるYAMLの配列、ハッシュについて
動機
kubernetesのmanifestファイルを書こうと思って、kubectl explainコマンドで調べるが、配列、ハッシュ周りの記法があやふやで間違えることがよくあった。具体的には
xxx: - yyy: YYY zzz: ZZZ
と書くべきか
xxx: - yyy: YYY - zzz: ZZZ
と書くべきか
xxx: yyy: YYY zzz: ZZZ
と書くべきかが迷うので整理する。
YAMLの配列とハッシュ
前提知識となるYAMLの構文を整理する。
配列
YAMLでは、インデントを揃えたうえで行頭に"- "(半角ハイフンスペース)をつけることで配列を表現する。
- aaa - bbb - ccc
この例は配列 [aaa bbb ccc]
(Go風に書くと*1)と同値である。
念のため、ハッシュと比較する意味で配列をちゃんと定義しておく。配列とは、0から始まる連続する自然数をキーとするオブジェクトの列のこと。
ハッシュ
ハッシュは、文字列をキーとしたオブジェクトの列のこと。文字列連想配列とかマップとかも呼ばれる。キーとバリュー(値)のペアで構成される。 YAMLでのハッシュは、インデントを揃えたうえで「キー: 値」の形式で並べて表現する。
A: aaa B: bbb C: ccc
この例をGoのmap風に書くと、map[A: aaa B: bbb C: ccc]
と同値である。
ネスト
ハッシュや配列はネストして入れ子構造にして使われることが多い。
ハッシュのネスト
半角スペースでインデントさせることでハッシュをネストさせる。
A: aaa B: B1: bbb1 B2: bbb2 C: ccc
この例の場合、B
というキーに対応するのは一個の値ではなく、
B1: bbb1 B2: bbb2
という、「キー: 値」のかたまりである。
配列のネスト
配列も半角スペースでインデントさせることでネストできる。
- aaa - - bbb1 - bbb2 - ccc
aaa
の次の行のハイフンの後には何もないが、この要素に対応するのは一個の値ではなく
- bbb1 - bbb2
という配列である*2。すなわち[aaa [bbb1 bbb2] ccc]
と同値である。
ハッシュと配列のネスト
ハッシュと配列のネストはどちらが外側に来るかで2通り考えられる。それぞれ示す。
ハッシュの中に配列
A: aaa B: - bbb1 - bbb2 C: ccc
この例ではB
というキーに対応する値は、
- bbb1 - bbb2
という配列である。
配列の中にハッシュ
- aaa - B1: bbb1 B2: bbb2 - ccc
この例ではaaa
の次の要素は、
B1: bbb1 B2: bbb2
というハッシュである。なお、ハイフンの次の行にハッシュを持ってこずにいきなりハイフンの後にハッシュを続けて書いてもよいことにYAMLの仕様上なっているため、以下の書き方ができる*3。
- aaa - B1: bbb1 B2: bbb2 - ccc
kubernetesのmanifestにおける実例
前提知識であるYAMLの構文を踏まえ、kuberntestのmanifestの記載と照らし合わせる。
RoleBindingのmanifest
RoleBindingのmanifestをYAML形式で表示すると下記のようになる。
# kubectl get rolebindings.rbac.authorization.k8s.io -n kube-system kube-proxy -o yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding (中略) roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kube-proxy subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:bootstrappers:kubeadm:default-node-token
roleRef:
はハッシュにおけるキーとなっており、それと対応する値が、
apiGroup: rbac.authorization.k8s.io kind: Role name: kube-proxy
というハッシュである。
subjects:
もハッシュにおけるキーであるが、対応する値は配列である。この例だと配列には1つの要素だけがある。その要素に格納されている値が、
apiGroup: rbac.authorization.k8s.io kind: Group name: system:bootstrappers:kubeadm:default-node-token
というハッシュである。すなわち、ハッシュ-配列-ハッシュという入れ子になっている。わかりやすく書くと、
subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:bootstrappers:kubeadm:default-node-token
ということである。
kubectl explain
コマンドで調べると、キーroleRef
に対応する値が<Object>
(オブジェクト)と書かれている。この場合のオブジェクトは単体の値もしくは、入れ子になったハッシュである。
一方、キーsubjects
に対応する値が<[]Object>
(配列)と書かれている。キーに対応する値が配列かどうかは、[]
があるかどうかでわかる。実行例を下記に示す。
# kubectl explain rolebindings KIND: RoleBinding VERSION: rbac.authorization.k8s.io/v1 (中略) roleRef <Object> -required- RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. If the RoleRef cannot be resolved, the Authorizer must return an error. subjects <[]Object> Subjects holds references to the objects the role applies to.
キーsubjects
が配列を値に取るということがよりわかりやすいのは、複数のハッシュのかたまりを要素とする配列というケースである。
subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: hogehoge - apiGroup: rbac.authorization.k8s.io kind: Group name: fugafuga
参考にしたもの
*1:参考にしたサイトはRubyなのだが、Goを勉強中なのでそちらの書き方を例として挙げた。
*2:なお体感であるが、配列の中に配列のパターンのネストはkubernetesのmanifestでの出現頻度が高くない気がする。
*3:kubernetesのmanifestではかなり多い書き方である。