LoginSignup
2
2

More than 1 year has passed since last update.

OpenShiftにおけるPodの分散配置

Last updated at Posted at 2021-08-29

はじめに

OpenShiftやKubernetesではスケジューラーがどのノードにPodを配置するか決定します。複数ノードに分散配置されることが望ましいですが、単純にデプロイした場合、すべてのPodが1ノードに配置されることもあります。この記事では「トポロジー分散制約」と「Deschedulearを使用したPodのエビクト」を試します。

環境やアプリケーションについては以下の記事を参照ください。

■ OpenShift環境

■ Spring Bootアプリケーション

1. トポロジー分散制約

ラベル「topology.kubernetes.io/zone」が異なるノードにPodが分散してスケジュールされるように、マニフェストに「topologySpreadConstraints」を追加してデプロイしました。workerノード0~2に1Podずつスケジュールされたことを確認できます。

oc get nodes
NAME       STATUS   ROLES    AGE   VERSION
master-0   Ready    master   14d   v1.21.1+051ac4f
master-1   Ready    master   14d   v1.21.1+051ac4f
master-2   Ready    master   14d   v1.21.1+051ac4f
worker-0   Ready    worker   14d   v1.21.1+051ac4f
worker-1   Ready    worker   14d   v1.21.1+051ac4f
worker-2   Ready    worker   14d   v1.21.1+051ac4f

oc label node worker-0 topology.kubernetes.io/zone=tok0
oc label node worker-1 topology.kubernetes.io/zone=tok1
oc label node worker-2 topology.kubernetes.io/zone=tok2

oc apply -f spring-liberty.yaml

oc get pod -o wide
### 標準出力↓
NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
spring-liberty-85469f6ffd-7j6gq   1/1     Running   0          24s   10.128.3.165   worker-0   <none>           <none>
spring-liberty-85469f6ffd-c6sms   1/1     Running   0          24s   10.129.2.60    worker-1   <none>           <none>
spring-liberty-85469f6ffd-fl67k   1/1     Running   0          24s   10.131.0.34    worker-2   <none>           <none>
spring-liberty.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-liberty
  labels:
    app: spring-liberty
spec:
  replicas: 3
  selector:
    matchLabels:
      app: spring-liberty
  template:
    metadata:
      labels:
        app: spring-liberty
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: ScheduleAnyway
        labelSelector:
          matchLabels:
            app: spring-liberty
      containers:
        - name: spring-liberty
          image: image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty
          ports:
            - containerPort: 9080
          readinessProbe:
            httpGet:
              path: /healthz
              port: 9080

また、レプリカ数を3~6に変更したとき、各ノードのPod数は下表のようになりました。
maxSkewで指定したPod数の最大差『1』でスケジュールされています。

レプリカ数 ノード
worker-0
ノード
worker-1
ノード
worker-2
3 1 1 1
4 1 2 1
5 1 2 2
6 2 2 2
レプリカ数変更方法
oc scale --replicas=<レプリカ数> deploy/spring-liberty 

2. Kube DeschedulerオペレーターによるPodのエビクト

「Kube Descheduler」オペレーターにより、ポリシーに違反するPodが削除(エビクト)されることを確認します。削除後、Podがどのノードに作成されるかはスケジューラーが決定します。

2.1. ノード停止後の挙動確認

ノード「worker-2」停止後、同ノードのスタータスは『NotReady』になりました。また、worker-2のPod「spring-liberty-85469f6ffd-fl67k」は終了中となり、worker-1にPod「spring-liberty-85469f6ffd-fl67k」が作成されました。マニフェストに記載したレプリカ数『3』を維持しようとしていることが分かります。

oc get nodes
### 標準出力↓
NAME       STATUS     ROLES    AGE   VERSION
master-0   Ready      master   1d   v1.21.1+051ac4f
master-1   Ready      master   1d   v1.21.1+051ac4f
master-2   Ready      master   1d   v1.21.1+051ac4f
worker-0   Ready      worker   1d   v1.21.1+051ac4f
worker-1   Ready      worker   1d   v1.21.1+051ac4f
worker-2   NotReady   worker   1d   v1.21.1+051ac4f

