深入浅出Kubernetes:StatefulSet概念理解
25073 ワード
文書ディレクトリ深入浅出Kubernetes:StatefulSet概念理解 背景知識及び関連概念 二StatefulSetの二種類の構造 2.1トポロジー 2.2ストレージ構造 深入浅出Kubernetes:StatefulSet概念理解
一背景知識及び関連概念
StatefulSetのデザインは実はとても分かりやすいです.実際の世界での応用状態を2つの状況に抽象化しています.
トポロジーの状態.このことは、適用される複数のインスタンス間が完全に対等な関係ではないことを意味する.これらのアプリケーションインスタンスは、例えば、アプリケーションのプライマリノードAがノードBから先に起動されるなど、いくつかの順序で起動しなければならない.AとBの2つのPodを削除すると、再び作成されるときもこの順序に厳格に従わなければなりません.また、新しく作成されたPodは、元のPodのネットワークIDと同じように、元の訪問者が同じ方法でこの新しいPodにアクセスできるようにしなければならない.
ストレージステータス.この場合、アプリケーションの複数のインスタンスがそれぞれ異なるストレージデータをバインドしていることを意味する.これらの適用例では、Pod Aが最初に読み取ったデータと、10分ぶりに再び読み取ったデータは、その間にPod Aが再作成されても同じであるべきである.この場合の最も典型的な例は、1つのデータベース・アプリケーションの複数のストレージ・インスタンスです.
StatefulSetの核心機能は、何らかの方法でこれらの状態を記録し、Podが再作成されたときに、新しいPodのためにこれらの状態を回復することができることです.
このサービスはどのようにしてアクセスされたのでしょうか?
第1の方式は、サービスのVIP(Virtual IP、すなわち仮想IP)方式である.たとえば、172.2.0.25.3というサービスのIPアドレスにアクセスすると、172.0.25.3はVIPであり、サービスがエージェントするPodにリクエストを転送します.
2つ目の方法は、サービスのDNS方式です.たとえば、「my-svc.my-namespace.svc.cluster.local」というDNSレコードにアクセスすれば、my-svcというServiceエージェントのあるPodにアクセスできます.
二StatefulSetの二種類の構造
2.1トポロジー
次の例を見てみましょう.
これらのPodの作成も,厳密に番号順に行われている.例えば、web-server-gysl-0がRunning状態に入り、かつ細分化状態(Conditions)がReadyになるまで、web-server-gysl-1はPending状態になる.
次のコマンドを使用してテストします.
最近のバージョンのbusyboxに穴があったので、DNSテストツールを自分で作成しました.Dockerfileは以下の通りです.
Masterノードに戻って見てください.
クラスタ内でドメイン名web-server-gysl-0をそれぞれpingするとnginx.default.svc.cluster.localとweb-server-gysl-1.nginx.default.svc.cluster.localの時、正常に対応するPod IPを返して、pingドメイン名nginx.default.svc.cluster.localの場合,2つのPod IPのうちの1つをランダムに返す.上記の内容を完全に証明した.
上記の操作の過程で、私はランダムにこれらのPodの中の1つまたはいくつかを削除して、後で再び見に来た時、新しく作成したPodは依然として前の番号に従って編成されました.
また、StatefulSetの1つのPodが存在するクラスタ内のノードをオフラインにし、再びPodの状況を確認し、システムは他のノードで元のPodの名前で迅速に新しいPodを作成しました.番号はいずれも0から加算され,StatefulSetの各Podインスタンスに1つずつ対応し,決して繰り返されない.
2.2ストレージ構造
試験環境資源が限られているため,rook−cephを用いて実験を行う予定であったが,NFSを用いて実験を行うことはできなかった.CephのPV作成に関するyamlは以下の通り.
NFS実験関連yaml:
次のコマンドを使用して、関連するPodに検証内容を書き込みます.
実験結果を観察する:
実験結果から,PodとPV,PVCの対応関係を見ることができ,前述のyamlと組み合わせて,我々は容易に発見できる: Podは対応するPVストレージに1つずつ対応しており、Podを作成すると同時に、StatefulSetは対応するルールに従って対応するPVCを作成し、PVCは条件に合ったPVを選択してバインドしている.Podが削除された後もデータはPVに保存され、削除されたPodが再び作成されると、そのPodは直ちに元のPodとバインドされ、元の対応関係を維持する. クラスタ内部では、pod名に対応するサービス名を付けて指定されたPodおよびそのバインドされたPVにアクセスすることができる.サービス名でStatefulSetにアクセスする場合、サービス名の機能はVIPの機能と似ています.
一背景知識及び関連概念
StatefulSetのデザインは実はとても分かりやすいです.実際の世界での応用状態を2つの状況に抽象化しています.
トポロジーの状態.このことは、適用される複数のインスタンス間が完全に対等な関係ではないことを意味する.これらのアプリケーションインスタンスは、例えば、アプリケーションのプライマリノードAがノードBから先に起動されるなど、いくつかの順序で起動しなければならない.AとBの2つのPodを削除すると、再び作成されるときもこの順序に厳格に従わなければなりません.また、新しく作成されたPodは、元のPodのネットワークIDと同じように、元の訪問者が同じ方法でこの新しいPodにアクセスできるようにしなければならない.
ストレージステータス.この場合、アプリケーションの複数のインスタンスがそれぞれ異なるストレージデータをバインドしていることを意味する.これらの適用例では、Pod Aが最初に読み取ったデータと、10分ぶりに再び読み取ったデータは、その間にPod Aが再作成されても同じであるべきである.この場合の最も典型的な例は、1つのデータベース・アプリケーションの複数のストレージ・インスタンスです.
StatefulSetの核心機能は、何らかの方法でこれらの状態を記録し、Podが再作成されたときに、新しいPodのためにこれらの状態を回復することができることです.
このサービスはどのようにしてアクセスされたのでしょうか?
第1の方式は、サービスのVIP(Virtual IP、すなわち仮想IP)方式である.たとえば、172.2.0.25.3というサービスのIPアドレスにアクセスすると、172.0.25.3はVIPであり、サービスがエージェントするPodにリクエストを転送します.
2つ目の方法は、サービスのDNS方式です.たとえば、「my-svc.my-namespace.svc.cluster.local」というDNSレコードにアクセスすれば、my-svcというServiceエージェントのあるPodにアクセスできます.
二StatefulSetの二種類の構造
2.1トポロジー
次の例を見てみましょう.
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- port: 80
name: web
clusterIP: None
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-server-gysl
labels:
app: nginx
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
restartPolicy: Always
containers:
- name: web-server
image: nginx:1.16.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web-port
これらのPodの作成も,厳密に番号順に行われている.例えば、web-server-gysl-0がRunning状態に入り、かつ細分化状態(Conditions)がReadyになるまで、web-server-gysl-1はPending状態になる.
次のコマンドを使用してテストします.
kubectl run -i --tty --image toolkit:v1.0.0821 dns-test --restart=Never --rm /bin/bash
[root@dns-test /]# nslookup web-server-gysl-0.nginx
Server: 10.0.0.2
Address: 10.0.0.2#53
Name: web-server-gysl-0.nginx.default.svc.cluster.local
Address: 172.20.25.3
[root@dns-test /]# nslookup web-server-gysl-1.nginx
Server: 10.0.0.2
Address: 10.0.0.2#53
Name: web-server-gysl-1.nginx.default.svc.cluster.local
Address: 172.20.72.7
[root@dns-test /]# nslookup nginx
Server: 10.0.0.2
Address: 10.0.0.2#53
Name: nginx.default.svc.cluster.local
Address: 172.20.72.7
Name: nginx.default.svc.cluster.local
Address: 172.20.25.3
最近のバージョンのbusyboxに穴があったので、DNSテストツールを自分で作成しました.Dockerfileは以下の通りです.
FROM centos:7.6.1810
RUN yum -y install bind-utils
CMD ["/bin/bash","-c","while true;do sleep 60000;done"]
Masterノードに戻って見てください.
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-server-gysl-0 1/1 Running 0 43m 172.20.25.3 172.31.2.12 <none> <none>
web-server-gysl-1 1/1 Running 0 42m 172.20.72.7 172.31.2.11 <none> <none>
$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx ClusterIP None <none> 80/TCP 43m app=nginx
クラスタ内でドメイン名web-server-gysl-0をそれぞれpingするとnginx.default.svc.cluster.localとweb-server-gysl-1.nginx.default.svc.cluster.localの時、正常に対応するPod IPを返して、pingドメイン名nginx.default.svc.cluster.localの場合,2つのPod IPのうちの1つをランダムに返す.上記の内容を完全に証明した.
上記の操作の過程で、私はランダムにこれらのPodの中の1つまたはいくつかを削除して、後で再び見に来た時、新しく作成したPodは依然として前の番号に従って編成されました.
また、StatefulSetの1つのPodが存在するクラスタ内のノードをオフラインにし、再びPodの状況を確認し、システムは他のノードで元のPodの名前で迅速に新しいPodを作成しました.番号はいずれも0から加算され,StatefulSetの各Podインスタンスに1つずつ対応し,決して繰り返されない.
2.2ストレージ構造
試験環境資源が限られているため,rook−cephを用いて実験を行う予定であったが,NFSを用いて実験を行うことはできなかった.CephのPV作成に関するyamlは以下の通り.
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-gysl
labels:
type: local
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
rbd:
monitors:
- '172.31.2.11:6789'
- '172.31.2.12:6789'
pool: data
image: data
fsType: xfs
readOnly: true
user: admin
keyring: /etc/ceph/keyrin
NFS実験関連yaml:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-gysl-0
labels:
environment: test
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /data-0
server: 172.31.2.10
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-gysl-1
labels:
environment: test
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /data-1
server: 172.31.2.10
---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: nfs
provisioner: fuseim.pri/ifs
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulset-pvc-gysl
spec:
replicas: 2
serviceName: "gysl-web"
selector:
matchLabels:
app: pod-gysl
template:
metadata:
name: web-pod
labels:
app: pod-gysl
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- name: web-port
containerPort: 80
volumeMounts:
- name: www-vct
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www-vct
annotations:
volume.beta.kubernetes.io/storage-class: "nfs"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs
---
apiVersion: v1
kind: Service
metadata:
name: gysl-web
spec:
type: NodePort
selector:
app: pod-gysl
ports:
- name: web-svc
protocol: TCP
nodePort: 31688
port: 8080
targetPort: 80
次のコマンドを使用して、関連するPodに検証内容を書き込みます.
for node in 0 1;do kubectl exec statefulset-pvc-gysl-$node -- sh -c "echo \Node: ${node}\>/usr/share/nginx/html/index.html"
;done
実験結果を観察する:
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
statefulset-pvc-gysl-0 1/1 Running 0 51m 172.20.85.2 172.31.2.11 <none> <none>
statefulset-pvc-gysl-1 1/1 Running 0 32m 172.20.65.4 172.31.2.12 <none> <none>
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-vct-statefulset-pvc-gysl-0 Bound pv-nfs-gysl-0 1Gi RWO nfs 51m
www-vct-statefulset-pvc-gysl-1 Bound pv-nfs-gysl-1 1Gi RWO nfs 49m
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-gysl-0 1Gi RWO Recycle Bound default/www-vct-statefulset-pvc-gysl-0 nfs 51m
pv-nfs-gysl-1 1Gi RWO Recycle Bound default/www-vct-statefulset-pvc-gysl-1 nfs 51m
$ cat /data-0/index.html
<h1>Node: 0</h1>
$ cat /data-1/index.html
<h1>Node: 1</h1>
$ curl 172.31.2.11:31688
<h1>Node: 0</h1>
$ curl 172.31.2.11:31688
<h1>Node: 1</h1>
$ curl 172.31.2.12:31688
<h1>Node: 1</h1>
$ curl 172.31.2.12:31688
<h1>Node: 0</h1>
kubectl run -i --tty --image toolkit:v1.0.0821 test --restart=Never --rm /bin/bash
[root@test /]# curl statefulset-pvc-gysl-0.gysl-web
Node: 0
[root@test /]# curl statefulset-pvc-gysl-0.gysl-web
Node: 0
[root@test /]# curl statefulset-pvc-gysl-1.gysl-web
Node: 1
[root@test /]# curl statefulset-pvc-gysl-1.gysl-web
Node: 1
[root@test /]# curl gysl-web:8080
Node: 1
[root@test /]# curl gysl-web:8080
Node: 1
[root@test /]# curl gysl-web:8080
Node: 0
[root@test /]# curl gysl-web:8080
Node: 0
実験結果から,PodとPV,PVCの対応関係を見ることができ,前述のyamlと組み合わせて,我々は容易に発見できる: