このトピックでは、ステートフルサービスの作成に StatefulSet が必要となる典型的なシナリオ、および StatefulSet の使用方法を解説します。

背景

N 個のレプリカを持つ StatefulSet は一般的に以下の条件の 1 つ以上が必要とされるアプリケーションに使用されます。
  • 決められた順番でのデプロイ。 ポットのデプロイや拡張が順に実行されること。 つまり、0 から N-1 までの定義された順番でポッドがデプロイされます。 新しいポッドがデプロイされる前に、先にデプロイされた全てのポッドが実行中または準備完了のステータスである必要があります。
  • 決められた順番でのスケーリング。 0 から N-1 までの定義された順番でポッドが削除されます。 ポッドが削除される前に、それに先立つオペレーションが全て実行中または準備完了のステータスである必要があります。
  • 固定された固有のネットワーク識別 ID。 ポッドが他のノードに対して再スケジューリングされた後、その PodName および HostName は変更されません。
  • PVC を介した安定した永続性ストレージの実装。 ポッドが再スケジューリングされた後、同じ永続データにアクセスできるようにします。

StatefulSet サービスの使用方法

volumeClaimTemplates を設定し、システムが自動的に PVC および PV を作成できるようにします。

このトピックでは以下の方法を解説します。
  • StatefulSet サービスのデプロイ
  • StatefulSet サービスのスケール
  • StatefulSet サービスの削除
  • StatefulSet サービスの永続ストレージ

前提条件

StatefulSet サービスのデプロイ

volumeClaimTemplates: 同じタイプの PVC のテンプレートです。 このフィールドを設定した場合、システムにより、StatefulSet サービスに設定されたレプリカ数に応じた PVC が作成されます。 つまり、PVC 数とレプリカ数が同じになります。 さらに、これらの PVC は名前以外は同じ設定になります。
  1. statefulset.yaml ファイルを作成します。
    storageClassName パラメーターに alicloud-disk-ssd を設定する必要があります。これは、Alibaba Cloud SSD クラウドディスクが使用されることを示しています。
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      ports:
      - port: 80
        name: web
      clusterIP: None
      selector:
        app: nginx
    ---
    apiVersion: apps/v1beta2
    kind: StatefulSet
    metadata:
      name: web
    spec:
      selector:
        matchLabels:
          app: nginx
      serviceName: "nginx"
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
              name: web
            volumeMounts:
            - name: disk-ssd
              mountPath: /data
      volumeClaimTemplates:
      - metadata:
          name: disk-ssd
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: "alicloud-disk-ssd"
          resources:
            requests:
              storage: 20Gi
  2. 以下のコマンドを実行し、StatefulSet サービスをデプロイします。
    $ kubectl create -f statefulset.yaml
  3. もう 1 つの Kubernetes インターフェイスを開きます。以下のコマンドを実行し、ポッドが順番にデプロイされたことを確認します。
    $ kubectl get pod -w -l app=nginx
    NAME         READY   STATUS    RESTARTS   AGE
    web-0        0/1     Pending   0          0s
    web-0        0/1     Pending   0          0s
    web-0        0/1     ContainerCreating    0          0s
    web-0        1/1     Running   0          20s
    web-1        0/1     Pending   0          0s
    web-1        0/1     Pending   0          0s
    web-1        0/1     ContainerCreating    0          0s
    web-1        1/1     Running   0          7s
  4. 以下のコマンドを実行し、デプロイされたポッドを表示します。
    $ kubectl get pod
    NAME                          READY   STATUS    RESTARTS   AGE
    web-0                         1/1     Running   0          6m
    web-1                         1/1     Running   0          6m
  5. 以下のコマンドを実行し、PVC を表示します。
    $ kubectl get pvc
    NAME             STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
    disk-ssd-web-0   Bound    d-2zegw7et6xc96nbojuoo   20Gi       RWO            alicloud-disk-ssd   7m
    disk-ssd-web-1   Bound    d-2zefbrqggvkd10xb523h   20Gi       RWO            alicloud-disk-ssd   6m

StatefulSet サービスのスケール

StatefulSet サービスのスケールアウト
  1. 以下のコマンドを実行し、StatefulSet サービスを 3 つのポッドにスケールアウトします。
    $ kubectl scale sts web --replicas=3
    statefulset.apps/web scaled
  2. 以下のコマンドを実行し、ポッドを表示します。
    $ kubectl get pod
    NAME                          READY   STATUS    RESTARTS   AGE
    web-0                         1/1     Running   0          34m
    web-1                         1/1     Running   0          33m
    web-2                         1/1     Running   0          26m
  3. 以下のコマンドを実行し、PVC を表示します。
    $ kubectl get pvc
    NAME             STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
    disk-ssd-web-0   Bound    d-2zegw7et6xc96nbojuoo   20Gi       RWO            alicloud-disk-ssd   35m
    disk-ssd-web-1   Bound    d-2zefbrqggvkd10xb523h   20Gi       RWO            alicloud-disk-ssd   34m
    disk-ssd-web-2   Bound    d-2ze4jx1zymn4n9j3pic2   20Gi       RWO            alicloud-disk-ssd   27m