oc get pod -o wide
### 標準出力↓
NAME                              READY   STATUS        RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATES
spring-liberty-85469f6ffd-4d9d9   1/1     Running       0          116s    10.129.2.64    worker-1   <none>           <none>
spring-liberty-85469f6ffd-7j6gq   1/1     Running       0          8m36s   10.128.3.165   worker-0   <none>           <none>
spring-liberty-85469f6ffd-c6sms   1/1     Running       0          8m36s   10.129.2.60    worker-1   <none>           <none>
spring-liberty-85469f6ffd-fl67k   1/1     Terminating   0          8m36s   10.131.0.34    worker-2   <none>           <none>

2.2. ノード起動後の挙動確認

ノード「worker-2」起動後、同ノードのスタータスは『Ready』になりました。worker-2のPod「spring-liberty-85469f6ffd-fl67k」の終了処理は完了しましたが、Podが再作成されることはありません。

oc get nodes
### 標準出力↓
NAME       STATUS   ROLES    AGE   VERSION
master-0   Ready    master   1d   v1.21.1+051ac4f
master-1   Ready    master   1d   v1.21.1+051ac4f
master-2   Ready    master   1d   v1.21.1+051ac4f
worker-0   Ready    worker   1d   v1.21.1+051ac4f
worker-1   Ready    worker   1d   v1.21.1+051ac4f
worker-2   Ready    worker   1d   v1.21.1+051ac4f

oc get pod -o wide
### 標準出力↓
NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
spring-liberty-85469f6ffd-4d9d9   1/1     Running   0          7m40s   10.129.2.64    worker-1   <none>           <none>
spring-liberty-85469f6ffd-7j6gq   1/1     Running   0          14m     10.128.3.165   worker-0   <none>           <none>
spring-liberty-85469f6ffd-c6sms   1/1     Running   0          14m     10.129.2.60    worker-1   <none>           <none>

2.3. KubeDeschedulerマニフェストの適用

「Kube Descheduler」オペレーターをインストールした後、「KubeDescheduler」マニフェストを適用すると、worker-1に2つ起動していたPodのうち1つが終了し、worker-2にPod「spring-liberty-85469f6ffd-pm9jw」が作成されました。結果的に各ノードに1つのPodが存在する状態になっています。

oc apply -f descheduler.yaml

oc get pod -o wide
### 標準出力↓
spring-liberty-85469f6ffd-4d9d9   1/1     Running   0          10m     10.129.2.64    worker-1   <none>           <none>
spring-liberty-85469f6ffd-7j6gq   1/1     Running   0          16m     10.128.3.165   worker-0   <none>           <none>
spring-liberty-85469f6ffd-pm9jw   1/1     Running   0          2m14s   10.131.0.35    worker-2   <none>           <none>

「KubeDescheduler」マニフェストでは、同じノードにPodが重複する場合は削除されるように、TopologyAndDuplicatesプロファイルを有効にしています。

desucheduler.yaml
apiVersion: operator.openshift.io/v1
kind: KubeDescheduler
metadata:
  name: cluster
  namespace: openshift-kube-descheduler-operator
spec:
  deschedulingIntervalSeconds: 0
  logLevel: Normal
  managementState: Managed
  operatorLogLevel: Normal
  profiles:
  - TopologyAndDuplicates

2.4. OpenShift Kube Deschedulerについて

OpenShiftの「Kube Descheduler」オペレーターは、GitHubに公開されている「Descheduler for Kubernetes」のアップストリーム版です。

The Descheduler is an upstream Kubernetes subproject owned by SIG-Scheduling. 21

「Descheduler for Kubernetes」は、「DeschedulerPolicy」をConfigMapとして作成し、同設定を元にdeschedulerコンテナを実行することでPodの削除を行う仕組みのようです。一方、OpenShiftの「Kube Descheduler」オペレーターでは、「KubeDescheduler」マニフェスト適用時に「DeschedulerPolicy」が作成されていました。

oc describe cm cluster -n openshift-kube-descheduler-operator
### 標準出力↓
Name:         cluster
Namespace:    openshift-kube-descheduler-operator
Labels:       <none>
Annotations:  <none>

Data
====
policy.yaml:
----
apiVersion: descheduler/v1alpha1
ignorePvcPods: true
kind: DeschedulerPolicy
strategies:
  RemoveDuplicates:
    enabled: true
    params:
      includeSoftConstraints: false
      namespaces:
        exclude:
        - kube-system
        - openshift-apiserver
        - openshift-apiserver-operator
