はじめに
Kubernetesのマニフェストファイルの内容がよくわからない、という方いらっしゃるではないでしょうか?
私もその一人です。
今回はマニフェストファイルの読み方についてyaml
コード内にコメントをつけて解説してきたいと思います。
補足説明はコード外にいたします。
マニフェストファイルの解説
apiVersion: apps/v1 # KubernetesにはAPIバージョンがあるためそれを記述します。 ①
kind: Deployment # リソースの種類を記述します。 (Ingress, Serviceなど) DeploymentはReplicaSetを生成/管理し、ReplicaSetはPod(Podの数 = レプリカ数)を生成/管理します。
metadata: # その名の通りメタデータ、要するに「そのデータ(ここではDeployment)に関連する情報を記述したデータ」を記述します。
name: nginx-deployment # Deploymentの名前を記述します。
namespace: default # 名前空間を記述します。 ②
spec: # ReplicaSetのあるべき姿を定義します。
replicas: 1 # レプリカ数を定義します = 1の場合1つのPodを要求します。
selector: # Deploymentの管理対象とするPodの情報を指定します。selectorによってラベルの条件が指定され、その条件に一致するPodがDeploymentによって管理されます。
matchLabels: # Podをラベルでフィルタリングします。 ③
app: nginx # Podが持つラベルを指定します。
template: # Deploymentが生成するPodの使用を定義します。 ④
metadata:
labels:
app: nginx
spec: # コンテナのスペックを定義します。使用するイメージ, cpu, memory, portなど
containers:
- name: nginx
image: nginx:1.27.1
resources:
requests:
cpu: "2"
memory: "10G"
ports:
- containerPort: 80 # コンテナのポートに関する情報です。 ⑤
livenessProbe: # Podに対するヘルスチェックを行う仕組みです。 ⑥
httpGet:
port: 80
path: /liveness/healthcheck
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 10
補足説明
① apiVersion
kubectl
コマンドでkubectl api-resources
とすると、以下のように各apiVersion
を表示することができます。
$ kubectl api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
podtemplates v1 true PodTemplate
replicationcontrollers rc v1 true ReplicationController
resourcequotas quota v1 true ResourceQuota
secrets v1 true Secret
serviceaccounts sa v1 true ServiceAccount
services svc v1 true Service
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition
apiservices apiregistration.k8s.io/v1 false APIService
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
selfsubjectreviews authentication.k8s.io/v1 false SelfSubjectReview
tokenreviews authentication.k8s.io/v1 false TokenReview
localsubjectaccessreviews authorization.k8s.io/v1 true LocalSubjectAccessReview
selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview
selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview
subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview
horizontalpodautoscalers hpa autoscaling/v2 true HorizontalPodAutoscaler
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true Job
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
leases coordination.k8s.io/v1 true Lease
endpointslices discovery.k8s.io/v1 true EndpointSlice
events ev events.k8s.io/v1 true Event
flowschemas flowcontrol.apiserver.k8s.io/v1 false FlowSchema
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1 false PriorityLevelConfiguration
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
runtimeclasses node.k8s.io/v1 false RuntimeClass
poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget
clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding
clusterroles rbac.authorization.k8s.io/v1 false ClusterRole
rolebindings rbac.authorization.k8s.io/v1 true RoleBinding
roles rbac.authorization.k8s.io/v1 true Role
priorityclasses pc scheduling.k8s.io/v1 false PriorityClass
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
csistoragecapacities storage.k8s.io/v1 true CSIStorageCapacity
storageclasses sc storage.k8s.io/v1 false StorageClass
volumeattachments storage.k8s.io/v1 false VolumeAttachment
grep
することで、このマニフェストのapiVersion
ってなんだっけ?を確認する手段として使用できます。
> kubectl api-resources | grep deployment
deployments deploy apps/v1 true Deployment
② namespace
namespaceとは例えると家の中でそれぞれの名前が付けられた部屋を作って分離することです。
家(クラスター)の中に各部屋(namespace)が存在し、それぞれの部屋は独立して管理されています。
例えば、4人家族で父、母、娘、息子の家族構成の場合、娘の部屋、息子の部屋、寝室などを倫理的に区切り、それらは独立して管理できるようにしています。
娘の部屋を模様替えしても、息子の部屋まで模様替えされることはありえません。
namespaceの運用方法として例えば運用
と開発
のチームごとに、namespaceを分離することです。
- 運用のnamespaceには特定のリソースに対してのみ読み取り権限を与える
- 開発のnamespaceにはリソースの作成、変更削除をできる権限を与える
といった具合です。
Kubernetesにはデフォルトで以下のnamespaceが存在し、この名前空間をすぐに使用できるように設定されています。
- default
- kube-system (Kubernetesコンポーネントに使用)
- kube-public (パブリックリソースに使用)
以下コマンドを実行することでnamespaceの情報を取得することができます。
> kubectl get namespace
NAME STATUS AGE
default Active 192d
kube-node-lease Active 192d
kube-public Active 192d
kube-system Active 192d
kubernetes-dashboard Active 192d
namespaceを作成する場合は以下コマンドで作成することができます。
> kubectl create namespace <名前空間名>
③ matchLabels
説明が長くなりそうなので補足します。
Podをラベルでフィルタリングする方法がmatchLabelsです。
matchLabels
にapp: nginx
というラベルが指定されています。
つまり、app: nginx
というラベルを持つPodがDeployment
によって管理される対象となります。
selector:
matchLabels:
app: nginx
Deployment
はReplicaSet
を生成/管理し、ReplicaSet
はPod
を生成/管理します。
ReplicaSet
は指定されたPod
数に調整、管理を行う仕組みです。
マニフェストにReplicaset
を定義することで、障害などでPod
がダウンした際にも自動的に指定の数にPod
数を調整してくれます。
Deployment
は例えばコンテナのイメージのバージョンアップをしなければならない場合などに、新しいReplicaSet
を作成し、新旧の全体のPod
数を調整しながら新しいPod
を生成します。
④ templateとmatchLabelsの違い
template
の役割
Podの仕様を定義する部分で、「どんなコンテナを使用するか」「どんなリソースを要求するか」「どんなラベルを付けるのか」といったことを設定します。
template
以下を見てもらうとわかりやすいかと思いますが、ぱっと見でも「コンテナの名前」「コンテナのイメージ」「コンテナのスペック」などが定義されているのがわかります。
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27.1
resources:
requests:
cpu: "2"
memory: "10G"
ports:
- containerPort: 80
以下に記述されているtemplate.metadata.labels
に記述されているフィールドは生成されるPodにどんなラベルを付けるを指定する箇所です。
生成されるPodにはapp: nginx
というラベルが付与されます。
template:
metadata:
labels:
app: nginx
matchLabels
の役割
selector.matchLabels
については「app: nginx
というラベルを持つPodを管理します」ということを指定しています。
selector:
matchLabels:
app: nginx
Deploymentによる管理の流れは以下のようになります。
-
Deployment
はPodを作成するときにtemplate
に基づいてPodを生成します。この時、生成される全てのPodにapp: nginx
というラベルが付与されます。 -
selector.matchLabels
は「app: nginx
というラベルを持つPod」を管理対象として指定します。
Deployment
└─ spec:
└─ template: <-- Podがこのテンプレートに従って作成される
└─ metadata:
└─ labels:
└─ app: nginx <-- 作成されたPodに「app=nginx」ラベルが付与される
└─ spec:
└─ selector: <-- このラベルに一致するPodを管理する
└─ matchLabels:
└─ app: nginx
⑤ containerport
このcontainerport
ですが、あくまでコンテナのポートは80
を指定していますよ、ということにすぎず、実際にマニフェストファイルにポートを記述したからと言って記述したポートが実際のコンテナに設定されるわけではありません。
つまりただの飾り
であることがわかりました。
以下の公式ドキュメントに内にも
https://kubernetes.io/ja/docs/concepts/services-networking/connect-applications-service/
コンテナポートの仕様を指定していることに注意してください。
と記載があるように、仕様を指定
しているにすぎません。
ほんとですか?という信じられない気持ちでしたので検証してみました。
前提としてKubernetesクラスターはkindを使用してKubernetesリソースの作成ができている状態で検証しております。
以下のDockerfileを準備します。
# Dockerfile
FROM nginx:latest
# Install bash net-tools
RUN apt-get update && apt-get install -y bash bash net-tools && rm -rf /var/lib/apt/lists/*
docker image
を作成します。
docker image build -t my-nginx .
containerport
を8080
にしてPodを生成します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-liveness-check
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-liveness
template:
metadata:
labels:
app: nginx-liveness
spec:
containers:
- name: nginx
image: my-nginx:latest
ports:
- containerPort: 8080
apply
してPodを作成 -> 起動します。
kubectl get pods
でRunning
になっていることを確認します。
kubectl apply -f <yamlファイル名>
kubectl get pods -w
NAME READY STATUS RESTARTS AGE
<Pod名> 1/1 Running 0 4s
以下コマンドでコンテナに接続します。
kubectl exec -it <Pod名> -- /bin/bash
netstat
でリッスンしているポートを確認すると0.0.0.0:80
となっているので8080
でリッスンしていないことが確認できます。
netstat -tnlp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master pro
tcp6 0 0 :::80 :::* LISTEN 1/nginx: master pro
まんまと騙されましたが、マニフェストに記載するcontainerport
はただの飾りであることがわかりました。
⑥ Probeについて
Probeについては以前の記事で解説しておりますので、こちらを参照ください。
最後に
Kubernetesマニフェストファイルの中身についてどんな意味なのかについて深掘りしていきました。
あいまいだった理解がアウトプットすることで少しづつ深まっていきました。
また、実際に動作確認することで、見た目に騙されないマニフェストファイルの奥深さを理解できて非常に勉強になりました。
本記事がマニフェストファイルの読み方がわからない、という方の助けになれば幸いです。
参考