vSphere with Kubernetes のスーパーバイザー クラスタで、
Pod をノードに分散して起動する「アンチ アフィニティ」を試してみます。
vSphere で VM を起動する場合でも、複数台の VM を ESXi に分散して配置しようとするケースが多くあります。
たとえば「Web サーバ VM の 1号機と2号機は別の ESXi で起動する」といったものです。
vSphere Pod の実体は VM なのですが、特殊な VM なので、
ユーザが手動で vMotion できなかったり、DRS + アンチ アフィニティルールが利用できなかったりします。
そこで、Kubernetes の持つ affinity の仕組みを利用できそうか様子を見てみます。
今回の環境。
vCenter Server 7.0b / ESXi 7.0 を利用しています。
スーパーバイザー クラスタ(wcp-cluster-41)には、3台のワーカー ノードとなる ESXi があります。
kubectl でも、スーパーバイザー クラスタに ESXi が 3台あることが確認できます。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
42113326156c17e10192d03d69cfc933 Ready master 25d v1.17.4-2+a00aae1e6a4a69
4211b5cba366a26db4debeca422d75ca Ready master 25d v1.17.4-2+a00aae1e6a4a69
4211b7998322f27779a8a0af22dbf35d Ready master 25d v1.17.4-2+a00aae1e6a4a69
lab-wcp-esxi-41.go-lab.jp Ready agent 25d v1.17.4-sph-c4c19c8
lab-wcp-esxi-42.go-lab.jp Ready agent 25d v1.17.4-sph-c4c19c8
lab-wcp-esxi-43.go-lab.jp Ready agent 25d v1.17.4-sph-c4c19c8
ホスト名やソフトウェア バージョンは若干異なりますが、
このラボは下記のように環境構築しています。
vSphere with Kubernetes ラボ環境構築。(まとめ)
vSphere Pod の起動。
まず、Kubernetes の Deployment リソースで、vSphere Pod を2つ起動します。
Deployment の定義は下記のようにしています。
---
kind: Service
apiVersion: v1
metadata:
name: web-svc
spec:
type: LoadBalancer
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: demo-httpd
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: demo-httpd
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: demo-httpd
template:
metadata:
labels:
app: demo-httpd
spec:
containers:
- name: httpd
image: gowatana/centos7:httpd
ports:
- containerPort: 80
protocol: TCP
Pod を作成するのは、スーパーバイザー クラスタの名前空間「lab-ns-01」です。
$ kubectl config current-context
lab-ns-01
$ kubectl config get-contexts lab-ns-01
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* lab-ns-01 192.168.70.97 wcp:192.168.70.97:administrator@vsphere.local lab-ns-01
Deployment を作成します。
$ kubectl apply -f httpd.yml
service/web-svc created
deployment.apps/demo-httpd created
特に Pod 配置にかかわる定義はなく、1つのホストに Pod が2つとも起動しています。
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-httpd-6b58f9f454-kqld5 1/1 Running 0 70s 10.244.0.227 lab-wcp-esxi-41.go-lab.jp <none> <none>
demo-httpd-6b58f9f454-t8bwj 1/1 Running 0 70s 10.244.0.226 lab-wcp-esxi-41.go-lab.jp <none> <none>
vSphere Client でも、vSphere Pod として、
Pod が 2つとも「lab-wcp-esxi-41.go-lab.jp」で起動されたことが確認できます。
1つめの vSphere Pod です。
2つめの vSphere Pod です。
アンチ アフィニティへの定義変更。
アンチ アフィニティの方法については、下記の Kubernetes ドキュメントが参考になります。
アフィニティとアンチアフィニティ(日本語)
https://kubernetes.io/ja/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
podAntiAffinity を定義した、下記のような YAML を用意しました。
httpd_anti-affinity.yml · GitHub
Deployment を作成した YAML との差分です。
今回は、わかりやすく動きを見たいので、必須要件となるように
「requiredDuringSchedulingIgnoredDuringExecution」を指定しています。
$ diff httpd.yml httpd_anti-affinity.yml
37a38,47
> affinity:
> podAntiAffinity:
> requiredDuringSchedulingIgnoredDuringExecution:
> - labelSelector:
> matchExpressions:
> - key: app
> operator: In
> values:
> - demo-httpd
> topologyKey: "kubernetes.io/hostname"
それでは、定義を変更(YAML を適用)します。
※今回は既存の Deployment の定義を変更していますが、新規作成でもアンチ アフィニティ配置になります。
$ kubectl apply -f httpd_anti-affinity.yml
service/web-svc unchanged
deployment.apps/demo-httpd configured
kubectl get pods で様子を見ていると、
Kubernetes による Pod の追加 / 削除が実施されます。
既存の Pod(~-c26jc、~-sjxpp)は停止され、あらたに Pod(~-rdz6l、~-wb774)が起動されています。
特に、スーパーバイザー クラスタだからといって、vSphere DRS で vMotion されたりはしていません。
ちなみに内部的には、ReplicaSet リソースが作成されて Pod が追加されています。
$ kubectl get pods --watch
NAME READY STATUS RESTARTS AGE
demo-httpd-68979c6d58-rdz6l 0/1 Pending 0 9s
demo-httpd-6b58f9f454-c26jc 1/1 Running 0 70m
demo-httpd-6b58f9f454-sjxpp 1/1 Running 0 71m
demo-httpd-68979c6d58-rdz6l 1/1 Running 0 9s
demo-httpd-6b58f9f454-c26jc 1/1 Terminating 0 70m
demo-httpd-68979c6d58-wb774 0/1 Pending 0 0s
demo-httpd-68979c6d58-wb774 0/1 Pending 0 0s
demo-httpd-68979c6d58-wb774 0/1 Pending 0 1s
demo-httpd-6b58f9f454-c26jc 1/1 Terminating 0 70m
demo-httpd-68979c6d58-wb774 0/1 Pending 0 3s
demo-httpd-68979c6d58-wb774 0/1 Pending 0 4s
demo-httpd-6b58f9f454-c26jc 1/1 Terminating 0 70m
demo-httpd-68979c6d58-wb774 1/1 Running 0 9s
demo-httpd-6b58f9f454-sjxpp 1/1 Terminating 0 71m
demo-httpd-6b58f9f454-sjxpp 1/1 Terminating 0 71m
demo-httpd-6b58f9f454-sjxpp 1/1 Terminating 0 71m
別のワーカー ノードで、Pod が起動された状態になりました。
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-httpd-68979c6d58-bvlgx 1/1 Running 0 119s 10.244.0.228 lab-wcp-esxi-43.go-lab.jp <none> <none>
demo-httpd-68979c6d58-dhrpc 1/1 Running 0 106s 10.244.0.229 lab-wcp-esxi-42.go-lab.jp <none> <none>
vSphere Client でも、vSphere Pod が順次追加 → 削除される様子が見られます。
最終的に vSphere Pod は 2つとなり、別の ESXi で起動されたことが確認できます。
1つめの vSphere Pod です。
もうひとつの vSphere Pod も、別の ESXi で起動されています。
vSphere Pod 起動時の配置決定では DRS が利用されています。
しかし、vCenter 7.0b 時点では、vSphere Pod の配置制御を工夫したい場合には
アフィニティ ルールや DRS ではなく、Kubernetes 側の仕組みを利用するとよさそうです。
以上、vSphere Pod をアンチ アフィニティ配置してみる話でした。