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

原因として多いものを、起きやすい順に挙げます。

  1. **ImagePullBackOff / ErrImagePull**:イメージ名かタグの誤り、またはプライベートレジストリの認証情報がない状態です。describe pod の Events に取得に失敗した理由が出ます。タグを確認し、必要なら imagePullSecrets を設定します。
  2. **CrashLoopBackOff**:コンテナが起動してすぐ終了しています。kubectl logs --previous で前回のコンテナの出力を見ると、設定ミスや接続先の誤りが分かることが多いです。
  3. **Running だが READY が 0/1**:readinessProbeが通っていません。パスやポートが実際のアプリと合っているか、起動に時間がかかるアプリなら initialDelaySeconds や startupProbe が必要かを確認します。
  4. **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 かストレージ構成の見直しを検討する。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