この記事は Kubernetes道場 Advent Calendar 2018 17日目の記事です。
今回はLabel / NodeSelector / Annotationについて。
Label
今までLabelをシレッと使ってきたが改めてここで解説しよう。
Labelはkey/valueの組み合わせKubernetesオブジェクトに指定することができる。
システムに直結する意味合いを持つ設定ではなく、 LabelSelectorなどで使ってきたが、オブジェクトの選択やサブセットの指定などで使用される。
Labelの構文と使用できる文字列
LabelのKeyは/
を使って2つのセグメントに分割して表現することができる。/
より前をPrefix、後をNameと呼ぶ。
PrefixはDNS_LABELに従った253文字以下の文字列である。Prefixを省略すると、ユーザー固有のものとして扱われる。
Nameは63文字以下で下の正規表現に従っている必要がある。
1
|
([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]
|
要は最初と最後はアルファベットか数字、間の文字ではそれらに加えて -
/ _
/ .
が使用できる。
また、LabelのValueはKeyのNameと同じで、63文字以下で上記の正規表現に従っている必要がある。
以下がラベルの使用例だ。
k8s.io/name: nginx
environment: production
LabelSelectorについて
LabelSelectorについては過去取り扱ったことがあるので簡単に。
LabelSelectorには2種類の方法がある。
- 等価ベースの比較(matchLabels)
- 集合ベースの比較(matchExpressions)
詳しくは8日目のこちらの記事を参考にしてほしい。
ラベルの指定方法
ラベルを指定するするにはManifestを使用する方法とCLIから操作する方法がある。
Manifestを使用する方法
Manifestを使ったラベルの指定は metadata.labels
に記述する。以下のような感じ。
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
environment: dev
spec:
containers:
- name: nginx
image: nginx:alpine
terminationGracePeriodSeconds: 0
|
labels
にKey/Valueの形で指定する。
CLIから操作する方法
Labelはkubectlから操作することも可能だ。 kubectl label
コマンドで行う。
- ラベルの作成:
kubectl label pod/nginx foo=bar
- ラベルの更新:
kubectl label --overwrite pod/nginx foo=bar
- ラベルの削除:
kubectl label pod/nginx foo-
削除の時だけ少し特殊で、Keyの最後に -
をつけることで対象のLabelを削除することができる。
Labelについての実行例
それでは先程出てきた以下のManifestを適用してみよう。
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
environment: dev
spec:
containers:
- name: nginx
image: nginx:alpine
terminationGracePeriodSeconds: 0
|
1
2
|
$ kubectl apply -f nginx.yaml
pod/nginx created
|
Podの取得は kubectl get po
でできるが、 --show-labels
オプションを付けることでLabelも表示することができる。
1
2
3
|
$ kubectl get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 67s name=nginx
|
Labelがついていることが確認できる。
それではCLIからラベルを付けてみよう。foo=bar
というラベルを付けるため kubectl label pod/nginx foo=bar
を実行してみる。
1
2
3
4
5
|
$ kubectl label pod/nginx foo=bar
pod/nginx labeled
$ kubectl get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 3m36s foo=bar,name=nginx
|
ラベルが作成されたのがわかる。
削除も試してみよう。 kubectl label pod/nginx fooi-
を実行する。
1
2
3
4
5
|
$ kubectl label pod/nginx foo-
pod/nginx labeled
$ kubectl get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 6m44s name=nginx
|
正しく削除できたようだ。
NodeSelector
NodeSelectorはPodを特定のNodeへスケジューリングする仕組みだ。Selectorと書いてあるから予測できるかと思うが、ここにもLabelSelectorを使う。
NodeのLabelとNodeSelectorの条件がマッチしたNodeに対してスケジューリングされるようになる。
NodeSelectorはPodの spec.nodeSelector
に指定をする。但し、このNodeSelectorは matchExpressions
は使えず、完全一致での比較のみになる。
NodeSelectorを使ってみる
以下のようなManifestを作成した。
1
2
3
4
5
6
7
8
9
10
11
|
apiVersion: v1
kind: Pod
metadata:
name: node-selector
spec:
containers:
- name: nginx
image: nginx:alpine
nodeSelector:
environment: dev
terminationGracePeriodSeconds: 0
|
nodeSelector
に environment=dev
を指定した。 これを適用してみよう。
1
2
3
4
5
|
$ kubectl apply -f node-selector.yaml
pod/node-selector created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
node-selector 0/1 Pending 0 14s
|
Pending
のままだ。describeを確認してみよう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
$ kubectl describe po/node-selector
Name: node-selector
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: <none>
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"node-selector","namespace":"default"},"spec":{"containers":[{"image":...
Status: Pending
IP:
Containers:
nginx:
Image: nginx:alpine
Port: <none>
Host Port: <none>
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-qb4fq (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
default-token-qb4fq:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-qb4fq
Optional: false
QoS Class: BestEffort
Node-Selectors: environment=dev
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 9s (x20 over 2m53s) default-scheduler 0/1 nodes are available: 1 node(s) didn't match node selector.
|
スケジューリングに失敗しているのがわかる。 nodeSelector
で指定した対象がなかったようだ。
それもそのはずでNodeにLabelを今までに貼っていない。
1
2
3
|
$ kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
minikube Ready <none> 4h24m v1.13.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=minikube
|
というわけでNodeにLabelを追加しよう。以下のコマンドを実行する。
1
2
|
$ kubectl label node/minikube environment=dev
node/minikube labeled
|
それでは再度Podを確認してみる。
1
2
3
|
$ kubectl get po
NAME READY STATUS RESTARTS AGE
node-selector 1/1 Running 0 16m
|
スケジュールされて実行されたようだ。
ローカル環境だと有り難みが薄いが、実際に複数のNodeがあるクラスタなどでは活用できる機能だ。例えば
- SSDが搭載されているNode
- GPUが搭載されているNode
- 所定のNode群へのDeploy
などなど。実際にマネージドサービスなどで複数Nodeのクラスタを立ち上げて動作を確認すると理解が進むと思う。
Annotation
Annotationはオブジェクトに対してKey/Valueの形式でMetadataを登録できる仕組みだ。
Labelとほぼ同じ機能だが、Selectorなどで使用されない。
構文と使用できる文字列はLabelと同様だ。Valueについては特に使用文字や長さについて成約がない。
使用方法はManifestで metadata.annotations
に指定するか、 kubectl annotate
コマンドで操作をする。
具体的な操作方法はLabelと全く同じためManifestの例だけ記載して適用などについては省略させていただく。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
apiVersion: v1
kind: Pod
metadata:
name: nginx-annotate
annotations:
name: nginx
message: |
hello world!!
spec:
containers:
- name: nginx
image: nginx:alpine
terminationGracePeriodSeconds: 0
|
というわけで今回はここまで。
次回はAffinity / Anti-Affinity / Taint / Tolerationについて見ていこう。
それでは。