IBM Cloud Docs
パフォーマンスのチューニング

パフォーマンスのチューニング

特定のパフォーマンス最適化要件がある場合は、IBM Cloud® Kubernetes Service の 一部のクラスター・コンポーネント用のデフォルト設定を変更できます。

デフォルトの設定を変更する場合は、お客様自身の責任で行ってください。 変更された設定に対してテストを実行すること、および環境内の設定変更が原因で発生する可能性がある障害についてはお客様が責任を持ちます。

ワーカー・ノードのデフォルト設定

デフォルトでは、ワーカー・ノードには、ワーカー・プールの作成時に選択したワーカー・ノード・フレーバーのオペレーティング・システムとコンピュート・ハードウェアが搭載されています。

オペレーティング・システムのカスタマイズ

クラスター・バージョン別のサポート対象オペレーティング・システムのリストについては、 Kubernetes バージョン情報 を参照してください。 クラスターでオペレーティング・システムを混用したり、異なるオペレーティング・システムを使用したりすることはできません。

ワーカー・ノードを最適化する場合は、以下の情報を検討してください。

  • イメージとバージョンの更新: ワーカー・ノードの更新情報 (イメージや Kubernetes バージョンへのセキュリティー・パッチなど) は IBM によって提供されます。 ただし、ワーカー・ノードに更新を適用するタイミングはユーザーが選択します。 詳しくは、クラスター、ワーカー・ノード、クラスター・コンポーネントの更新を参照してください。
  • 一時的な変更: ポッドにログインするか他のプロセスを使用してワーカー・ノード設定を変更した場合、変更は一時的になります。 ワーカー・ノードのライフサイクル操作 (ワーカー・ノードの自動リカバリー、再ロード、更新、置換など) を行うと、それまでの変更内容がデフォルト設定に戻ります。
  • 永続的な変更 :ワーカーノードのライフサイクル操作に渡って変更を持続させるには、 init コンテナを使用するデーモンセットを作成します。 詳しくは、パフォーマンスを最適化するためのデフォルト・ワーカー・ノード設定の変更を参照してください。

オペレーティング・システムへの変更はサポートされていません。 デフォルト設定を変更する場合、問題が発生したときにお客様の責任でデバッグおよび解決する必要があります。

ハードウェアの変更

ワーカー・ノードごとに CPU やメモリーなどのコンピュート・ハードウェアを変更する場合、以下のオプションから選択します。

ワーカーノードのカーネル設定を変更してパフォーマンスを最適化する

クラスター・ワーカー・ノードは、ほとんどのワークロードのニーズを満たすことが期待される安定性、最適化、およびパフォーマンスのレベルで構成されます。 通常、ワーカー・ノードのカーネル設定を変更することはお勧めしません。そのような変更を行うと、異常な問題や意図しない問題が発生する可能性があります。 ただし、ワークロードに、カーネル設定の変更を必要とする非常に固有のパフォーマンス最適化要件がある場合は、カスタム Kubernetes デーモン・セットを適用してカーネル構成を変更することができます。 これらの変更は重大な悪影響を及ぼす可能性があること、および お客様自身の責任でカーネル設定構成に対する変更を実装することを理解してください。

カーネル設定の構成を変更する場合は、必ず、行った変更を正確に文書化して保存してください。 クラスターに関連する問題のサポート・チケットをオープンする場合は、これらの変更を指定する必要があります。 これらの構成変更が問題の原因となっている可能性があり、問題調査の一環として変更を元に戻すように求められる場合があります。 この場合、実装したカーネル構成変更を元に戻す必要があります。

デフォルトのカーネル設定を変更すると、クラスターに悪影響を及ぼす可能性があります。 これらの変更は、お客様の責任で行ってください。

デフォルトのカーネル設定を変更するには、 init コンテナー を使用してカスタム Kubernetes DaemonSet をクラスターに適用します。 デーモン・セットは、既存のすべてのワーカー・ノードの設定を変更し、クラスター内でプロビジョンされる新しいワーカー・ノードにこの設定を適用します。 init コンテナは、ワーカーノードで他のポッドがスケジュールされる前に、これらの変更が行われるようにする。 ポッドは影響を受けません。

サンプルの特権 initContainer を実行するには、すべてのネームスペースの Manager IBM Cloud IAM サービスアクセスロールが 必要です。 デプロイメントのコンテナーが初期化された後、特権は除去されます。

