ステートフルワークロード(StatefulSet)

StatefulSetが必要な理由

Deploymentでは、Deploymentについて説明しました。Deploymentコントローラーの下のポッドには共通の機能があります。つまり、各ポッドは名前とIPアドレスを除いて同一です。必要に応じて、Deploymentはポッドテンプレートを介して新しいポッドを作成できます。不要な場合、Deploymentは任意のポッドを削除できます。

ただし、一部のシナリオでは、これは需要を満たしません。たとえば、一部の分散シナリオでは、分散データベースなど、各ポッドに独自の個別の状態が必要な場合、各ポッドには個別のストレージが必要です。需要を満たすことができません。

ステートフルアプリケーションの要件の詳細な分析では、分散ステートフルネスの特徴は、主にアプリケーションの各部分の役割(つまり、分業)が異なることです。たとえば、データベースにはアクティブとスタンバイがあり、ポッド間に依存関係があります。Kubernetesに対応するのはポッドです。要件は次のとおりです。

  • ポッドは他のポッドで見つけることができます。ポッドには固定のロゴが必要です。
  • 各ポッドには個別のストレージがあります。ポッドを削除して復元した後、読み取られるデータは以前と同じである必要があります。そうでない場合、ステータスに一貫性がなくなります。
    Kubernetesは、この問題を解決するためのStatefulSetを提供しています。これは次のとおりです。
  1. StatefulSetは、各ポッドに固定名を提供します。ポッド名は、0からNまでの固定サフィックスを追加します。ポッドが再スケジュールされた後、ポッド名とHostNameは変更されません。
  2. StatefulSetは、ヘッドレスサービスを介して各ポッドに固定アクセスドメイン名を提供します。サービスの概念については、サービスで詳しく説明します。
  3. StatefulSetは、固定識別子を持つPVCを作成することにより、ポッドが再スケジュールされた後でも同じ永続データにアクセスできるようにします。

ステートフルワークロード(StatefulSet)

以下では、StatefulSetを作成することにより、StatefulSetのこれらの特性を体験します。

ヘッドレスサービスを作成する

前述のように、ステートフルセットを作成するには、ポッドアクセス用のヘッドレスサービスが必要です。サービスの概念については、サービスで詳しく説明します。ここでは、最初にヘッドレスサービスを作成する方法を紹介します。

次のファイルを使用して、ヘッドレスサービスについて説明します。

  • spec.clusterIP:Noneに設定する必要があります。これは、ヘッドレスサービスを意味します。
  • spec.ports.port:ポッド間の通信ポート番号。
  • spec.ports.name:ポッド間の通信ポートの名前。
    apiVersion: v1
    kind: Service       # 对象类型为Service
    metadata:
    name: nginx
    labels:
    app: nginx
    spec:
    ports:
    - name: nginx     # Pod间通信的端口名称
      port: 80        # Pod间通信的端口号
    selector:
    app: nginx        # 选择标签为app:nginx的Pod
    clusterIP: None     # 必须设置为None,表示Headless Service

次のコマンドを実行して、ヘッドレスサービスを作成します。

# kubectl create -f headless.yaml 
service/nginx created

作成後にサービスを照会できます。

# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx        ClusterIP   None         <none>        80/TCP    5s

Statefulsetを作成する

StatefulsetのYAML定義は基本的に他のオブジェクトと同じですが、2つの主な違いがあります。

  • serviceNameは、Statefulsetが使用するヘッドレスサービスを指定し、ヘッドレスサービスの名前を入力する必要があります。
  • volumeClaimTemplatesは、永続宣言PVCを適用するために使用されます。dataという名前のテンプレートがここで定義されます。ポッドごとにPVCが作成されます。storageClassNameは、永続ストレージのタイプを指定します。これについては、PV、PVC、およびStorageClassで詳しく説明します。volumeMountsポッド用のストレージをマウントすることです。もちろん、volumeClaimTemplatesフィールドとvolumeMountsフィールドを保存する必要がない場合は、それらを削除できます。
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
    name: nginx
    spec:
    serviceName: nginx                             # headless service的名称
    replicas: 3
    selector:
    matchLabels:
      app: nginx
    template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: container-0
          image: nginx:alpine
          resources:
            limits:
              cpu: 100m
              memory: 200Mi
            requests:
              cpu: 100m
              memory: 200Mi
          volumeMounts:                           # Pod挂载的存储
          - name:  data
            mountPath:  /usr/share/nginx/html     # 存储挂载到/usr/share/nginx/html
      imagePullSecrets:
        - name: default-secret
    volumeClaimTemplates:
    - metadata:
      name: data
    spec:
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
      storageClassName: csi-nas                   # 持久化存储的类型

次のコマンドを実行して作成します。

# kubectl create -f statefulset.yaml 
statefulset.apps/nginx created

コマンドが実行された後、StatefulSetとPodを照会すると、ポッドの名前の接尾辞が0から2で始まり、1つずつ増加していることがわかります。

# kubectl get statefulset
NAME    READY   AGE
nginx   3/3     107s

# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
nginx-0   1/1     Running   0          112s
nginx-1   1/1     Running   0          69s
nginx-2   1/1     Running   0          39s

この時点で、nginx-1ポッドを手動で削除してから、ポッドを再度クエリすると、StatefulSetが同じ名前のポッドを再作成したことがわかります。nginx-1は作成時間5秒までに作成されたばかりであることがわかります。

