Kubernetes ノート (13) - ステートフル アプリケーション StatefulSet、StatefulSet データ永続性の実現

1. ステートフル アプリケーションとは

永続ストレージを使用するとPersistentVolume、アプリケーションは実行時にいくつかの重要なデータをディスクに置くことができます。これは「保険」を持つことと同じです。予期しないクラッシュがPod発生したVolume。そして元のデータをロードして全血で復活させ、以前の「状態」を復元して実行を続けます。

したがって、この観点から、理論的にはすべてのアプリケーションはステートフルです。

ただ、一部のアプリケーションの状態情報はあまり重要ではなく、状態を復元しなくても正常に実行できるアプリケーションもあり、これを「ステートレス アプリケーション」と呼んでいます。「ステートレス アプリケーション」の典型NginxWebHTTPリクエストを状態を保存する必要がなく、状態に関係なく外部サービスを提供できます。で再開。

一部のアプリケーションでは、実行中のステータス情報が非常に重要です. 再起動によって状態が失われることは絶対に許されません. このようなアプリケーションは「ステートフルなアプリケーション」です.

「ステートフルなアプリケーション」の例もたくさんあります. 例えばRedis,MySQLそのようなデータベースでは, それらの「状態」はメモリ上またはディスク上に生成されたデータであり, これがアプリケーションの核となる価値です. これらのデータをアプリケーションで保存および復元できない場合時間、そして絶対に悲惨な結果。

これを理解したら、これまでに学んだ知識に基づいて考えてみましょう:DeploymentさらにPersistentVolumeKubernetesで?

確かにDeployment、高可用性を確保し、PersistentVolumeデータを保存するために使用すると、「ステートフル アプリケーション」を管理するという目的を部分的に達成できます。

ただしKubernetes、ビジョンはより包括的で長期的なものであり、「状態」はデータの永続性だけではないと考えています. クラスター化および分散シナリオでは、複数インスタンスの依存関係、起動シーケンス、ネットワーク識別などの問題も必要です.これらの問題はDeployment私たちの手の届か。

使うだけなのでDeployment、複数のインスタンスが関係なく、起動順序が固定されておらず、アプリケーションのPod名前、アドレス、ドメイン名が完全にランダムであり、まさに「ステートレス アプリケーション」の特徴です。IP

ただし、「ステートフル アプリケーション」の場合、複数のインスタンス間に依存関係がある場合があります。たとえばmaster/slaveactive/passiveアプリケーションの正常な動作を保証するために、 を順番に開始する必要があり、外部クライアントも固定のネットワーク識別子を使用してインスタンスにアクセスする場合があります。Pod再起動。

そのため、新しいオブジェクトKubernetesDeploymentAPI、その名前もわかりやすく、StatefulSetステートフル アプリケーションを管理するために特別に使用される と呼ばれます。

2. YAML を使用して StatefulSet を記述する

まず、コマンドを使用してkubectl api-resourcesStatefulSet基本情報を表示します。その略語は でありstsYAMLファイル ヘッダー情報は次のとおりです。


apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: xxx-sts

DaemonSetと同様に のStatefulSet特殊なDeploymentケース、kubectl createテンプレート ファイルの作成に直接使用することはできませんが、そのオブジェクトの記述はDeploymentと同様であり、オブジェクトDeploymentになるように適切に変更することもできます。StatefulSet

ここで の使い方RedisStatefulSet。それと の違いDeploymentを。

# redis-sts.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-sts

spec:
  serviceName: redis-svc
  replicas: 2
  selector:
    matchLabels:
      app: redis-sts

  template:
    metadata:
      labels:
        app: redis-sts
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379

mustYAML be in the file に加えて、 には追加のフィールドがあり、残りなどの とまったく同じであることがわかります。kindStatefulSetspecserviceNameDeploymentreplicasselectortemplate

これら 2 つの違いは、StatefulSet実際にDeploymentは と の主な違いです。これを本当に理解するには、そこで使用されている方法と組み合わせて分析するStatefulSet必要があります。Kubernetes

3. Kubernetes で StatefulSet を使用する

でオブジェクトkubectl apply作成し、最初に でどのように見えるか見てみましょう:StatefulSetkubectl get


kubectl apply -f redis-sts.yml
kubectl get sts
kubectl get pod

sts

StatefulSetスクリーンショットから、マネージド がランダムな名前でPodはなく、0 から始まり、それぞれ名前が付けられた連番を持ちredis-sts-0この順序で作成されることを確認できるはずです (番号 0 は番号 1 より多いredis-sts-1ですKubernetesAGE はもう少し長くなります)。これにより、「ステートフル アプリケーション」の最初の問題である起動順序が解決されます。

