機雷がなんだ! 全速前進!

SEというかプログラマというか、日々のエンジニア生活の中で体験したことなどを中心に書き残しています。

k8s Deploymentのラベルの扱いについて

先日CKADを再取得した際、Deploymentのラベルの扱いについて再認識したことがあったので備忘メモを残しておきます。

一般的なDeploymentのラベル

よく見るDeploymentの例では、以下の例のようなラベル(★印)が定義されています。

例:controllers/nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx ←★任意:このリソース(Deployment)のラベル
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx ←★必須:Deploymentが管理するPodのラベル ・・・【A】
  template:
    metadata:
      labels:
        app: nginx ←★必須:このリソース(Deployment)配下のPodのラベル ・・・【B】
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

それぞれのラベルの意味はkubernetes公式ドキュメント Deployment | Kubernetes にも記載されており【任意/必須】も含めて上記のような役割を担っています。

apply時にエラーとなるパターン

必須の【A】と【B】は省略できず、例えば以下のようなパターンではapply時にエラーとなりリソースを生成できません。(A ⊈ B)

パターン① 【A】(未定義):.spec.selector の定義が存在しない
The Deployment "nginx-deployment" is invalid: 
* spec.selector: Required value
* spec.template.metadata.labels: Invalid value: map[string]string{"app":"nginx"}: `selector` does not match template `labels`
パターン② 【A】(未定義):.spec.selector の定義は存在するがラベルが未定義
The Deployment "nginx-deployment" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string(nil), MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: empty selector is invalid for deployment
パターン③ 【A】app: nginx 【B】(未定義):.spec.template.metadata.labels の定義は存在するがラベルが未定義
The Deployment "nginx-deployment" is invalid: spec.template.metadata.labels: Invalid value: map[string]string(nil): `selector` does not match template `labels`
パターン④ 【A】app: nginx 【B】app: xxxxx:.spec.template.metadata.labels の定義は存在するがラベルが不一致
The Deployment "nginx-deployment" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{"app":"xxxxx"}: `selector` does not match template `labels`

apply時にエラーとならないパターン

ラベルは複数定義できるため、厳密にすべてのラベルが完全に一致している必要があるかと言えばそうではありません。

以下のようなパターンはリソースを生成できます。(A ⊆ B)

パターン⑤ 【A】app: nginx 【B】app: nginx + age: fifty

定義:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        age: fifty
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

をapplyすると以下のように問題なくリソース作成できます。

kubectl apply -f deploy.yaml 
deployment.apps/nginx-deployment created

kubectl get pods --show-labels 
NAME                                READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-7f5b4c8c69-k458q   1/1     Running   0          27s   age=fifty,app=nginx,pod-template-hash=7f5b4c8c69
nginx-deployment-7f5b4c8c69-kb6n2   1/1     Running   0          27s   age=fifty,app=nginx,pod-template-hash=7f5b4c8c69
nginx-deployment-7f5b4c8c69-vkrlh   1/1     Running   0          27s   age=fifty,app=nginx,pod-template-hash=7f5b4c8c69
パターン⑥ 【A】app: nginx 【B】app: xxxxx + app: yyyyy+ app: zzzzz+ app: nginx

※こんなことする人は居ないと思いますが試しにやってみました。(key重複は後勝ちなんですね😅)

定義:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: xxxxx
        app: yyyyy
        app: zzzzz
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

をapplyすると以下のように問題なくリソース作成できます。

kubectl apply -f deploy.yaml
deployment.apps/nginx-deployment created

kubectl get pods --show-labels 
NAME                                READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-647677fc66-8lrnr   1/1     Running   0          12s   app=nginx,pod-template-hash=647677fc66
nginx-deployment-647677fc66-gchpd   1/1     Running   0          12s   app=nginx,pod-template-hash=647677fc66
nginx-deployment-647677fc66-shcvh   1/1     Running   0          12s   app=nginx,pod-template-hash=647677fc66

所感

k8sのリソースまわりは公式ドキュメントなどを読んでもイマイチ正しく理解できたかいつもモヤモヤしてしまいます。 今回のように試験勉強でハマったり気になったりしたことは実際に手を動かしてコマンドを叩いて検証するのが一番スッキリしますし、 単に機械的に資格を取得するための学習だけをするのは非常にもったいないので、学びの機会として今後もうまく利用していきたいところです。

参考情報

今回は以下の情報を参考にさせてもらいました。🙇‍♂️