始める前に: アカウントにログインします。 該当する場合は、適切なリソース・グループをターゲットにします。 クラスターのコンテキストを設定します。

  1. 以下のデーモン・セットを worker-node-kernel-settings.yaml という名前のファイルに保存します。 spec.template.spec.initContainers セクションで、調整する sysctl パラメーターのフィールドと値を追加します。 このサンプルのデーモン・セットでは、環境に許可するデフォルトの最大接続数を net.core.somaxconn 設定を使用して変更し、一時ポート範囲を net.ipv4.ip_local_port_range 設定を使用して変更しています。
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: kernel-optimization
      namespace: kube-system
      labels:
        tier: management
        app: kernel-optimization
    spec:
      selector:
        matchLabels:
          name: kernel-optimization
      template:
        metadata:
          labels:
            name: kernel-optimization
        spec:
          hostNetwork: true
          hostPID: true
          hostIPC: true
          initContainers:
            - command:
                - sh
                - -c
                - sysctl -w net.ipv4.tcp_syn_retries="5"; sysctl -w net.ipv4.tcp_fin_timeout="15";
              image: us.icr.io/armada-master/network-alpine:latest
              imagePullPolicy: Always
              name: sysctl
              resources: {}
              securityContext:
                privileged: true
                capabilities:
                  add:
                    - NET_ADMIN
              volumeMounts:
                - name: modifysys
                  mountPath: /sys
          containers:
            - resources:
                requests:
                  cpu: 0.01
              image: us.icr.io/armada-master/network-alpine:latest
              name: sleepforever
              command: ["/bin/sh", "-c"]
              args:
                - >
                  while true; do
                    sleep 100000;
                  done
          volumes:
            - name: modifysys
              hostPath:
                path: /sys
    
  2. ワーカー・ノードにデーモン・セットを適用します。 この変更はすぐに適用されます。
    kubectl apply -f worker-node-kernel-settings.yaml
    

ワーカーノードの sysctl パラメータをデフォルト値に戻すには、以下の手順に従ってください。

  1. デーモン・セットを削除します。 カスタム設定を適用した initContainers が削除されます。
    kubectl delete ds kernel-optimization
    
  2. クラスター内のすべてのワーカー・ノードをリブートします。 ワーカー・ノードは、デフォルト値が適用された状態でオンラインに戻ります。

ポッドのパフォーマンスの最適化

特定のパフォーマンス・ワークロードの要件がある場合は、ポッドのネットワーク名前空間で、Linux カーネルの sysctl パラメーターのデフォルト設定を変更します。

app podsのカーネル設定を最適化するには、デプロイメントごとに YAMLに initContainerpod/ds/rs/deployment パッチを挿入できます。 パフォーマンスを最適化したいポッドのネットワーク名前空間にある各アプリ・デプロイメントに initContainer が追加されます。

開始する前に、サンプルの特権 initContainer を実行するすべてのネームスペースの Manager IBM Cloud IAM サービスアクセスロールが あることを確認してください。 デプロイメントのコンテナーが初期化された後、特権は除去されます。

  1. 以下の initContainer パッチを pod-patch.yaml という名前のファイルに保存し、調整する sysctl パラメーターのフィールドと値を追加します。 このサンプルの initContainer は、環境に許可するデフォルトの最大接続数を net.core.somaxconn 設定を使用して変更し、 一時ポート範囲を net.ipv4.ip_local_port_range 設定を使用して変更します。
    spec:
      template:
        spec:
          initContainers:
          - command:
            - sh
            - -c
            - sysctl -e -w net.core.somaxconn=32768;  sysctl -e -w net.ipv4.ip_local_port_range="1025 65535";
            image: alpine:3.6
            imagePullPolicy: IfNotPresent
            name: sysctl
            resources: {}
            securityContext:
              privileged: true
    
  2. 各デプロイメントにパッチを適用します。
    kubectl patch deployment <deployment_name> --patch pod-patch.yaml
    
  3. カーネル設定の net.core.somaxconn 値を変更した場合、ほとんどのアプリが、更新された値を自動的に使用します。 ただし、一部のアプリでは、カーネル値に一致するように、アプリ・コードの対応する値を手動で変更する必要がある場合があります。 例えば、NGINX アプリが実行されるポッドのパフォーマンスを調整する場合、NGINX アプリ・コードの backlog フィールドの値を一致するように変更する必要があります。 詳しくは NGINXブログの記事をご覧ください。

ネットワーク・キープアライブ sysctl 設定の最適化

ポッドの TCP 接続が長時間実行されていて、一定期間アイドル状態のときに切断されることがある場合は、ポッドの sysctl キープアライブ設定を変更すると役立つ可能性があります。

現在、クラスター内のすべてのポッドでこれらの sysctl キープアライブ設定をデフォルトで設定する方法はありません。 すべてのポッドの設定を変更する最善の方法は、特権 initContainer を使用することです。 test-ns 名前空間でデプロイメント用に initContainer をセットアップする方法については、以下の例を参照してください。

