tanke25616429のアウトプット

IT技術の基本を勉強したことをアウトプットします。Linux、Kubernetes、クラウド中心です。百番煎じくらいだけど誰かの役に立てばそれはそれでうれしい。

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

参考にしたもの

techplay.jp

プログラマーのための YAML 入門 (初級編)

teratail.com

*1:参考にしたサイトはRubyなのだが、Goを勉強中なのでそちらの書き方を例として挙げた。

*2:なお体感であるが、配列の中に配列のパターンのネストはkubernetesのmanifestでの出現頻度が高くない気がする。

*3:kubernetesのmanifestではかなり多い書き方である。