一般的に使用されるコントローラーのStatefulSet

一般的に使用されるコントローラーのStatefulSet

1.はじめに

インスタンスと、インスタンスが外部データに依存しているアプリケーションとの間の不平等な関係は、「ステートフルアプリケーション」と呼ばれます。
インスタンス間のいわゆる不均等な関係は、分散アプリケーションの場合、各インスタンスと各アプリケーションの間に比較的大きな依存関係があることが多いことを意味します。たとえば、アプリケーションは他のアプリケーションの前に起動する必要があります。そうしないと、他のアプリケーションは起動されません。
外部データに依存する最も重要なアプリケーションはデータベースアプリケーションです。データベースアプリケーションの場合、データを永続的に保存する必要があります。ステートレスアプリケーションの場合、データベース内のデータを再起動すると、アプリケーションは接続を失います。明らかに違反私たちの当初の意図は、それを本番環境に移行することではありませんでした。

したがって、Kubernetesでのステートフルアプリケーションの効果的なサポートを解決するために、KubernetesはStatefulSetを使用してステートフルアプリケーションを調整および管理します。
StatefulSetはReplicaSetに似ていますが、ポッドの起動シーケンスを制御でき、ポッドごとに一意の識別子を設定できる点が異なります。次の機能があります。

  • 安定した一意のネットワーク識別子

  • 安定した永続的なストレージ

  • 整然としたエレガントな展開とスケーリング

  • 整然とした自動ローリングアップデート

StatefulSetの設計は理解しやすく、現実世界を次の2つの状況に抽象化します。
(1)トポロジー状態。これは、アプリケーション間に非対称の関係があることを意味します。アプリケーションは特定の順序で起動する必要があります。アプリケーションを再起動しても、指定された順序で再起動する必要があり、ネットワークIDは再起動後の元のネットワークIDと同じである必要があります。元のアクセスが保証されるように、ユーザーは同じ方法で新しいポッドにアクセスできます。
(2)ストレージの状態。つまり、アプリケーションは、いつ、どのような状況であっても、ストレージ内のデータが変更されない限り、読み取られるデータは同じである必要があり、保存されたデータにバインドされます。

したがって、StatefulSetのコア機能は、ポッドの状態を特定の方法で記録し、ポッドが再作成されたときに何らかの方法でその状態を復元することです。

二、ヘッドレスサービス

StatefulSetを紹介する前に、まずヘッドレスサービスとは何かを理解しましょう。
Kubernetesでは、サービスはポッドのグループへの外部アクセスを提供する方法であることを私たちは知っています。通常、サービスを使用してポッドにアクセスするには、次の2つの方法があります。
(1)クラスターIPを介して、このクラスターIPはVIPと同等です。このIPにアクセスすると、リクエストはバックエンドポッドに転送されます。
(2)DNSを介してこの方法では、最初にKubernetesクラスターにDNSサービスがあることを確認する必要があります。このとき、「my-service.my-namespace.svc、cluster.local」にアクセスする限り、my-serviceという名前のサービスによってプロキシされるバックエンドポッドにアクセスできます。

2番目の方法には、次の2つの処理方法があります。
(1)通常のサービス、つまりドメイン名を解決し、クラスターIPを取得してから、方法1に従ってアクセスします。
(2)ヘッドレスサービス、つまり、ドメイン名を解決して取得します。バックエンドのポッドのIPアドレスであるため、直接アクセスできます。

2番目の処理方法では、クラスターIPは必要ないことがわかりますが、バックエンドポッドのIPアドレスは、アクセス用のドメイン名を介して直接解決されます。
以下は、ヘッドレスサービスの簡単なYAMLファイル定義です。

apiVersion: v1

kind: Service

metadata:

  name: nginx

  labels:

    app: nginx

spec:

  ports:

  - port: 80

    name: web

  clusterIP: None

  selector:

    app: nginx

上記のYAMLファイルから、通常のサービス定義とあまり違いがないことがわかります。唯一の違いは、clusterIPがNoneに設定されている、つまりクラスターが不要であるということです。このサービスはkubectl apply-fを使用して作成します。 、次にサービスのクラスターIPがNoneであることを確認します。
一般的に使用されるコントローラーのStatefulSet

この方法で作成されたサービスはヘッドレスサービスであり、VIPがないため、プロキシされたポッドがDNSレコードの形式で公開されます。