以下のサンプル initContainer をデプロイします。 containers: セクションは、必ず独自のアプリケーション・コンテナーに変更してください。 次に、 initContainer は、ポッド内のすべての通常コンテナーに対して sysctl 設定を設定します。これらのコンテナーはすべて同じネットワーク名前空間を共有するためです。

```sh {: pre}
kubectl apply -f - << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-sysctl
  namespace: test-ns
  labels:
    run: test-sysctl
spec:
  replicas: 2
  selector:
    matchLabels:
      run: test-sysctl
  template:
    metadata:
      labels:
        run: test-sysctl
    spec:
      initContainers:
      - command:
        - sh
        - -c
        - sysctl -e -w net.ipv4.tcp_keepalive_time=40; sysctl -e -w net.ipv4.tcp_keepalive_intvl=15; sysctl -e -w net.ipv4.tcp_keepalive_probes=6;
        image: us.icr.io/armada-master/alpine:latest
        imagePullPolicy: IfNotPresent
        name: sysctl-init
        resources: {}
        securityContext:
          privileged: true
      containers:
      - name: test-sysctl
        image: us.icr.io/armada-master/alpine:latest
        command: ["sleep", "2592000"]
  EOF
```

クラスター・メトリック・プロバイダー・リソースの調整

クラスターには、kube-system 名前空間内の metrics-server デプロイメントによって提供されるメトリック・サービスがあります。 metrics-server リソース要求は、クラスター内のノード数に基づいており、ワーカー・ノード当たりのポッド数が 30 以下のクラスター用に最適化されています。 メトリック・サービスは、リソース要求のメモリー制限および CPU 制限の突き合わせを行います。

メモリー要求が低すぎる場合、メトリック・サービス・コンテナーは「メモリー不足による強制終了」になる可能性があります。 CPU要求が低すぎる場合、CPUスロットリングのため、応答が非常に遅くなったり、有効性プローブやレディネス・プローブに失敗したりすることがある。

メモリー使用量は、クラスター内のポッド数によって決まります。 CPU 使用率は、メトリック (HPA、 kubectl top nodes / pods など) の要求数と API ディスカバリー要求数によって決まります。 metrics-server には Kubernetes API が用意されているため、API ディスカバリーを使用する kubectl などのクライアントは、メトリックを使用しない場合でも、metrics-server に負荷をかけます。

以下の症状は、metrics-server リソースを調整する必要があることを示している可能性があります。

  • metrics-server が頻繁に再始動する。

  • 名前空間を削除すると、名前空間が Terminating 状態のままになり、kubectl describe namespace にメトリック API ディスカバリー・エラーを報告する条件が含まれる。

  • kubectl top podskubectl top nodes、その他の kubectl コマンド、または Kubernetes API を使用するアプリケーションが、以下のような Kubernetes エラーをログに記録する。

The server is currently unable to handle the request (get pods.metrics.k8s.io)
Discovery failed for some groups, 1 failing: unable to retrieve the complete list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to handle the request
  • HorizontalPodAutoscalers (HPA) がデプロイメントをスケーリングしない。

  • kubectl get apiservices v1beta1.metrics.k8s.io を実行すると、次のような状況になる。

NAME                     SERVICE                      AVAILABLE                      AGE
v1beta1.metrics.k8s.io   kube-system/metrics-server   False (FailedDiscoveryCheck)   139d

metrics-server-config 構成マップの変更

CPU とメモリーの両方に、要求合計を計算するために使用されるチューナブル「基本 (base)」設定と「ノード当たり (per node)」設定があります。

  • baseCPU
  • cpuPerNode
  • baseMemory
  • memoryPerNode

ここで、

cpuRequest = baseCPU + cpuPerNode * number_of_nodes
memoryRequest = baseMemory + memoryPerNode * number_of_nodes

これらの計算におけるノード数は、一連の「バケット・サイズ」から取得され、最小サイズは 16 ノードです。

CPU は、1 などの値、または 100m (100 ミリコア) などの小数値を使用して、コア単位で要求されます。

メモリーはバイト単位で要求されます。オプションの接尾部は以下のとおりです。

  • base 2 1Ki = 1024): Ki (キロバイト)、 Mi (メガバイト)、 Gi (ギガバイト)。
  • メトリック 1k = 1000): k M, G.

クラスター内のノード数が時間の経過とともに増加する (または単に変化する) ことが予想される場合は、「ノード当たり (per node)」設定を調整することをお勧めします。 ノード数が変化しない場合は、「基本 (base)」設定を調整します。 最終的に、CPU とメモリーの合計値は、metrics-server デプロイメント・リソース要求で設定されます。