…

前項の例でworker-1で実行されていたPod「spring-liberty-85469f6ffd-c6sms」を削除したのは、ネームスペース『openshift-kube-descheduler-operator』のPod「cluster-69ccfc675b-6bpm2」です。下記のログが出力されていました。

"Evicted pod" pod="spring-liberty/spring-liberty-85469f6ffd-c6sms" reason="RemoveDuplicatePods"

oc get pod -n openshift-kube-descheduler-operator
### 標準出力↓ 
NAME                                    READY   STATUS      RESTARTS   AGE
cluster-69ccfc675b-6bpm2                0/1     Completed   3          63s
descheduler-operator-858465f765-kxsgj   1/1     Running     0          10m

oc logs cluster-69ccfc675b-6bpm2 -n openshift-kube-descheduler-operator
### 標準出力↓
I0826 03:18:54.636239       1 dynamic_serving_content.go:111] Loaded a new cert/key pair for "serving-cert::/certs-dir/tls.crt::/certs-dir/tls.key"
I0826 03:18:59.430209       1 dynamic_serving_content.go:130] Starting serving-cert::/certs-dir/tls.crt::/certs-dir/tls.key
I0826 03:18:59.430283       1 tlsconfig.go:200] loaded serving cert ["serving-cert::/certs-dir/tls.crt::/certs-dir/tls.key"]: "metrics.openshift-kube-descheduler-operator.svc" [ser
ving] validServingFor=[metrics.openshift-kube-descheduler-operator.svc,metrics.openshift-kube-descheduler-operator.svc.cluster.local] issuer="openshift-service-serving-signer@16285
84568" (2021-08-26 01:53:35 +0000 UTC to 2023-08-26 01:53:36 +0000 UTC (now=2021-08-26 03:18:59.430262245 +0000 UTC))
I0826 03:18:59.430471       1 named_certificates.go:53] loaded SNI cert [0/"self-signed loopback"]: "apiserver-loopback-client@1629947939" [serving] validServingFor=[apiserver-loop
back-client] issuer="apiserver-loopback-client-ca@1629947936" (2021-08-26 02:18:54 +0000 UTC to 2022-08-26 02:18:54 +0000 UTC (now=2021-08-26 03:18:59.430463658 +0000 UTC))
I0826 03:18:59.430522       1 secure_serving.go:197] Serving securely on [::]:10258
I0826 03:18:59.430612       1 tlsconfig.go:240] Starting DynamicServingCertificateController
I0826 03:18:59.537841       1 node.go:46] "Node lister returned empty list, now fetch directly"
I0826 03:18:59.629163       1 duplicates.go:99] "Processing node" node="master-0"
I0826 03:18:59.727021       1 duplicates.go:99] "Processing node" node="master-1"
I0826 03:18:59.827317       1 duplicates.go:99] "Processing node" node="master-2"
I0826 03:18:59.854129       1 duplicates.go:99] "Processing node" node="worker-0"
I0826 03:18:59.878843       1 duplicates.go:99] "Processing node" node="worker-1"
I0826 03:18:59.913138       1 duplicates.go:99] "Processing node" node="worker-2"
I0826 03:18:59.945896       1 duplicates.go:194] "Adjusting feasible nodes" owner={namespace:spring-liberty kind:ReplicaSet name:spring-liberty-85469f6ffd imagesHash:image-registry
.openshift-image-registry.svc:5000/spring-liberty/spring-liberty} from=6 to=3
I0826 03:18:59.945925       1 duplicates.go:202] "Average occurrence per node" node="worker-1" ownerKey={namespace:spring-liberty kind:ReplicaSet name:spring-liberty-85469f6ffd ima
gesHash:image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty} avg=1
I0826 03:18:59.967505       1 evictions.go:130] "Evicted pod" pod="spring-liberty/spring-liberty-85469f6ffd-c6sms" reason="RemoveDuplicatePods"
I0826 03:18:59.984554       1 topologyspreadconstraint.go:139] "Processing namespaces for topology spread constraints"
I0826 03:19:00.427877       1 descheduler.go:151] "Number of evicted pods" totalEvicted=1
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2