3、StatefulSetを使用します

次のように、StatefulSetを作成する前にPVを作成します。

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv01

  labels:

    release: stable

spec:

  capacity:

    storage: 1Gi

  accessModes:

  - ReadWriteOnce

  persistentVolumeReclaimPolicy: Recycle

  hostPath:

    path: /tmp/data

---

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv02

  labels:

    release: stable

spec:

  capacity:

    storage: 1Gi

  accessModes:

  - ReadWriteOnce

  persistentVolumeReclaimPolicy: Recycle

  hostPath:

    path: /tmp/data

次に、次のようにkubectl apply-fを実行してPVを開始します。

[root@master statefulset]# kubectl apply -f pv.yaml

persistentvolume/pv01 created

persistentvolume/pv02 created

[root@master statefulset]# kubectl get pv

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE

pv01   1Gi        RWO            Recycle          Available                                   10s

pv02   1Gi        RWO            Recycle          Available                                   9s

2つのPVの状態が両方とも利用可能であることがわかり、StatefulSetのYAMLファイルを書き込みます。

apiVersion: v1

kind: Service

metadata:

  name: nginx

spec:

  ports:

  - port: 80

    name: web

  clusterIP: None

  selector:

    app: nginx

    role: stateful

---

apiVersion: apps/v1

kind: StatefulSet

metadata:

  name: web

spec:

  serviceName: "nginx"

  replicas: 2

  selector:

    matchLabels:

      app: nginx

  template:

    metadata:

      labels:

        app: nginx

        role: stateful

    spec:

      containers:

      - name: nginx

        image: cnych/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

volumeMountsに関連付けられた上記のYAMLファイルは新しい属性であることに注意してください:volumeClaimTemplates、この属性は管理用のpvcオブジェクトとpvを自動的に宣言します。serviceName: "nginx"は、制御ループの実行時にnginxのヘッドレスが使用されることを意味します。ポッドの解決可能なIDを保存するサービス。

次に、ここで2つのターミナルウィンドウを開きます。最初のターミナルで、kubectl getを使用して、StatefulSetのポッドの作成を表示します。

$ kubectl get pods -w -l role=stateful

別のターミナルで、kubectl createを使用して、statefulset-demo.yamlで定義されたヘッドレスサービスとStatefulSetを作成します。

$ kubectl create -f statefulset-demo.yaml

service "nginx" created

statefulset.apps "web" created

次に、ポッドの起動シーケンスを観察します。

[root@master ~]# kubectl get pods -w -l role=stateful

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     3m12s

web-1   0/1   Pending             0     0s

web-1   0/1   Pending             0     0s

web-1   0/1   Pending             0     1s

web-1   0/1   ContainerCreating   0     1s

web-1   1/1   Running             0     5s

上記の作成プロセスを通じて、StatefulSetが管理するポッドに番号を付けることがわかります。その命名規則は[statefulset-name]-[index]であり、インデックスは0から始まります。これはStatefulSetの各ポッドインスタンスと同じです。対応、繰り返さないでください。さらに重要なことに、ポッドの作成プロセスはシーケンシャルです。上記のように、web-1は、web-0が実行状態に入った後、保留状態になります。

このコマンドを使用して、作成結果を表示します。

[root@master statefulset]# kubectl get statefulset web

NAME   READY   AGE

web    2/2     17m

[root@master statefulset]# kubectl get pods -l role=stateful

NAME    READY   STATUS    RESTARTS   AGE

web-0   1/1     Running   0          17m

web-1   1/1     Running   0          14m

[root@master statefulset]# kubectl get svc nginx

NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE

nginx   ClusterIP   None         <none>        80/TCP    17m

両方のポッドが実行状態に入ると、それぞれのネットワークIDを表示できます。次のようにkubectlexecを介して表示できます。

[root@master statefulset]# kubectl exec web-0 -- sh -c 'hostname'

web-0

[root@master statefulset]# kubectl exec web-1 -- sh -c 'hostname'

web-1

2つのポッドのホスト名とポッド名が同じであり、すべて対応する番号が割り当てられていることがわかります。次に、DNSを使用してヘッドレスサービスにアクセスします。
まず、次のコマンドでポッドを起動します。

kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh

次に、nslookupを使用して、このポッド内のポッドに対応するヘッドレスサービスを解析します。

kubectl run -i --tty --image centos dns-test --restart=Never --rm /bin/sh