メトリック・プロバイダーの構成マップを編集して、デフォルトのリソースを変更できます。 metrics-server デプロイメントでリソースの要求や制限を直接変更しないでください。これらの値は metrics-server-nanny コンテナーによって上書きされます。

デフォルトの metrics-server-config 構成マップは以下のとおりです。

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
    kubernetes.io/cluster-service: "true"
  name: metrics-server-config
  namespace: kube-system
data:
  NannyConfiguration: |-
    apiVersion: nannyconfig/v1alpha1
    kind: NannyConfiguration

この例は、すべての値が定義された構成マップを示しています。

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
    kubernetes.io/cluster-service: "true"
  name: metrics-server-config
  namespace: kube-system
data:
  NannyConfiguration: |-
    apiVersion: nannyconfig/v1alpha1
    kind: NannyConfiguration
    baseCPU: 200m
    cpuPerNode: 1m
    baseMemory: 40Mi
    memoryPerNode: 6Mi

デフォルト値は以下のとおりです。

baseCPU: 200m
cpuPerNode: 1m
baseMemory: 40Mi
memoryPerNode: 6Mi

構成マップの編集

kubectl edit コマンドを使用して構成マップを編集できます。

kubectl edit cm metrics-server-config -n kube-system

変更するフィールドを追加または編集し、構成マップを保存してエディターを終了します。

IBM Cloud 提供の metrics-server は、構成マップの変更をモニターし、デプロイメント・リソース要求を自動的に更新します。 metrics-server が変更を検出し、更新された設定に基づいて新しいポッド・セットをロールアウトするまでに、最大 10 分かかる場合があります。

デフォルト設定の復元

metrics-server をデフォルト設定に復元するには、構成マップを削除します。 数分以内に再作成されます。

kubectl delete cm metrics-server-config -n kube-system

チューニングするリソースの決定

kubectl describe pod コマンドを使用して、ポッド定義、状態情報、および最近のイベントを取得します。

kubectl get pod -n kube-system -l k8s-app=metrics-server
NAME                             READY   STATUS    RESTARTS   AGE
metrics-server-9fb4947d6-s6sgl   3/3     Running   0          2d4h
kubectl describe pod -n kube-system metrics-server-9fb4947d6-s6sgl

出力例

Containers:
  metrics-server:
    Container ID:  containerd://fe3d07c9a2541242d36da8097de3896f740c1363f6d2bfd01b8d96a641192b1b
    Image:         registry.ng.bluemix.net/armada-master/metrics-server:v0.4.4
    Image ID:      registry.ng.bluemix.net/armada-master/metrics-server@sha256:c2c63900d0e080c2413b5f35c5a59b5ed3b809099355728cf47527aa3f35477c
    Port:          4443/TCP
    Host Port:     0/TCP
    Command:
      /metrics-server
      --metric-resolution=45s
      --secure-port=4443
      --tls-cert-file=/etc/metrics-server-certs/tls.crt
      --tls-private-key-file=/etc/metrics-server-certs/tls.key
    State:          Running
      Started:      Fri, 10 Sep 2021 17:31:39 +0000
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137
      Started:      Fri, 10 Sep 2021 05:59:51 +0000
      Finished:     Fri, 10 Sep 2021 17:31:37 +0000
    Ready:          True
    Restart Count:  36

Last StateOOMKilledReason が表示されている場合は、metrics-server-config ConfigMap 内のメモリー要求を、メトリック・サーバーが安定し、OOMkilled されずに数時間以上実行されるようになるまで、100Mi 以上の単位で増加させます。

Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137

Last stateErrorReason と、以下の例のようなイベントが表示されている場合は、メトリック・サーバーが安定し、プローブ・タイムアウトのために強制終了されずに数時間以上実行されるようになるまで、metrics-server-config 構成マップの CPU 要求を 100m 以上の単位で増加させます。

Last State:     Terminated
  Reason: Error
  Exit Code: 137
Events:
Warning Unhealthy 46m (x5 over 80m) kubelet Liveness probe failed: Get "https://198.18.68.236:4443/livez": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Warning Unhealthy 26m (x65 over 89m) kubelet Liveness probe failed: Get "https://198.18.68.236:4443/livez": net/http: TLS handshake timeout
Warning Unhealthy 21m (x10 over 76m) kubelet Readiness probe failed: Get "https://198.18.68.236:4443/readyz": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning Unhealthy 115s (x93 over 90m) kubelet Readiness probe failed: Get "https://198.18.68.236:4443/readyz": net/http: TLS handshake timeout

安定した構成に達するには、このプロセスを数回繰り返すことが必要になる場合があります。最初にメモリー要求を調整してから CPU 要求を調整します。

ヒュージ・ページの有効化

