StatefulSet の Pod を各ノードに順番に並べる方法
StatefulSet の Pod を各ノードに順番に並べたいユースケースに直面しました.
具体的にやりたいことは以下のようなことです.
- Pod 0 → ノード1番目
- Pod 1 → ノード2番目
- Pod 2 → ノード3番目
今回は上記のようなスケジューリングを Kubernetes の Affinity 定義を使って実現してみます.
Node Affinity と Pod Anti Affinity を用いたスケジューリング
以下のような YAML で実現できます.
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: example-app
name: example-app
namespace: kawanuma
spec:
replicas: 3
selector:
matchLabels:
app: example-app
template:
metadata:
labels:
app: example-app
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- example-app
topologyKey: "kubernetes.io/hostname"
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker1.example.com
- weight: 50
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker2.example.com
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker3.example.com
containers:
- image: fabxc/instrumented_app
imagePullPolicy: Always
name: example-app
ports:
- containerPort: 8080
name: web
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
securityContext: {}
terminationGracePeriodSeconds: 30
解説していきます.
まずは Pod Anti Affinity です.
こちらを指定することで『StatefulSet の各 Pod を同じノードに重複して配置しない』ということが実現できます. 簡単な言葉に言い換えると、『各ノードにばらけて配置する』ということになります.
今回は kubernetes.io/hostname をトポロジー(グルーピング)のキーとして、app=example-app が同一の Pod が重複して配置されないように指定しました.
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- example-app
topologyKey: "kubernetes.io/hostname"
次に Node Affinity です.
こちらを指定することで『ノードに優先度を付けて配置する』ということが実現できます.
今回は kubernetes.io/hostname をキーに、worker0, worker1, worker2 の順番で優先度を高くしてあります(なお、スケジューリングはこの値のみで決まるわけではないので、出来るだけ weight の値に差がでるように値を設定しています).
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker1.example.com
- weight: 50
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker2.example.com
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker3.example.com
以上です.