DaemonSet と StatefulSet の使用
Pod
今回は、このようなオブジェクトリソースの使い方を中心に説明しましたが、次に、特定の場面で使用するコントローラー、 、Deployment
について説明します。DaemonSet
StatefulSet
DaemonSet の使用
コントローラーの名前から、その用途がわかります: デーモンはデーモン プロセスをデプロイするために使用され、デーモン プロセスのコピーをDaemonSet
各Kubernetes
ノードでバックグラウンド プロセスとして実行するために使用されます。各ノードのデーモン プロセスをPod
コピーすると、ノードがKubernetes
クラスターに参加すると、Pod
そのノードで実行されるようにスケジュールされます。ノードがクラスターからのみ削除できる場合は、ノード上のこのノードも削除されますPod
。 、すべて、およびこのオブジェクトを削除しますDaemonSet
。関連するものがPods
削除されます。
このビジネス シナリオを使用する必要があるのはどのような状況ですか? 実際、次のようなこのシナリオは比較的一般的です。
- クラスターストレージデーモン。たとえば、永続ストレージを提供するため
glusterd
にceph
各ノードにデプロイされます。 - 監視クラスターなどのノード監視デーモンは
Prometheus
、各ノードでプロセスを実行して、node-exporter
監視ノードに関する情報を収集できます。 fluentd
または などのログ収集デーモンがlogstash
各ノードで実行され、コンテナのログを収集します。
ここで特に説明する必要があるのは、DaemonSet
を実行する際のスケジューリングの問題ですPod
。通常、Pod
どのノードで実行するかはKubernetes
スケジューラの戦略によって決まりますが、実際にはDaemonSet
コントローラが作成するノードはPod
あらかじめ決まっています。(Pod
で指定)作成時間.spec.nodeName
)、つまり:
DaemonSet
ノードのフィールドは関係ありませんunshedulable
。これについては、後のスケジューリングの章で説明します。DaemonSet
Pod
スケジューラが起動していなくても作成できますが、これは非常に重要です。
以下では、各ノードに 1 つをデプロイする例を直接使用して説明しますNginx Pod
: (nginx-ds.yaml)
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: nginx-ds
labels:
k8s-app: nginx
spec:
selector:
matchLabels:
k8s-app: nginx
template:
metadata:
labels:
k8s-app: nginx
spec:
containers:
- image: nginx:1.7.9
name: nginx
ports:
- name: http
containerPort: 80
次に、それを直接作成します。
$ kubectl create -f nginx-ds.yaml
Pod
次に、それが各ノードに分散されているかどうかを観察できます。
$ kubectl get nodes
$ kubectl get pods -o wide
StatefulSet の使用
この種のコントローラーについて学ぶ前にStatefulSet
、「ステートフル サービスとは何なのか」という概念を理解する必要があります。ステートレスサービスとは何ですか?
-
WordPress
ステートレス サービス (ステートレス サービス): このサービスの実行中のインスタンスは、永続化する必要があるデータをローカルに保存しません。また、同じリクエストに応答する複数のインスタンスの結果は、前に説明したインスタンスのように完全に一貫しています。複数のインスタンスを同時に起動できますが、どのインスタンスから得られる結果も同じですよね。永続化する必要があるデータのみがデータベースに保存されているため、このアプリケーションはステートレス サービスであるMySQL
と言えますが、データをローカルに永続化する必要があるため、データベースはステートレス サービスではありません。WordPress
MySQL
-
ステートフル サービス (ステートフル サービス): 上記の概念とは反対です。このサービスの実行中のインスタンスは、永続的なデータをローカルに保存する必要があります。たとえば、上記のデータベースは、現在ノード A で実行している場合、そのデータは次の場所に保存されます
MySQL
。ノード A では、この時点でサービスをノード B に移行すると、以前のデータはなくなります。これは、対応するデータ ディレクトリにデータを復元する必要があり、現時点ではデータが存在しないためです。
これで、誰もがステートフルとステートレスについてある程度理解できるようになりました。たとえば、一般的な WEB アプリケーションはユーザーsession
のログイン ステータスを維持します。session
それをノードに永続化すると、アプリケーションはステートフル サービスになります。はい、私は今ログインしていて、あなたはログインしているからです。データをノード A に永続化しました。次回ログインすると、リクエストはノード B にルーティングされる可能性がありますが、session
ノード B には現在のデータがまったくないため、ログインしていないと見なされ session
一般的に、水平拡張のために、この種の WEB アプリケーションをステートレスなサービスに変更しますが、それをどのように変更するか? session
クライアントのリクエストによっては、データを社内などの公共の場所に保存するだけでredis
十分ですか。ユーザーのステータスを保持するためにAPI
データを使用するのではなく、代わりに使用することも可能です。session
token
ステートレス サービスは、以前のサービスまたはステートフル サービスを使用することで適切に制御できます。ステートフル サービスについては、考慮する必要がある詳細がさらに多くあります。コンテナ化されたアプリケーションで最も困難なタスクの 1 つは、ステートフル分散コンポーネントのデプロイメントを設計することですDeployment
。RC
ステートレス コンポーネントには、事前定義された起動シーケンス、クラスタリング要件、ポイントツーポイント TCP 接続、一意のネットワーク識別子、正常な起動および終了要件などが含まれていない可能性があるため、簡単にコンテナ化できます。データベース、ビッグ データ分析システム、分散キー/バリュー ストア、メッセージ ブローカーなどのシステムは、複雑な分散アーキテクチャを持ち、上記の機能を使用する場合があります。この目的を達成するために、このような複雑な要件をサポートするリソースKubernetes
が導入されていますStatefulSet
。
StatefulSet
に似ていますが、起動シーケンスを処理し、それぞれの状態を保持するための一意の識別子を設定することReplicaSet
ができます。また、次の機能があります。Pod
Pod
- 安定した一意のネットワーク識別子
- 安定した永続的なストレージ
- 秩序ある適切なデプロイメントとスケーリング
- 秩序ある適切な削除と終了
- 秩序ある自動ローリング更新
ステートフルセットを作成する
StatefulSet
次に、オブジェクトの使用方法を示します。開始する前に、2 つの 1G ストレージ ボリューム (PV) を準備します。次のコースでは、PV と PVC の使用方法についても詳しく説明します。これについては掘り下げません。ここ: (pv001.yaml)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
release: stable
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
hostPath:
path: /tmp/data
もう 1 つは、名前を pv002 に変更して、以下を作成するだけです。
$ kubectl create -f pv001.yaml && kubectl create -f pv002.yaml
persistentvolume "pv001" created
persistentvolume "pv002" created
$ kubectl get pv
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO Recycle Available 12s
pv002 1Gi RWO Recycle Available 11s
2 つの PV オブジェクトが正常に作成され、ステータスが「Available」になっていることがわかります。
次に、それを使用してStatefulSet
Nginx ポッドを作成します。このタイプのリソースの場合、通常、ヘッドレス サービスとして設定されるHeadless Service
サービスのタイプを作成してサービスを公開します: (statefulset-demo.yaml)clusterIP
None
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
role: stateful
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 が自動的に宣言されます。
次に、ここで 2 つのターミナル ウィンドウを開きます。最初のターミナルで、kubectl get を使用して、StatefulSet の Pod の作成を表示します。
$ 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
ポッドの順序インデックスを確認する
N 個のレプリカを持つ StatefulSet の場合、ポッドはデプロイ時に {0…N-1} の順序で作成されます。最初のターミナルでは、次の情報が表示されます。
$ kubectl get pods -w -l role=stateful
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 19s
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 18s
web-0 ポッドが実行状態および準備完了状態になるまで、web-1 ポッドは開始されないことに注意してください。
StatefulSet の概念で述べたように、StatefulSet 内のポッドは安定した一意の ID を持ちます。このフラグは、StatefulSet コントローラーによって各 Pod に割り当てられた一意の順次インデックスに基づいています。ポッド名の形式は です<statefulset name>-<ordinal index>
。Web StatefulSet には 2 つのレプリカがあるため、web-0 と web-1 の 2 つのポッドを作成します。
上記のコマンドは、それぞれ NGINX Web サーバーを実行する 2 つのポッドを作成します。nginx サービスと Web StatefulSet を取得して、それらが正常に作成されたことを確認します。
$ kubectl get service nginx
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx None <none> 80/TCP 12s
$ kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 1 20s
安定したネットワーク ID を使用する
各ポッドには、シーケンシャルインデックスに基づいた安定したホスト名があります。kubectl exec を使用して各 Pod でホスト名を実行します。
$ for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1
次に、kubectl run を使用して、nslookup コマンドを提供するコンテナーを実行します。Pod のホスト名に対して nslookup を実行すると、クラスター内の DNS アドレスを確認できます。
$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
nslookup web-0.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.6
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.6
ヘッドレス サービスの CNAME は SRV レコードを指します (各ポッドを実行中および準備完了状態でログに記録します)。SRV レコードは、ポッドの IP アドレスを含むレコード エントリを指します。
次に、StatefulSet の下の Pod を削除することを見てみましょう。
ターミナルで StatefulSet ポッドを表示します。
$ kubectl get pod -w -l role=stateful
別のターミナルで kubectl delete を使用して、StatefulSet 内のすべての Pod を削除します。
$ kubectl delete pod -l role=stateful
pod "web-0" deleted
pod "web-1" deleted
StatefulSet がそれらを再起動し、両方の Pod が実行中および準備完了になるまで待ちます。
$ kubectl get pod -w -l app=nginx
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 34s
次に、kubectl exec を使用し、kubectl run を再度実行して、ポッドのホスト名とクラスター内の DNS エントリを表示します。
$ for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1
$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
nslookup web-0.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.7
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.8
ポッドの序数、ホスト名、SRV エントリ、およびレコード名は変更されていないことがわかりますが、ポッドに関連付けられた IP アドレスは変更されている可能性があります。このため、他のアプリケーションからの接続には StatefulSet 内の Pod の IP アドレスを使用しないことが重要です。一般に、SRV レコード web-0.nginx、web-1.nginx を介して直接接続できます。これらは安定しているため、ポッドのステータスが実行中および準備完了に変わると、アプリケーションはそれらのアドレスを検出できます。
同様に、PV と PVC の最終的なバインディング ステータスを確認できます。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO Recycle Bound default/www-web-0 1h
pv002 1Gi RWO Recycle Bound default/www-web-1 1h
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pv001 1Gi RWO 22m
www-web-1 Bound pv002 1Gi RWO 22m
ストレージボリュームの使用方法については後で説明するため、混乱を避けるためにここでは説明しません。
もちろん、StatefulSet には他の機能もあります。実際のプロジェクトでは、自分で完全に保持できない限り、StatefulSet を介して直接ステートフル サービスをデプロイするために戻ることはまだほとんどありません。一部の特定のサービスについては、より高度な Operator を使用してデプロイする場合があります。 etcd-operator、prometheus-operator など。これらのアプリケーションは、単に StatefulSet を使用して Pod をデプロイするのではなく、ステートフル サービスを適切に管理できます。これは、ステートフル アプリケーションにとって最も重要なことはデータ リカバリ、フェイルオーバーなどであるためです。