起動の順序で、アプリケーションはどのように自分の ID を認識し、それらの間の依存関係を判断するのでしょうか?

Kubernetes与えられた方法は、を使用することですhostname。つまり、Pod各の。kubectl execログインしてPod内部ましょう。


kubectl exec -it redis-sts-0 -- sh

ホスト名

この名前は環境変数を表示するか、Pod$HOSTNAMEコマンドを実行することで取得できますhostnamePodredis-sts-0

この一意の名前を使用すると、アプリケーションは依存関係を独自に判断できます。たとえば、このRedis例最初のインスタンス 0 をPodマスター インスタンスに、2 番目のインスタンス 1 をスレーブ インスタンスPodにできます。

起動シーケンスと依存関係を解決しても、まだ 3 番目の問題があります。それは、Serviceオブジェクト。

しかし、ここで別の奇妙なことがあります。コマンドを使用して を直接生成するkubectl exposeことはできません。手動でしか記述できませんStatefulSetServiceYAML

オブジェクトは自動的に生成されないため、 Serviceobjectですmetadata.nameStatefulSetserviceNameselectorStatefulSet

# redis-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: redis-svc

spec:
  selector:
    app: redis-sts

  ports:
  - port: 6379
    protocol: TCP
    targetPort: 6379

を書き込んServiceだ後、次のようにkubectl applyオブジェクトを作成します。

redis-svc

これには特別なServiceこと。また、ラベル セレクターを使用してStatefulSet2 つの管理対象を見つけPod、次にそれらのIPアドレス。

しかし、StatefulSet最大の謎はそのドメイン名にあります。

Service「オブジェクト名.名前空間」の形式のドメイン名があり、それぞれに「IP アドレス.名前空間」の形式のドメイン名Podもあります。ただし、IPアドレス、Podのドメイン名は実用的ではなく、一般的には の安定したServiceドメイン名。

Serviceオブジェクトを に適用するStatefulSetと、状況が異なります。

Serviceこれらは通常のアプリケーションPodではなくため、Pod新しいドメイン名はそれ以上作成されず、形式はPod 名. 服务名. 名字空间.svc.cluster.local. もちろん、このドメイン名はPod 名. 服务名.

kubectl exec内部に入りPodpingコマンドを確認します。


kubectl exec -it redis-sts-0 -- sh

実行ping

明らかに、これらはどちらStatefulSetPod独自のドメイン名、つまり安定したネットワーク ID を持っています。次に、外部クライアントがStatefulSetオブジェクトを、固定番号を使用して特定のインスタンスにアクセスできます. のアドレスPodは変更される可能性がありますが、番号付きドメイン名はオブジェクトによって維持され、安定しています.IPService

これまでのところStatefulSetServiceと を併用することで、Kubernetes「ステートフル アプリケーション」の依存関係、起動シーケンス、ネットワーク識別の 3 つの問題が解決されていますが、残りの内部通信と複数のインスタンス間の調整は、アプリケーション自体で解決する必要があります。と。

についてService、もう一つ特筆すべき点があります。

Service本来の目的はロード バランシングであり、Podの前でが、StatefulSet の場合、この機能は不要です。これは、Podすでに安定したドメイン名があり、外部アクセス サービスがServiceこの層を通過してはならないためです。したがって、セキュリティとシステム リソースの節約の観点からServiceこのオブジェクトにアドレスを割り当てる必要がないことclusterIP: Noneを示すフィールドを追加できます。KubernetesIP

StatefulSet オブジェクトと Service オブジェクトの関係を示す図を描きました。これらのフィールド間の相互参照を参照できます。
画像.png

4. StatefulSet のデータ永続性を実現する

StatefulSet名前、起動順序、ネットワーク識別子が決まったので、そこにデータ永続化機能を追加すれば、「ステートフルなアプリケーション」の管理が実現できます。

前のレッスンで学んPersistentVolumeNFS. 簡単に定義しStorageClass、書きPVCPodマウントすることができますVolume.

ただし、永続ストレージとStatefulSetの間の、フィールドはKubernetesのためにStatefulSet特別にvolumeClaimTemplatesPVCその定義はのファイルStatefulSetに直接埋め込まれます。YAMLこれにより、 がStatefulSet作成される、それぞれがPod自動的に作成されPVCの可用性が高くなります。StatefulSet

