2026年6月22日
2026年6月22日
KubernetesのDeploymentの作成と管理|YAMLの書き方・更新・スケール・ロールバックと止まったときの調べ方
KubernetesでWebアプリを動かすときの基本単位がDeploymentです。「このイメージのPodを何個動かすか」を宣言しておくと、Podが落ちたときの作り直しや、イメージ更新時の入れ替え(ローリングアップデート)をKubernetesが受け持ちます。この記事では、DeploymentのYAMLの書き方と各項目の意味、作成・更新・スケール・ロールバックの操作、更新が途中で止まったときの調べ方、WordPressのように永続ボリュームを使うアプリでの注意点を説明します。
コマンドとAPIの内容は、Kubernetesの現行のサポート対象の版(2026年10月現在)で共通して使えるものに絞っています。
Deployment・ReplicaSet・Podの関係
最初に3つの関係を押さえておくと、後の調査がずっと楽になります。
- Pod:コンテナを実際に動かす単位です。Pod単体で作ると、落ちても誰も作り直しません。
- ReplicaSet:同じPodを指定した数だけ動かし続ける役です。
- Deployment:ReplicaSetを管理する役です。イメージなどPodの中身を変えると、新しいReplicaSetを作り、古いほうと少しずつ数を入れ替えます。
つまり、Deploymentの更新とは「ReplicaSetの入れ替え」です。古いReplicaSetはPod数0のまま履歴として残り、ロールバックはこの履歴を使って戻します。
YAMLを書く
nginxを3つ動かす最小限に近い例です。ここに、本番で外せない項目を加えています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 3
revisionHistoryLimit: 5
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
readinessProbe:
httpGet:
path: /
port: 80
periodSeconds: 5
押さえておきたい点は次のとおりです。
- **
selector.matchLabelsとtemplate.metadata.labelsは一致させる**:一致していないと作成時にエラーになります。またselectorは作成後に変更できません。変えたいときはDeploymentを作り直します。 - イメージのタグを固定する:
latestを使うと、いつ何が動いているか分からなくなり、ロールバックしても同じイメージに戻る保証がありません。版のタグか、より厳密にはダイジェスト(@sha256:...)で指定します。 - **
maxSurgeとmaxUnavailable**:更新中に「一時的に何個まで増やしてよいか」「何個まで減ってよいか」です。既定はどちらも25%です。上の例は「1個ずつ増やし、稼働数は減らさない」設定で、少ないレプリカ数でも処理能力が落ちません。 - **
readinessProbe**:新しいPodが「リクエストを受けられる状態になった」とKubernetesが判断する基準です。これがないとコンテナが起動しただけで準備完了とみなされ、初期化中のPodに通信が流れてエラーが出ることがあります。 - **
resources.requests**:スケジューラーがPodを置くノードを選ぶ基準です。指定がないと、混雑したノードに詰め込まれることがあります。 - **
revisionHistoryLimit**:ロールバック用に残す古いReplicaSetの数です(既定は10)。
作成と確認
kubectl apply -f web-deployment.yaml
kubectl rollout status deployment/web
kubectl get deployment web
kubectl get rs,pods -l app=web
kubectl get deployment の列は、READY(準備完了の数/希望する数)、UP-TO-DATE(最新の設定で動いている数)、AVAILABLE(利用可能な数)です。READY が 3/3 になれば完了です。rollout status は完了するまで待つので、CIの中で「デプロイが終わったか」を判定するのにも使えます。
試しに作る程度なら kubectl create deployment web --image=nginx:1.27 --replicas=3 でも作れます。ただし、運用するものはYAMLファイルにしてGitで管理し、kubectl apply で反映するほうが、誰が何を変えたかを追えます。適用前に kubectl diff -f web-deployment.yaml で差分を確認する習慣も有効です。
更新する(ローリングアップデート)
イメージを変えるには、YAMLのタグを書き換えて apply し直すのが基本です。
# YAMLの image を nginx:1.28 に変えてから
kubectl apply -f web-deployment.yaml
kubectl rollout status deployment/web
# 変更理由を履歴に残す
kubectl annotate deployment/web kubernetes.io/change-cause="nginx 1.28 に更新"
一時的な検証では kubectl set image deployment/web nginx=nginx:1.28 も使えますが、YAMLと実際の状態がずれるため、後で apply したときに古い版へ戻ってしまう原因になります。
設定はそのままでPodだけ作り直したいとき(ConfigMapの内容を反映させたいときなど)は、次のコマンドを使います。
kubectl rollout restart deployment/web
これもローリングアップデートとして順に入れ替わるため、サービスを止めずに再起動できます。
スケールする
kubectl scale deployment/web --replicas=5
ただし、これもYAMLとずれる操作です。恒久的に数を変えるならYAMLの replicas を書き換えます。HorizontalPodAutoscaler(HPA)で自動的に増減させる場合は、YAMLから replicas を外しておくのが一般的です。残しておくと、apply するたびにHPAが決めた数が上書きされ、一時的にPodが急に減ることがあります。
履歴とロールバック
kubectl rollout history deployment/web
kubectl rollout history deployment/web --revision=3
kubectl rollout undo deployment/web
kubectl rollout undo deployment/web --to-revision=2
undo は1つ前の版に、--to-revision は指定した版に戻します。CHANGE-CAUSE 列には先ほどの kubernetes.io/change-cause の注釈が表示されます。以前は --record オプションで記録していましたが、非推奨になっているため注釈を使います。
ロールバックはクラスター内の状態を戻すだけで、YAMLファイルは変わりません。戻した後はファイル側も同じ内容に直さないと、次の apply で問題のある版が再び反映されます。
更新が止まったときの調べ方
rollout status が終わらない、READY が増えないときは、上から順に見ていきます。
kubectl describe deployment web
kubectl get pods -l app=web
kubectl describe pod <Pod名>
kubectl logs <Pod名> --previous
原因として多いものを、起きやすい順に挙げます。
- **
ImagePullBackOff/ErrImagePull**:イメージ名かタグの誤り、またはプライベートレジストリの認証情報がない状態です。describe podの Events に取得に失敗した理由が出ます。タグを確認し、必要ならimagePullSecretsを設定します。 - **
CrashLoopBackOff**:コンテナが起動してすぐ終了しています。kubectl logs --previousで前回のコンテナの出力を見ると、設定ミスや接続先の誤りが分かることが多いです。 - **
RunningだがREADYが0/1**:readinessProbeが通っていません。パスやポートが実際のアプリと合っているか、起動に時間がかかるアプリならinitialDelaySecondsや startupProbe が必要かを確認します。 - **
Pending**:置けるノードがありません。Events に「Insufficient cpu」「Insufficient memory」などと出ます。requestsを見直すかノードを増やします。
既定では、更新が600秒(progressDeadlineSeconds)進まないと、Deploymentの状態に ProgressDeadlineExceeded が記録されます。ただしKubernetesが自動でロールバックするわけではありません。CIでは rollout status の失敗を検知して rollout undo を実行するなど、戻す手順を自分で用意します。
WordPressなど永続ボリュームを使う場合の注意
WordPressの wp-content を ReadWriteOnce(1ノードからだけ書き込める)の永続ボリュームに置いていると、ローリングアップデートが止まることがあります。新しいPodが別のノードに置かれると、古いPodがボリュームをつかんだままなので接続できず、Events に「Multi-Attach error」と出ます。
対処は次のいずれかです。
strategy.type: Recreateにする:古いPodを止めてから新しいPodを作るため、更新中に短い停止が発生しますが、ボリュームの取り合いは起きません。- 複数ノードから使える ReadWriteMany のストレージを使う。
- アップロードファイルをオブジェクトストレージに移し、Podを使い捨てにできる構成にする。
いずれの場合も、データベースとアップロードファイルのバックアップを取ってから構成を変えてください。
まとめ
- DeploymentはReplicaSetを入れ替えることで更新とロールバックを実現している。
selectorとPodのラベルを一致させ、イメージのタグを固定し、readinessProbeとresources.requestsを書く。- 変更はYAMLを直して
kubectl apply。set imageやscaleは一時的な操作と考え、YAMLとのずれに注意する。 - 止まったら
describe deployment→get pods→describe pod→logs --previousの順に見る。 - ReadWriteOnceのボリュームを使うアプリは
Recreateかストレージ構成の見直しを検討する。