対象
異常なめんどくさがりの人
疑問
kubernetesのDeployment
代表的な記述例がここ
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
にあるこちらですが
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.4
        ports:
        - containerPort: 80
なんか app: nginx 多くないですか?
と思ったので少し調べました。
それぞれの役割
まずはそれぞれにどういう意味があるのかを確認します。
これはわかりやすく書いてある記事があるのでそちらを読みましょう。
https://44smkn.hatenadiary.com/entry/2018/07/30/235030
https://medium.com/@zwhitchcox/matchlabels-labels-and-selectors-explained-in-detail-for-beginners-d421bdd05362
.metadata.labels と .spec.template.metadata.labelsについては問題ないですね。
(余談ですが.metadata.labelsは必須のフィールドでないので特に必要なければ設定しなくてもよいみたいです)
少し引っかかるのが.spec.selector.matchLabels
基本的に.spec.template.metadata.labelsと同じものを書くものみたいです。
というか両者が一致しないとエラーになってapplyできません。(厳密に言うと.spec.selector.matchLabelsが.spec.template.metadata.labelsに含まれていればapplyは通る)
省略もできません、必須のフィールドです。
必要なのは先程の記事を読めばわかるのですが、
なぜ同じことを2回書かなくてはいけないのか!内部でよしなにやってくれ!
と思ったので続いてその理由も調べました。
両方書かせる理由
(個人的には納得できた)答えがありました
https://stackoverflow.com/questions/50309057/what-is-the-purpose-of-a-kubernetes-deployment-pod-selector
要約すると
- 
apps/v1beta1まではspec.selector.matchLabelsの指定がない場合spec.template.metadata.labelsと同じものを展開してくれていた(実際にapps/v1beta1でdeployすると確認できます)
- 
kubectl applyを使った時に設定はmetadata.annotations.kubectl.kubernetes.io/last-applied-configurationに保持されるが、ここには実際に記述したものしか保持されない(上の勝手に補完されるspec.template.metadata.labelsは保持されない)
- 
kubectl applyでspec.template.metadata.labelsを変更した時に、前回補完されたspec.selector.matchLabelsと一致せずにエラーになる!
- で、apps/v1beta2からはspec.selector.matchLabelsもちゃんと書いてもらうことになった、あとspec.template.metadata.labelsは変更禁止になった
ということみたいですね、
変更できなくしたならbeta1の頃のように補完してくれても問題ないような気がするんですが。
これだけだとkubectl applyの実装に合わせて取り繕ったように見えてしまいますし、ちゃんと調べたらもっと深い部分の話が出てきそうです。
が、全部書かないといけない理由としては納得できたので一旦ここで終了。気が向いたら更に追ってみようかと…