クラシック・インフラストラクチャー 仮想プライベート・クラウド

Kubernetes バージョン 1.19 以降を実行するクラスタでは、 Kubernetes HugePages スケジューリングを有効にできます。 サポートされている唯一のページ・サイズはページ当たり 2 MB で、これが Kubernetes 機能ゲートのデフォルト・サイズです。

ヒュージ・ページのスケジュール設定は、IBM Cloud Kubernetes Service のベータ版機能であり、変更される可能性があります。

デフォルトでは、ワーカー・ノードの CPU は、RAM を 4 KB のチャンクまたはページ単位で割り当てます。 アプリにもっと多くの RAM が必要な場合、システムはさらにページを検索し続けなければならず、そのために処理速度が低下することがあります。 ヒュージ・ページを使用すると、ページ・サイズを 2 MB まで増やして、人工知能 (AI) 用のデータベース、モノのインターネット (IoT)、または機械学習のワークロードなど、RAM を激しく使用するアプリのパフォーマンスを向上できます。 巨大ページの詳細については、 Linux カーネル・ドキュメントを参照のこと。

ワーカー・ノードをリブートしても、ヒュージ・ページの構成は維持されます。 しかし、巨大ページのコンフィギュレーションは、他のワーカーノードのライフサイクル操作に渡って持続しません。 ワーカー・ノードの更新、再ロード、置換、または追加のたびに有効化のステップを繰り返す必要があります。

  • IBM Cloud IAM のクラスターに対する**「オペレーター」プラットフォーム・アクセス役割と「マネージャー」**サービス・アクセス役割

始める前に: アカウントにログインします。 該当する場合は、適切なリソース・グループをターゲットにします。 クラスターのコンテキストを設定します。

  1. ヒュージ・ページを有効にするための hugepages-ds.yaml 構成ファイルを作成します。 以下のサンプル YAML は、デーモン・セットを使用して、クラスター内のすべてのワーカー・ノードでこのポッドを実行します。 vm.nr_hugepages パラメーターを使用して、ワーカー・ノードで使用できるヒュージ・ページの割り振りを設定できます。 この例では、512 ページ (ページ当たり 2 MB) を割り振り、合計で 1 GB の RAM をヒュージ・ページ専用に割り振っています。

    RAM を大量に使用するアプリに使用するワーカー・プールなど、特定のワーカー・ノードのみに対してヒュージ・ページを有効にする場合は、 ワーカー・プールに ラベルを付けて テイントし、デーモン・セットに アフィニティ・ルールを追加して、指定したワーカー・プールのワーカー・ノードにのみポッドがデプロイされるようにする。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: hugepages-enablement
      namespace: kube-system
      labels:
        tier: management
        app: hugepages-enablement
    spec:
      selector:
        matchLabels:
          name: hugepages-enablement
      template:
        metadata:
          labels:
            name: hugepages-enablement
        spec:
          hostPID: true
          initContainers:
            - command:
                - sh
                - -c
                # Customize allocated Hugepages by providing the value
                - "echo vm.nr_hugepages=512 > /etc/sysctl.d/90-hugepages.conf"
              image: alpine:3.6
              imagePullPolicy: IfNotPresent
              name: sysctl
              resources: {}
              securityContext:
                privileged: true
              volumeMounts:
                - name: modify-sysctld
                  mountPath: /etc/sysctl.d
          containers:
            - resources:
                requests:
                  cpu: 0.01
              image: alpine:3.6
              # once the init container completes, keep the pod running for worker node changes
              name: sleepforever
              command: ["/bin/sh", "-c"]
              args:
                - >
                  while true; do
                      sleep 100000;
                  done
          volumes:
            - name: modify-sysctld
              hostPath:
                path: /etc/sysctl.d
    
  2. 先ほど作成したファイルを適用します。

    kubectl apply -f hugepages-ds.yaml
    
  3. ポッドが**「実行中」**であることを確認します。

    kubectl get pods
    
  4. ワーカー・ノードをリブートして、各ワーカー・ノードで実行される kubelet を再始動します。 kubelet を再始動するためにワーカー・ノードを再ロードしないでください。 kubelet がヒューズ・ページの有効化について認識する前にワーカー・ノードを再ロードすると、有効化は失敗します。

    1. クラスター内のワーカー・ノードをリストします。
      ibmcloud ks worker ls -c <cluster_name_or_ID>
      
    2. ワーカー・ノードをリブートします。 複数の -w オプションを含めることで、複数のワーカーノードをリブートすることができますが、アプリが停止しないよう、十分な数のワーカーノードを同時に稼動させておくようにしてください。
      ibmcloud ks worker reboot -c <cluster_name_or_ID> -w <worker1_ID> -w <worker2_ID>
      
  5. ヒュージ・ページをボリュームとしてマウントし、ポッドが使用するヒュージ・ページのリソースの量をリソース制限と要求を使用して設定する、hugepages-test.yaml テスト・ポッドを作成します : ラベル、テイント、およびアフィニティー・ルールを使用して選択したワーカー・ノードのみでヒュージ・ページを有効にした場合は、これらの同じルールをテスト・ポッドに含めてください。

    apiVersion: v1
    kind: Pod
    metadata:
      name: hugepages-example
    spec:
      containers:
      - name: hugepages-example
        image: fedora:34
        command:
        - sleep
        - inf
        volumeMounts:
        - mountPath: /hugepages-2Mi
          name: hugepage-2mi
        resources:
          limits:
            hugepages-2Mi: 100Mi
            memory: 100Mi
          requests:
            memory: 100Mi
      volumes:
      - name: hugepage-2mi
        emptyDir:
          medium: HugePages-2Mi
    
  6. 先ほど作成したポッド・ファイルを適用します。

    kubectl apply -f hugepages-pod.yaml
    
  7. ポッドがヒュージ・ページのリソースを使用していることを確認します。

    1. ポッドが**「実行中」**であることを確認します。 ヒュージ・ページを使用するワーカー・ノードが使用可能でない場合、ポッドは実行されません。
      kubectl get pods
      
    2. ポッドにログインします。
      kubectl exec -it <pod> /bin/sh
      
    3. ポッドで、ヒュージ・ページのサイズを表示できることを確認します。
      ls /sys/kernel/mm/hugepages
      
      出力例
      hugepages-1048576kB  hugepages-2048kB
      
  8. オプション: 有効化デーモン・セットを削除します。 後に、ヒュージ・ページを使用するワーカー・ノードの更新、再ロード、置換、または追加が必要になった場合は、デーモン・セットを再作成しなければならないことに注意してください。

    kubectl -n kube-system delete daemonset hugepages-enablement
    
  9. ワーカー・ノードを更新、再ロード、置換、または追加するたびにこれらのステップを繰り返します。

ヒュージ・ページを使用するワーカー・ノードをトラブルシューティングする場合は、対象のワーカー・ノードのリブートのみを行うことができます。 ヒュージ・ページの構成は、ワーカー・ノードの更新、再ロード、置換、または追加などの他のワーカー・ノード・ライフサイクル操作には引き継がれません。 クラスターからヒュージ・ページの構成を削除するには、すべてのワーカー・ノードを更新、再ロード、または置換できます。

Calico 最大伝送単位 (MTU) の変更

Calico プラグインの最大伝送単位 (MTU) を増減して環境のネットワーク・スループット要件を満たすことができます。

これらの手順は、バージョン 1.29 以降を実行するクラスタに適用されます。 さらに、すべてのVPCワーカーノードはジャンボフレームをサポートしていますが、クラシックインフラはベアメタルワーカーでのみジャンボフレームをサポートしています。

最大伝送単位(MTU)値を変更すると、特に複雑なネットワーク環境では予期せぬ結果を招くことがある。 ワークフローの中断を避けるため、本番クラスタに変更を加える前に、開発クラスタでこれらの変更をテストすることを強くお勧めします。

デフォルトでは、IBM Cloud Kubernetes ServiceクラスタのCalicoネットワークプラグインのMTUは、Satelliteクラスタでは1450バイト、Satelliteクラスタでは1480バイトです。 ほとんどの場合、パケットのドロップやフラグメンテーションを防ぐには、このデフォルトのCalicoMTU値で十分です。 ほとんどのホストは1500のMTU値を使用するため、これらのデフォルト値ではSatelliteクラスタにVXLANヘッダ用に50バイトの追加バイトが提供され、Satelliteクラスタ以外のクラスタに一部のポッド間クラスタネットワークトラフィックで使用されるIPヘッダ用に20バイトの追加バイトが提供されます。 クラスタ内のすべてのワーカーノードが同じCalicoMTU値を使用しなければならないことに注意してください。

デフォルトの Calico MTU の変更が必要になる状況としては、次のような状況があります。

  • ポッド間ネットワークのスループットを向上させる必要があり、クラスタノードがより高いホストMTUを使用できる場合は、ホストとCalicoのMTUの両方を増やすことができます。 これを「ジャンボフレーム」の使用と呼ぶ。 一般的なジャンボフレームのMTUは9000である。 この場合、ホストのプライベート・ネットワーク・インタフェースのMTUを9000に設定し、CalicoのMTUを少し低い値(Satelliteクラスタでは8950、Satelliteクラスタでは8980)に設定することができます。 Azure仮想マシンなど、クラウドプロバイダーのハードウェアやリソースによっては、ジャンボフレームをサポートしていなかったり、最大4000のMTU値しかサポートしていなかったりする場合があることに注意してください。
  • クラスターにセットアップした VPN 接続に、デフォルトよりも小さい Calico MTU を必要とするものがある場合。 デフォルトより小さい Calico MTU が必要かどうかは、VPN サービス・プロバイダーに確認してください。
