WebアプリをKubernetesで継続稼働させるとき、通常はPodを直接作りません。Deployment → ReplicaSet → Pod という所有関係を使います。

3層の責務
| オブジェクト | 主な責務 | 直接操作する頻度 |
|---|---|---|
| Pod | 1個以上のコンテナを実行する最小単位 | 調査対象。通常は直接作らない |
| ReplicaSet | 同じPodを指定数に保つ | Deploymentが管理するため通常触らない |
| Deployment | ReplicaSetの世代、更新、ロールバックを管理 | Web/API運用の主な操作対象 |
Podが削除されてもReplicaSetが新しいPodを作り、イメージを更新するとDeploymentが新しいReplicaSetへ段階的に切り替えます。
Deploymentマニフェスト
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-api
namespace: YOUR_NAMESPACE
labels:
app: example-api
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: example-api
template:
metadata:
labels:
app: example-api
spec:
containers:
- name: api
image: registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG
ports:
- name: http
containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
readinessProbe:
httpGet:
path: /health/ready
port: http
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health/live
port: http
initialDelaySeconds: 15
periodSeconds: 20
このイメージパスは形式例です。第12回でGitLab Container Registryからpullする認証を設定します。
labelとselectorが接着剤になる
Deploymentは spec.selector.matchLabels に一致するPodを管理します。そのため次の2箇所を一致させます。
selector:
matchLabels:
app: example-api
template:
metadata:
labels:
app: example-api
Serviceも同じラベルでPodを選択できます。名前が似ているだけでは関連付かず、ラベルセレクターがオブジェクト間を結ぶことを覚えます。
所有関係をコマンドで確認する
kubectl apply -f deployment.yaml
kubectl get deployment,replicaset,pods -n YOUR_NAMESPACE
kubectl describe deployment example-api -n YOUR_NAMESPACE
kubectl get pods -n YOUR_NAMESPACE -l app=example-api --show-labels
Pod名は example-api-<ReplicaSet hash>-<suffix> のようになります。更新後にhashの異なるReplicaSetとPodが現れることで、世代交代を確認できます。
自己修復を確認する
学習環境でPodを1つ削除すると、ReplicaSetが代わりを作ります。
kubectl delete pod YOUR_POD_NAME -n YOUR_NAMESPACE
kubectl get pods -n YOUR_NAMESPACE -l app=example-api -w
これは同じPodが復活するのではなく、望ましいレプリカ数を満たす新しいPodが作られる動きです。Pod名やIPを永続IDとして扱ってはいけない理由でもあります。
ローリングアップデート
マニフェストの image を新しい固定タグへ変更し、差分を確認して適用します。
kubectl diff -f deployment.yaml
kubectl apply -f deployment.yaml
kubectl rollout status deployment/example-api -n YOUR_NAMESPACE
kubectl rollout history deployment/example-api -n YOUR_NAMESPACE
maxUnavailable: 1 は更新中に利用不能を許す最大数、maxSurge: 1 は指定レプリカ数を超えて一時追加できる最大数です。レプリカが1個しかない場合、設定とアプリの起動時間によっては停止時間が生じ得ます。
問題があればロールバックする
kubectl rollout undo deployment/example-api -n YOUR_NAMESPACE
kubectl rollout status deployment/example-api -n YOUR_NAMESPACE
ロールバック後もログ、イベント、実際の応答を確認します。原因不明のまま再デプロイを繰り返すと証拠を失うため、まず describe と logs --previous を保存します。
Probeの役割
- readinessProbe:通信を受けられるか。失敗中はServiceの転送先から外れる
- livenessProbe:停止状態から自力回復できないか。連続失敗すると再起動対象になる
- startupProbe:起動が遅いアプリの初期化完了まで他のProbeを待たせる
Probeは「とりあえず同じ /health」ではなく、目的に合わせて設計します。外部DBが一時停止しただけで全Podのlivenessが失敗する設計は、再起動ループを悪化させることがあります。
ReplicaSetを直接変更しない
Deployment配下のReplicaSetを直接scaleまたは編集しても、Deploymentの望ましい状態によって戻されたり、次回更新で失われたりします。変更点はDeploymentへ記述します。
次回
常時稼働ではなく完了する処理は、Job・CronJobによるバッチ処理へ分けます。