volumeClaimTemplatesこの分野はちょっとわかりにくそうですがPod、と比べてみるわかりますtemplateJobjobTemplateStorageClassPVC

今すぐRedis StatefulSetオブジェクト、永続的なストレージ機能を追加しましょう:

# redis-pv-sts.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-pv-sts

spec:
  serviceName: redis-pv-svc

  volumeClaimTemplates:
  - metadata:
      name: redis-100m-pvc
    spec:
      storageClassName: nfs-client
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Mi

  replicas: 2
  selector:
    matchLabels:
      app: redis-pv-sts

  template:
    metadata:
      labels:
        app: redis-pv-sts
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379

        volumeMounts:
        - name: redis-100m-pvc
          mountPath: /data

まず、StatefulSetオブジェクトの名前は ですredis-pv-sts。これは、PVストレージ。次に、1 つがvolumeClaimTemplatesPVC、名前は でredis-100m-pvc、100MB のNFSストレージ。これはPodテンプレートで参照され、ネットワーク ディスクはデータ ディレクトリであるディレクトリにマウントされます。volumeMountsPVC/dataRedis

次の図は、このStatefulSetオブジェクト:
画像.png最初に上記のセクションを実行します

kubectl apply -f rbac.yml
kubectl apply -f class.yml
kubectl apply -f deployment.yml

次に実行

kubectl apply -f redis-pv-svc.yml

最後に、これらのオブジェクトkubectl applyを作成すると、永続化機能を備えた「ステートフル アプリケーション」が実行されます。


kubectl apply -f redis-pv-sts.yml

次のコマンドを使用してkubectl get pvcStatefulSet関連するストレージ ボリュームのステータスを表示できます。

get_pvc

この2つPVCの、ランダムではなく規則的で、PVC名前StatefulSet+名前で構成されているPodので、破壊されても名前が変わらないので、再びPVCバインドする前にこれを見つけることができます。保存されたデータ。

次に、その場で確認して、kubectl exec実行Redis中のクライアントを使用してKVデータ。


kubectl exec -it redis-pv-sts-0 -- redis-cli

キーを設定する

ここでは、a=111 と b=222 の 2 つの値を設定します。

不測の事態をシミュレートしたので、これを削除しますPod


kubectl delete pod redis-pv-sts-0

は のようStatefulSetための数が少ないことが判明した場合、新しいインスタンスがすぐに作成され、名前とネットワーク ID は以前とまったく同じに。DeploymentPodPodPodPod

ポッドを削除

Redisそこに保存されたデータはどうなりましたか? 永続ストレージは本当に使用され、完全に復元されていますか?

Redisクライアントで再度ログインして、以下を確認できます。


kubectl exec -it redis-pv-sts-0 -- redis-cli

キーを取得する

ディレクトリにNFSネットワークストレージをマウントしたので、定期的にデータをディスクに保存しますので、新しく作成したディレクトリを再度バックアップファイルからデータが復元され、メモリ内のデータが復元されます。元の状態に復元されました。Pod/dataRedisPod

5. まとめ

このセクションでは、「ステートフル アプリケーション」の展開専用のAPIオブジェクトStatefulSet。これはオブジェクトにDeployment非常が、違いPodは、固定された名前、起動シーケンス、およびネットワーク ID を持つことです。同値関係の適用は非常に重要です。 .

  1. StatefulSetYAML説明はDeploymentとほぼ同じですが、もう 1 つのキー フィールドがありますserviceName
  2. StatefulSetの安定したドメイン名を生成するには、 の名前一致する名前のオブジェクトPodを定義する必要があります。ServiceStatefulSetserviceName
  3. アクセスでStatefulSetPod、 の形式でPod 名. 服务名、それぞれに個別のドメイン名を使用する必要があり、Serviceの。
  4. StatefulSetフィールドを使用しvolumeClaimTemplatesて直接定義できるのでPVC、永続的なデータ ストレージPodを実現できます。

volumeClaimTemplatesインライン定義を使用しない場合PVC、複数のコピーが同じネットワーク ストレージ デバイスをマウントする可能性があり、データが失われる可能性があります。

Podサービス担当、Jobスケジューリング担当、

Daemon/Deploymentステートレスな展開を担当し、StatefulSetステートフルな展開を担当し、

Service4 層アクセス (負荷分散、IP 割り当て、ドメイン名アクセス) を担当し、Ingressアプリケーション層 (7 層) アクセス (ルーティング ルール) を担当します。

PVC/PV信頼性の高いストレージを担当します。

おすすめ

転載: blog.csdn.net/wohu1104/article/details/129808188