Kubernetes Kubernetes

Deployment:スケーリング、自己修復、ローリングアップデート

Pod のレプリカを実行し、ダウンタイムなしで更新し、リリースがうまくいかなかったときにロールバックします。

14 min learn.level.初級

Pod は使い捨てで、単独の Pod が死ぬと、そのまま死んだままです。Deployment がこれを解決します。必要なコピーの数と実行するイメージを宣言すると、Kubernetes がその数を稼働させ続け、更新も処理してくれます。このガイドでは、作成、スケーリング、ダウンタイムなしの更新、ロールバックを説明します。

単独の Pod をほとんど作らない理由

ノードが故障したり Pod が削除されたりしても、単独の Pod を再作成するものはありません。実際には、Pod を直接作成することはほとんどありません。Deployment を作成し、それが ReplicaSet を作成し、ReplicaSet が Pod を作成して維持します。Deployment は、ReplicaSet に欠けているもの、つまり制御された更新とバージョン履歴を追加します。

Deployment を書く

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80

metadata のセクションは 2 つあり、区別しておくと役に立ちます。上のものは Deployment を記述します。template の下のものは、それが作成する Pod を記述し、template は単に名前のない Pod のマニフェストです。selector は、どの Pod が Deployment に属するかを Deployment に伝えるため、テンプレートのラベルと一致している必要があります。そうでないと、Kubernetes はマニフェストを拒否します。

kubectl apply -f deployment.yaml
kubectl get deployment,replicaset,pods

1 つの Deployment、その名前にハッシュが付いた 1 つの ReplicaSet、ReplicaSet の名前を元にした 3 つの Pod が表示されます。

ラベルとセレクター:オブジェクト同士が互いを見つける方法

ラベルは、任意のオブジェクトに付けられるキーと値のペアです。セレクターはそれらをクエリします。これが Kubernetes がものをつなぐ方法です。Deployment が Pod を見つけ、Service がバックエンドを見つけ、ネットワークポリシーが自身が管理する Pod を見つけます。

kubectl get pods --show-labels
kubectl get pods -l app=web

セレクターがどれほど重要かを確認するには、1 つの Pod からラベルを外します。

kubectl label pod POD_NAME app-
kubectl get pods --show-labels

ReplicaSet は、その Pod を自分のものとして数えなくなるため、3 つに戻すために代わりの Pod を起動します。ラベルを外した Pod は動作し続けますが、それを管理するものは何もありません。放置しないよう、kubectl delete pod POD_NAME で削除してください。

スケーリングして自己修復を観察する

kubectl scale deployment web --replicas=5
kubectl get pods -w

別のターミナルで Pod を削除すると、ほんの少しの間に代わりの Pod が現れます。レプリカ数を恒久的に変更するには、マニフェストの replicas を編集して再度適用します。kubectl scale だけでは、ファイルが古いままになるからです。Deployment の Pod は、削除しても戻ってくるため、削除して取り除くことはできません。Deployment 自体を削除するか、ゼロにスケールします。

新しいバージョンをロールアウトする

イメージなど、Pod テンプレート内の何かを変更すると、ローリングアップデートが始まります。

kubectl set image deployment/web nginx=nginx:1.26
kubectl rollout status deployment/web

Deployment は、新しいバージョン用に 2 つ目の ReplicaSet を作成し、古いものを縮小しながら徐々にスケールアップするため、常にいくつかの Pod がトラフィックを処理しています。デフォルトでは、変更中に最大 25% の追加の Pod(maxSurge)と、最大 25% の利用不可(maxUnavailable)を許容します。spec で調整できます。

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

maxUnavailable: 0 では、新しい Pod が準備完了になってはじめて、古い Pod が削除されます。「準備完了」の意味は readiness probe が決めるもので、後のガイドで説明します。レプリカ数の変更は、Pod テンプレートに触れないため、ロールアウトではありません。

ロールバックする

Kubernetes は古い ReplicaSet を保持しており、そのおかげでロールバックが素早く行えます。

kubectl rollout history deployment/web
kubectl rollout undo deployment/web
kubectl rollout undo deployment/web --to-revision=1

undo は直前のリビジョンに戻し、--to-revision は特定のものを選びます。保持される古いリビジョンの数は revisionHistoryLimit で設定され、デフォルトは 10 です。1 つ注意があります。マニフェストが Git にあり、Argo CD のようなものがそれを適用している場合は、rollout undo よりも commit の revert を優先してください。undo はクラスターを変更しますが Git は変更しないため、誰かが調整するまで、両者は食い違います。

人気のガイド