# kubectl delete pod nginx-1
pod "nginx-1" deleted

# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
nginx-0   1/1     Running   0          3m4s
nginx-1   1/1     Running   0          5s
nginx-2   1/1     Running   0          1m10s

コンテナを入力してコンテナのホスト名を表示します。これもnginx-0、nginx-1、およびnginx-2であることがわかります。

# kubectl exec nginx-0 -- sh -c 'hostname'
nginx-0
# kubectl exec nginx-1 -- sh -c 'hostname'
nginx-1
# kubectl exec nginx-2 -- sh -c 'hostname'
nginx-2

同時に、StatefulSetによって作成されたPVCを確認できます。これらのPVCには、「PVC name-StatefulSet name-number」という名前が付けられ、バインドされた状態になっていることがわかります。

# kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-nginx-0   Bound    pvc-f58bc1a9-6a52-4664-a587-a9a1c904ba29   1Gi        RWX            csi-nas        2m24s
data-nginx-1   Bound    pvc-066e3a3a-fd65-4e65-87cd-6c3fd0ae6485   1Gi        RWX            csi-nas        101s
data-nginx-2   Bound    pvc-a18cf1ce-708b-4e94-af83-766007250b0c   1Gi        RWX            csi-nas        71s

StatefulSetのネットワークID

StatefulSetが作成されると、ポッドの名前が固定されていることがわかります。ヘッドレスサービスはどのように機能しますか?DNSを使用してポッドの固定ドメイン名を提供し、ポッドが再作成された場合でもドメイン名を使用してポッドにアクセスできるようにします。その結果、ポッドのIPアドレスが変更され、ドメイン名は変更されません。

ヘッドレスサービスが作成されると、各ポッドのIPには次の形式のドメイン名が付けられます。

<pod-name>。<svc-name>。<namespace> .svc.cluster.local

たとえば、上記の3つのポッドのドメイン名は次のとおりです。

  • nginx-0.nginx.default.svc.cluster.local
  • nginx-1.nginx.default.svc.cluster.local
  • nginx-1.nginx.default.svc.cluster.local
    実際のアクセスには省略できます。<namespace> .svc.cluster.local

次のコマンドは、tutum / dnsutilsイメージを使用してポッドを作成し、ポッドコンテナーに入り、nslookupコマンドを使用してポッドに対応するドメイン名を表示します。ポッドのIPアドレスを解決できることがわかります。ここで、DNSサーバーのアドレスが10.247.3.10であることがわかります。これは、DNSサービスを提供するCCEクラスターを作成するときのCoreDNSプラグインのデフォルトのインストールです。CoreDNSの役割については、後でKubernetesネットワークで詳しく説明します。

$ kubectl run -i --tty --image tutum/dnsutils dnsutils --restart=Never --rm /bin/sh 
If you don't see a command prompt, try pressing enter.
/ # nslookup nginx-0.nginx
Server:         10.247.3.10
Address:        10.247.3.10#53
Name:   nginx-0.nginx.default.svc.cluster.local
Address: 172.16.0.31

/ # nslookup nginx-1.nginx
Server:         10.247.3.10
Address:        10.247.3.10#53
Name:   nginx-1.nginx.default.svc.cluster.local
Address: 172.16.0.18

/ # nslookup nginx-2.nginx
Server:         10.247.3.10
Address:        10.247.3.10#53
Name:   nginx-2.nginx.default.svc.cluster.local
Address: 172.16.0.19

この時点で、これら2つのポッドを手動で削除し、StatefulSetによって再作成されたポッドのIPを照会してから、nslookupコマンドを使用してポッドのドメイン名を解決すると、nginx-0.nginxおよびnginx-1.nginxが対応するポッドを解決できることがわかります。これにより、StatefulSetネットワークIDが変更されないことが保証されます。

StatefulSetは状態を保存します

前述のように、StatefulSetをPVCを介した永続ストレージに使用して、ポッドの再スケジュール後に同じ永続データにアクセスできるようにすることができます。ポッドが削除されても、PVCは削除されません。

図1StatefulSetのポッド再構築プロセス
ステートフルワークロード(StatefulSet)

以下は、これが実際の操作でどのように行われるかを確認し、次のコマンドを実行し、nginx-1のディレクトリ/ usr / share / nginx / htmlにコンテンツを書き込みます。たとえば、index.htmlのコンテンツを「hello」に変更します。世界"。

# kubectl exec nginx-1 -- sh -c 'echo hello world > /usr/share/nginx/html/index.html'

変更後、ポッドでアクセスした場合“http://localhost”,那就会返回“hello world”

# kubectl exec -it nginx-1 -- curl localhost
hello world

この時点で、nginx-1ポッドを手動で削除してから、ポッドを再度クエリすると、StatefulSetが同じ名前のポッドを再作成したことがわかり、nginx-1が作成時間4秒までに作成されたことがわかります。

# kubectl delete pod nginx-1
pod "nginx-1" deleted

# kubectl get pods
NAME       READY   STATUS    RESTARTS   AGE
nginx-0    1/1     Running   0          14m
nginx-1    1/1     Running   0          4s
nginx-2    1/1     Running   0          13m

ポッドのindex.htmlページに再度アクセスすると、「hello world」がまだ返されていることがわかります。これは、ポッドが引き続き同じストレージにアクセスしていることを意味します。

# kubectl exec -it nginx-1 -- curl localhost
hello world

おすすめ

転載: blog.51cto.com/14051317/2553698