sh-4.2# yum install bind-utils -y

sh-4.2# nslookup web-0.nginx

Server:        10.68.0.2

Address:    10.68.0.2#53

Name:    web-0.nginx.default.svc.cluster.local

Address: 172.20.2.63

sh-4.2# nslookup web-1.nginx

Server:        10.68.0.2

Address:    10.68.0.2#53

Name:    web-1.nginx.default.svc.cluster.local

Address: 172.20.2.64

nslookupの結果の分析から、web-0.nginxにアクセスすると、ポッドweb-0のIPが解析され、もう一方は同じです。
このとき、2つのポッドを削除した場合は、ポッドを再起動するプロセスを確認してください。

[root@master statefulset]# kubectl delete pod -l role=stateful

pod "web-0" deleted

pod "web-1" deleted

次に、次のように再起動シーケンスを確認します。

[root@master ~]# kubectl get pods -w -l role=stateful

NAME    READY   STATUS    RESTARTS   AGE

web-0   0/1     ContainerCreating   0          0s

web-0   1/1     Running             0          2s

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          2s

ポッドを削除した後も、その再起動シーケンスは元の番号に従って再起動され、ネットワークIDは以前と同じままであることがわかります。
この厳密な対応ルールにより、StatefulSetはポッドのネットワークIDの安定性を保証します。この方法により、ポッドのトポロジ状態をポッドの名前+番号に従って固定できます。さらに、Kubernetesは、ポッドごとに固定された一意のアクセスエントリ、つまりポッドのDNSレコードも提供します。

PVとPVCの結合も確認できます。

[root@master statefulset]# kubectl get pv

NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE

pv01   1Gi        RWO            Recycle          Bound    default/www-web-0                           129m

pv02   1Gi        RWO            Recycle          Bound    default/www-web-1                           129m

[root@master statefulset]# kubectl get pvc

NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE

www-web-0   Bound    pv01     1Gi        RWO                           124m

www-web-1   Bound    pv02     1Gi        RWO                           116m

したがって、StatefulSetは次のように分類されます。
(1)、StatefulSetはポッドを直接管理します。これは、StatefulSetのPodインスタンスがReplicaSetのPodインスタンスと完全に同じではないためです。これらはわずかに異なります。たとえば、各Podの名前とホスト名が異なり、StatefulSetがこれらのインスタンスを区別する方法は次のとおりです。ポッド番号を追加するには、
(2)、Kubernetesは、ヘッドレスサービスを介して、この番号の付いたポッドのDNSサーバーに同じ番号のレコードを生成します。StatefulSetがこのポッドの数が変更されないことを保証できる限り、サービスのweb-0.nginx.default.svc.cluster.localに類似したDNSレコードは変更されず、ポッドのIPアドレスはこのレコードによって解決されますポッドの再作成で自動的に更新されます。
(3)StatefulSetは、各ポッドのポッドと同じ番号のPVCを割り当てて作成することもできます。このようにして、Kubernetesは、Persitent Volumeメカニズムを介して対応するPVをこのPVCにバインドし、各ポッドに独立したボリュームがあることを確認できます。この場合、ポッドが削除されても、対応するPVCとPVは保持されるため、ポッドが再作成されると、Kubernetesは同じ番号のPVCを見つけて、PVCに対応するボリュームをマウントします。Get前のボリュームの前のデータ。

4、まとめ

StatefulSetコントローラーの主な機能の1つは、ポッドテンプレートを使用してポッドを作成するときにそれらに番号を付け、番号の順序でタスクを完了することです。StatefulSetの制御ループが、ポッドの実際の状態がと矛盾していることを検出した場合期待される状態で、ポッドも順番に操作します。

もちろん、StatefulSetには他の機能もあります。実際のプロジェクトでは、自分で完全に保持できない限り、StatefulSetを介してステートフルサービスに戻って直接デプロイすることはめったにありません。特定のサービスによっては、より高度なオペレーターを使用する場合があります。 etcd-operator、prometheus-operatorなどとして。ステートフルアプリケーションの場合、最も重要なことはデータリカバリ、フェイルオーバーなどであるため、これらのアプリケーションは、StatefulSetを使用してポッドをデプロイするだけでなく、ステートフルサービスを非常にうまく管理できます。

終了

おすすめ

転載: blog.51cto.com/15080014/2654577