StatefulSet サービスのスケールイン
  1. 以下のコマンドを実行し、StatefuleSet サービスを 2 つのポッドにスケールインします。
    $ kubectl scale sts web --replicas=2
    statefulset.apps/web scaled
  2. 以下のコマンドを実行し、ポッドを表示します。ポッド数が 2 つに削減されたことを確認します。
    $ kubectl get pod
    NAME                          READY   STATUS    RESTARTS   AGE
    web-0                         1/1     Running   0          38m
    web-1                         1/1     Running   0          38m
  3. 以下のコマンドを実行し、PVC を表示します。ポッド数の変更後に、PVC 数および PV 数に変更がないことを確認します。
    $ kubectl get pvc
    NAME             STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
    disk-ssd-web-0   Bound    d-2zegw7et6xc96nbojuoo   20Gi       RWO            alicloud-disk-ssd   39m
    disk-ssd-web-1   Bound    d-2zefbrqggvkd10xb523h   20Gi       RWO            alicloud-disk-ssd   39m
    disk-ssd-web-2   Bound    d-2ze4jx1zymn4n9j3pic2   20Gi       RWO            alicloud-disk-ssd   31m
StatefulSet サービスの再スケールアウト
  1. 以下のコマンドを実行し、StatefulSet サービスを 3 つのポッドにスケールアウトします。
    $ kubectl scale sts web --replicas=3
    statefulset.apps/web scaled
  2. 以下のコマンドを実行し、ポッドを表示します。
    $ kubectl get pod
    NAME                          READY   STATUS    RESTARTS   AGE
    web-0                         1/1     Running   0          1h
    web-1                         1/1     Running   0          1h
    web-2                         1/1     Running   0          8s
  3. 以下のコマンドを実行し、PVC を表示します。StatefulSet サービスのスケールアウト後に、新しく作成されたポッドが元の PVC および PV をそのまま使用していることを確認します。
    $ kubectl get pvc
    NAME             STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
    disk-ssd-web-0   Bound    d-2zegw7et6xc96nbojuoo   20Gi       RWO            alicloud-disk-ssd   1h
    disk-ssd-web-1   Bound    d-2zefbrqggvkd10xb523h   20Gi       RWO            alicloud-disk-ssd   1h
    disk-ssd-web-2   Bound    d-2ze4jx1zymn4n9j3pic2   20Gi       RWO            alicloud-disk-ssd   1h

StatefulSet サービスの削除

  1. 以下のコマンドを実行し、PVC が web-1 という名称のポッドに使用されていることを確認します。
    $  kubectl describe pod web-1 | grep ClaimName
        ClaimName:  disk-ssd-web-1
  2. 以下のコマンドを実行し、web-1 という名称のポッドを削除します。
    $ kubectl delete pod web-1
    pod "web-1" deleted
  3. 以下のコマンドを実行し、ポッドを表示します。再度作成されたポッドが削除されたポッドと同じ名前を共有していることを確認します。
    $ kubectl get pod
    NAME                          READY   STATUS    RESTARTS   AGE
    web-0                         1/1     Running   0          1h
    web-1                         1/1     Running   0          25s
    web-2                         1/1     Running   0          9m
  4. 以下のコマンドを実行し、PVC を表示します。再度作成されたポッドが削除されたポッドと同じ PVC を使用していることを確認します。
    $ kubectl get pvc
    NAME             STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS        AGE
    disk-ssd-web-0   Bound    d-2zegw7et6xc96nbojuoo   20Gi       RWO            alicloud-disk-ssd   1h
    disk-ssd-web-1   Bound    d-2zefbrqggvkd10xb523h   20Gi       RWO            alicloud-disk-ssd   1h
    disk-ssd-web-2   Bound    d-2ze4jx1zymn4n9j3pic2   20Gi       RWO            alicloud-disk-ssd   1h
  5. もう 1 つの Kubernetes インターフェイスを開きます。以下のコマンドを実行し、ポッドの削除処理およびポッドの再作成処理を表示します。
    $ kubectl get pod -w -l app=nginx
    NAME READY STATUS RESTARTS AGE
    web-0   1/1     Running   0          102m
    web-1   1/1     Running   0          69s
    web-2   1/1     Running   0          10m
    web-1   1/1   Terminating   0     89s
    web-1   0/1   Terminating   0     89s
    web-1   0/1   Terminating   0     90s
    web-1   0/1   Terminating   0     90s
    web-1   0/1   Pending   0     0s
    web-1   0/1   Pending   0     0s
    web-1   0/1   ContainerCreating   0     0s
    web-1   1/1   Running   0     20s

StatefulSet サービスの永続性ストレージ

  1. 以下のコマンドを実行し、/data パスにあるファイルを表示します。
    $ kubectl exec web-1 ls /data
    lost+found
  2. 以下のコマンドを実行し、/data パスに statefulset ファイルを作成します。
    $ kubectl exec web-1 touch /data/statefulset
  3. 以下のコマンドを実行し、/data パスにあるファイルを表示します。
    $ kubectl exec web-1 ls /data
    lost+found
    statefulset
  4. 以下のコマンドを実行し、web-1 という名前のポッドを削除します。
    $ kubectl delete pod web-1
    pod "web-1" deleted
  5. 以下のコマンドを実行し、/data パス内のファイルを表示し、statefulset という名前で作成されたファイルが削除されていなことを確認します。これは、クラウドディスク上のデータが永続的に保存されることを示しています。
    $ kubectl exec web-1 ls /data
    lost+found
    statefulset