概要
Kubernetesのmanifestファイルの書き方について説明する。
このページでは、以下の3つについて説明する。
目次
Labelの使い方
Labelは他のリソースから参照するときに利用する。
以下の例では、ServiceからDeploymentへリクエストを流すために各種labelを合わせている。
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 2
selector:
matchLabels:
# 後述のspec.template.metadata.labels.appと合わせる
app: sample-app
template:
metadata:
labels:
# 上記のspec.selector.matchLabels.appと合わせる
app: sample-app
spec:
containers:
# Dockerコンテナ名
- name: http-container
# 利用するDockerイメージ
image: php:7.0-apache
# localイメージ利用。ただし、localに指定したイメージが存在しない場合はレポジトリを参照する
imagePullPolicy: IfNotPresent
ports:
# service.ymlで定義する外部公開用port設定の箇所と名前を合わせることでbindされる
# nameは15文字以内でないとエラーになる
- name: ha-inner-port
# コンテナ内のport
containerPort: 80
apiVersion: v1
kind: Service
metadata:
name: sample-service
spec:
selector:
# deployment.ymlのspec.selector.matchLabels.appと合わせる
app: sample-app
ports:
- name: ha-outer-port
# 外部公開するport
port: 8080
# deployment.ymlで定義したport名と合わせることでbindされる
targetPort: ha-inner-port
type: NodePort
apply
$ sudo kubectl apply -f pod.yml
pod/nginx created
LABELを確認
$ sudo kubectl get all --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod/sample-deployment-85f4cb9d7c-2qncx 1/1 Running 0 20s app=sample-app,pod-template-hash=85f4cb9d7c
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 111m component=apiserver,provider=kubernetes
service/sample-service NodePort 10.98.7.194 <none> 8080:32661/TCP 20s app=http-service
NAME READY UP-TO-DATE AVAILABLE AGE LABELS
deployment.apps/sample-deployment 1/1 1 1 20s <none>
NAME DESIRED CURRENT READY AGE LABELS
replicaset.apps/sample-deployment-85f4cb9d7c 1 1 1 20s app=sample-app,pod-template-hash=85f4cb9d7c
動作確認
WEBページが閲覧できれば、ServiceからDeploymentへのリクエストが流れたことになる。
$ curl $(sudo minikube service sample-service --url)
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /
on this server.<br />
</p>
<hr>
<address>Apache/2.4.25 (Debian) Server at 172.21.115.122 Port 32691</address>
</body></html>
LabelSelectorの使い方
LabelSelectorには以下の2種類がある。
- matchLabels
- matchExpressions
matchLabels
指定したLabelと全て一致したものが対象になる。
matchLabels:
app: nginx
tier: frontend
matchExpressions
matchExpressionsでは、operator
を使い、柔軟な条件を設定することができる。
operator
には以下を指定することができる。
- In
- NotIn
- Exists
- DoesNotExists
具体的な書き方は以下の通り。
matchExpressions:
# envがprodかstgのいずれかである場合
- key: env
operator: In
values: [prod, stg]
# appがprodかstgのいずれかでもない場合
- key: app
operator: NotIn
values: [sample001, sample002]
# appが存在する場合
- key: app
operator: Exists
# tierが存在する場合
- key: tier
operator: DoesNotExist
例
envがprodもしくはstgの場合という条件を設定する。
matchExpressions:
- key: env
operator: In
values: [prod, stg]
この条件でマッチするもの、しないものは以下のとおりである。
マッチする
labels:
app: sample-app
tier: frontend
env: prod
マッチする
labels:
app: sample-app
tier: frontend
env: stg
マッチしない
labels:
app: sample-app
tier: frontend
env: dev
参考:Kubernetes道場 8日目 - ReplicaSet / Deploymentについて
NodeSelectorの使い方
NodeSelectorとは、Podを特定のNodeにスケジューリングする仕組みである。
ここでもLabelSelectorを使うが、先述のものとは違い、matchExpressionsは使えず、完全一致のみとなる。
例として、environment: dev
というLabelを持ったNodeにPodをスケジューリングさせてみる。
まずは、存在しないLabelを指定しスケジューリングされないことを確認し、その後に、存在するLabelを指定してスケジューリングさせるという手順で行う。
Podを定義
environment: dev
のNodeにスケジューリングする設定にする。
apiVersion: v1
kind: Pod
metadata:
name: node-selector
spec:
containers:
- name: nginx
image: nginx
# 以下でNodeの指定をする
nodeSelector:
environment: dev
terminationGracePeriodSeconds: 0
ラベルを確認
しかし、environment: dev
は存在していない。
$ sudo kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
minikube Ready master 3h35m v1.14.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=minikube,kubernetes.io/os=linux,node-role.kubernetes.io/master=
スケジューリング失敗
存在しないNodeのLabelを指定した場合は、エラーとなりスケジューリングされない。
$ sudo kubectl describe pod/node-selector
# **snip**
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 24s (x2 over 24s) default-scheduler 0/1 nodes are available: 1 node(s) didn't match node selector.
NodeにLabelを貼る。
以下のコマンドでNodeにenvironment: dev
というLabelを貼る。
$ sudo kubectl label node/minikube environment=dev
environment=dev
がLabelに追加された。
$ sudo kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
minikube Ready master 3h41m v1.14.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,environment=dev,kubernetes.io/arch=amd64,kubernetes.io/hostname=minikube,kubernetes.io/os=linux,node-role.kubernetes.io/master=
スケジューリングされたことを確認
これでPodがNodeにスケジューリングされた。
$ sudo kubectl describe pod/node-selector
# **snip**
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 2m28s (x5 over 6m30s) default-scheduler 0/1 nodes are available: 1 node(s) didn't match node selector.
Normal Scheduled 101s default-scheduler Successfully assigned default/node-selector to minikube
Normal Pulled 100s kubelet, minikube Container image "nginx:alpine" already present on machine
Normal Created 100s kubelet, minikube Created container nginx
Normal Started 100s kubelet, minikube Started container nginx
$ sudo kubectl get pod
NAME READY STATUS RESTARTS AGE
node-selector 1/1 Running 0 7m16s
Annotationの使い方
Labelと同じようなことができるが、Labelと違い、metadataなどをもたせるのが一般的らしい。
You can use Kubernetes annotations to attach arbitrary non-identifying metadata to objects. Clients such as tools and libraries can retrieve this metadata.
apiVersion: v1
kind: Pod
metadata:
name: annotations-demo
annotations:
imageregistry: "https://hub.docker.com/"
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
関連記事
- 【KubernetesのAffinity】その1 - Node Affinityの使い方
- 【KubernetesのAffinity】その2 - Pod Affinity / Pod Anti-Affinityの使い方