開始前に
ワーカーノードがまだデフォルトの MTU 値を使用している場合は、 Calico プラグインの MTU 値を増やす前に、まずワーカーノードの MTU 値を増やしてください。 たとえば、次のデーモン・セットを適用して、ワーカー・ノードのMTUを9000バイトに変更できます。 ip link コマンドで使用されるインターフェース名は、ワーカー・ノードのタイプによって異なることに注意してください。
  • ベア・メタル・ワーカー・ノードのコマンド例: ip link set dev bond0 mtu 9000;ip link set dev bond1 mtu 9000;
  • VPC 第 2 世代ワーカー・ノードのコマンド例: ip link set dev ens3 mtu 9000;
  1. クラスタのワーカーノードにログインし、ノード間でpingを実行するには、以下のコマンドを実行します。 ノードのMTUは1500または1480にしか設定されていないため、この試みは失敗すると予想される。 次のステップでは、これらのコマンドを再度実行して、変更が成功したことを確認します。

    1. クラスター内のノードをリストします。 健全な2つのノードの名前とIPアドレスを保存する。

      kubectl get nodes -o wide
      
    2. いずれかのノードにログインします。 ノードの名前を指定する。

      kubectl debug --image=us.icr.io/armada-master/network-alpine -it node/<NODE_NAME> -- sh
      
    3. 一方のノードから他方のノードにpingを打つコマンドを実行する。 前のステップで参照しなかったノードのIPアドレスを指定します。

      ping -c1 -Mdo -s 8972 <OTHER_HOST_IP>
      
  2. 以下の例のデーモンセットでノードのMTUを変更する。 このMTU値はノード間トラフィックに適用される。 MTU値を含めるために - ip link set dev ens3 mtu <MTU_VALUE> 行を修正する(例ではMTU値9000を使用)。 ens3があなたのノードに適切でない場合は、「ens3 インターフェース名も変更する必要があるかもしれないことに注意してください。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      labels:
        app: set-host-mtu
      name: set-host-mtu
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          name: set-host-mtu
      template:
        metadata:
          labels:
            name: set-host-mtu
        spec:
          containers:
          - args:
            - |
              while true; do
                sleep 100000;
              done
            command:
            - /bin/sh
            - -c
            image: us.icr.io/armada-master/network-alpine:latest
            imagePullPolicy: IfNotPresent
            name: sleepforever
            resources:
              requests:
                cpu: 10m
          hostNetwork: true
          initContainers:
          - command:
            - sh
            - -c
            - ip link set dev ens3 mtu 9000
            image: us.icr.io/armada-master/network-alpine:latest
            imagePullPolicy: IfNotPresent
            name: set-host-mtu
            securityContext:
              capabilities:
                add:
                - NET_ADMIN
              privileged: true
            volumeMounts:
            - mountPath: /sys
              name: modifysys
          restartPolicy: Always
          terminationGracePeriodSeconds: 2
          tolerations:
          - operator: Exists
          volumes:
          - hostPath:
              path: /sys
              type: ""
            name: modifysys
      updateStrategy:
        rollingUpdate:
          maxSurge: 0
          maxUnavailable: 1
        type: RollingUpdate
    
  3. デーモンセットを適用してノードのMTU値を変更する。

      kubectl apply -f <file_name>
    
  4. ノードにログインし、あるホストから別のホストへ、大きなパケットサイズを使ってpingを打つコマンドを再実行する。 ノードのMTU値を増やしたので、'ping コマンドは成功すると思われる。

    kubectl debug --image=us.icr.io/armada-master/network-alpine -it node/<NODE_NAME> -- sh
    
    ping -c1 -Mdo -s 8972 <OTHER_HOST_IP>
    
  5. 時間をかけて、新しいノードMTU値でクラスタをテストしてください。 CalicoのMTU値の変更を続ける前に、アプリケーションが期待通りに機能するか確認することをお勧めします。

  6. コマンドを実行してCalicoのMTU値を更新し、ポッド間のトラフィックもより大きなMTUを使用できるようにします。 SatelliteCore OSクラスタの場合、CalicoのMTU値はノードのMTU値より50バイト少なくする必要があります。 それ以外のクラスタでは、CalicoのMTU値を20バイト少なくする必要があります。 たとえば、ノードのMTUに9000を指定した場合、CalicoのMTUはSatelliteCore OSクラスタでは8950、その他のクラスタでは8980になるはずです。

    kubectl patch installation.operator.tigera.io default --type='merge' -p '{"spec":{"calicoNetwork":{"mtu":<MTU_VALUE>}}}'
    

    また、'kubectl edit installation.operator.tigera.io default を実行して直接リソースを編集することもできる。

  7. すべてのノードを注意深く再起動して、これらの変更をすべてのノードに適用します。 これらの変更によってワークロードが中断される可能性があるため、このステップを続行する前に、開発クラスタ上でこのプロセスをテストしていることを確認してください。 ノードをリブートするには、ノードの コード化、排水、リブート を1つずつ行うことをお勧めします。

