StatefulSet

このページでは、Kubernetes の StatefulSet オブジェクト、および Google Kubernetes Engine(GKE)での使用方法について説明します。ステートフル アプリケーションをデプロイする方法もご覧ください。

概要

StatefulSet は、スケジュールされた場所にかかわらず GKE が保持する一意で永続的な ID と固有のホスト名を持つ Pod のセットを表します。任意の StatefulSet Pod の状態情報やその他の復元データは、StatefulSet に関連付けられた永続ディスク ストレージに保持されます。

StatefulSet は、その Pod の ID と順序付けに序数インデックスを使用します。デフォルトで、StatefulSet の Pod は順番にデプロイされ、逆順で終了します。たとえば、web という StatefulSet に web-0web-1web-2 という Pod があるとします。web Pod の仕様が変更されると、それに属する Pod は正常に停止し、所定の順序に従って再作成されます。この例では、まず web-2 が終了し、次に web-1 が終了します。また、podManagementPolicy: Parallel フィールドで StatefulSet のすべての Pod を StatefulSet が一斉に起動または終了するように指定すると、ある Pod が稼働状態になるまで、あるいは終了するまで、別の Pod を起動または終了できないということがなくなります。

StatefulSets は Pod テンプレートを使用します。これには、StatefulSets の Pod の仕様が組み込まれています。Pod 仕様によって、各 Pod の外観(コンテナ内で実行するアプリケーション、マウントするボリューム、ラベルとセレクタなど)が決定されます。

使用パターン

StatefulSet は、Compute Engine の永続ディスクなどの永続ストレージにデータを保存するステートフル アプリケーションやクラスタ化されたアプリケーションをデプロイするように設計されています。StatefulSet は、Kafka、MySQL、Redis、ZooKeeper などの一意で永続的な ID と固有のホスト名が必要なアプリケーションのデプロイに適しています。ステートレス アプリケーションには、Deployment を使用します。

StatefulSet の作成

StatefulSet を作成するには、kubectl apply を使用します。

StatefulSet が作成されると、StatefulSet によって、指定された数の Pod が実行され、いつでも利用できる状態であることが保証されます。StatefulSet は、障害が起きた Pod や Node から削除された Pod を自動的に置き換え、新しい Pod を StatefulSet の Pod 仕様で定義されたストレージ リソース、リソースの要求と制限、およびその他の設定に自動的に関連付けます。

サービスと StatefulSet のマニフェスト ファイルの例を以下に示します。

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # Label selector that determines which Pods belong to the StatefulSet
                 # Must match spec: template: metadata: labels
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx # Pod template's label selector
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

この例では、

  • metadata: name フィールドで指定された、nginx という名前の Service オブジェクトが作成されます。この Service は、labels: app: nginxselector: app: nginx で指定された nginx というアプリをターゲットとします。また、ポート 80 を公開して web という名前を付けます。この Service は、ネットワーク ドメインを制御し、StatefulSet でデプロイしたコンテナ化されたアプリケーションにインターネット トラフィックをルーティングします。
  • 3 つの複製された Pod(replicas: 3)を使用して、web という StatefulSet が作成されます。
  • Pod テンプレート(spec: template)の指定により、その Pod に app: nginx というラベルが付けられます。
  • Pod 仕様(template: spec)は、StatefulSet の Pod が 1 つのコンテナ nginx を実行し、そのコンテナがバージョン 0.8nginx-slim イメージを実行するように指定します。コンテナ イメージは Container Registry によってホストされます。
  • Pod 仕様では、Service によって開かれた web ポートが使用されます。
  • template: spec: volumeMounts によって、www という mountPath が指定されます。mountPath は、ストレージ ボリュームがマウントされるコンテナ内のパスです。
  • StatefulSet は、1 GB のプロビジョニング済みストレージがある www という PersistentVolumeClaim をプロビジョニングします。

要約すると、Pod 仕様には次の指示が含まれています。

  • 各 Pod に app: nginx というラベルを付ける。
  • 各 Pod で、nginx というコンテナを 1 つ実行する。
  • バージョン 0.8nginx-slim イメージを実行する。
  • Pod にポート 80 を使用するよう指示する。
  • データをマウントパスに保存する。

StatefulSet 設定の詳細については、StatefulSet API リファレンスをご覧ください。

StatefulSet の更新

StatefulSet を更新するには、コンテナのイメージとボリュームを含むポッド仕様を変更します。また、オブジェクトのリソースの要求と制限、ラベル、および注釈を更新することもできます。StatefulSet の更新には、kubectl、Kubernetes API、Google Cloud Console の [GKE ワークロード] メニューを使用できます。

StatefulSet で更新の処理方法を決定する際は、spec: updateStrategy で定義された更新戦略が使用されます。OnDeleteRollingUpdate という 2 つの戦略があります

  • OnDelete では、オブジェクトの構成が変更される際に、自動的に Pod を削除、再作成しません。古い Pod を手動で削除し、更新された Pod をコントローラで作成する必要があります。
  • RollingUpdate では、オブジェクトの構成の変更時に、Pod が自動的に削除、再作成されます。古い Pod が削除される前に、新しい Pod を稼働状態にする必要があります。この戦略では、Pod 仕様を変更すると自動的にロールアウトがトリガーされます。これは、StatefulSet のデフォルトの更新戦略です。

StatefulSet は、Pod を逆順で更新します。次のコマンドを実行することにより、更新ロールアウトを監視できます。

kubectl rollout status statefulset statefulset-name

ローリング更新のパーティショニング

ローリング更新をパーティショニングすることができます。パーティショニングは、更新をステージングしたり、カナリアをロールアウトしたり、段階的ロールアウトを実行したりする場合に便利です。

更新をパーティショニングすると、StatefulSet の Pod 仕様が更新される際、序数がパーティション値以上になっている Pod がすべて更新されます。序数がパーティション値未満になっている Pod は更新されません。削除された場合は、以前のバージョンの仕様を使って再作成されます。パーティション値がレプリカ数を上回っている場合は、更新が Pod に伝播されません。

次のステップ