本番クラスタ上でこれらの手順を完了する場合は、本番ノードの更新または交換に使用するのと同じプロセスを使用する必要があります。 本番クラスタでこれらの手順を完了する前に、テストクラスタでこのプロセス全体をテストすることを強くお勧めします。

リブート処理中、一部のポッドは新しい大きいMTUを使用し、一部のポッドは元の小さいMTUのままです。 通常、このシナリオでは、双方が正しい最大パケットサイズをネゴシエートするため、問題は発生しない。 ただし、ICMPパケットをブロックすると、ネゴシエーションがうまくいかず、すべての再起動が完了するまでクラスタにポッド接続の問題が発生する可能性があります。 このプロセスは、まず開発クラスタでテストすることが重要である。

ポート・マップ・プラグインの無効化

Calico のコンテナー・ネットワーク・インターフェース (CNI) 用の portmap プラグインは、hostPort を使用して、ワーカー・ノードの特定のポートでアプリ・ポッドを公開できるようにするものです。 このポート・マップ・プラグインをクラスターの Calico CNI 構成から削除すると、iptables のパフォーマンスの問題を防止できます。

クラスター内に 500 以上のサービスなど多くのサービスがある場合や、10 以上のサービスに対して 1 サービスあたり 50 以上のポートがあるなどサービス上のポートが多い場合、これらのサービスの Calico ネットワーク・ポリシーおよび Kubernetes ネットワーク・ポリシーに対して多数の iptables ルールが生成されます。 多数の iptables ルールを使用すると、ポートマッププラグインのパフォーマンスに問題が発生する可能性があります。また、指定した時間内に iptables ルールの更新を行うためのロックが受信されない場合、iptables ルールの今後の更新が妨げられたり、 calico-node コンテナが再起動したりする可能性があります。 このようなパフォーマンスの問題を防止するために、ポート・マップ・プラグインをクラスターの Calico CNI 構成から削除して無効にすることができます。

hostPortsを使用する必要がある場合は、ポート・マップ・プラグインを無効にしないでください。

Kubernetes バージョン 1.29 以降でのポート・マップ・プラグインの無効化

  1. default Calico インストール・リソースを編集します。
    kubectl edit installation default -n calico-system
    
  2. spec.calicoNetwork セクションで、hostPorts の値を Disabled に変更します。
    ...
    spec:
      calicoNetwork:
        hostPorts: Disabled
        ipPools:
        - cidr: 172.30.0.0/16
          encapsulation: IPIPCrossSubnet
          natOutgoing: Enabled
          nodeSelector: all()
        mtu: 1480
        nodeAddressAutodetectionV4:
          interface: (^bond0$|^eth0$|^ens6$|^ens3$)
      kubernetesProvider: OpenShift
      registry: registry.ng.bluemix.net/armada-master/
      variant: Calico
    status:
      variant: Calico
    
  3. ファイルを保存して閉じます。 変更が自動的に適用されます。

Kubernetes バージョン 1.28 以前でのポート・マップ・プラグインの無効化

  1. calico-config 構成マップ・リソースを編集します。

    kubectl edit cm calico-config -n kube-system
    
  2. data.cni_network_config.plugins プラグインの後の kubernetes セクションの portmap プラグイン・セクションを削除します。 portmap セクションを削除した後の構成は、次のようになります。

    apiVersion: v1
    data:
      calico_backend: bird
      cni_network_config: |-
        {
          "name": "k8s-pod-network",
          "cniVersion": "0.3.1",
          "plugins": [
            {
              "type": "calico",
              ...
            },
            {
              "type": "tuning",
              ...
            },
            {
              "type": "bandwidth",
              ...
            }
          ]
        }
      typha_service_name: calico-typha
      ...
    

    この構成マップで Calico プラグインの他の設定を変更することはできません。

  3. すべての calico-node ポッドを再始動して、変更をクラスターに適用します。

    kubectl rollout restart daemonset -n kube-system calico-node