ack-koordinator コンポーネントは、ACK クラスターで実行されているコンテナにメモリサービス品質 (QoS) を提供します。コンテナに異なる QoS クラスを割り当てることで、ack-koordinator は遅延の影響を受けやすいワークロードのメモリを優先し、メモリ競合時のメモリ不足 (OOM) エラーを削減します。
仕組み
Kubernetes は、各 Pod にメモリリクエストとメモリ制限を割り当てます。メモリが制約されている場合、2つの障害モードが発生します。
-
コンテナレベルの負荷: コンテナのメモリ使用量 (ページキャッシュを含む) がその制限に近づくと、OS は memcgレベルの直接メモリ再利用をトリガーし、コンテナのプロセスをブロックします。メモリの割り当てが再利用よりも速い場合、OOM エラーにより Pod が終了します。
-
ノードレベルの負荷: コンテナのメモリ制限の合計がノードの物理メモリを超えると、OS カーネルはコンテナ間で無差別にメモリを再利用します。これによりパフォーマンスが低下し、ノード上の任意の Pod で OOM エラーがトリガーされる可能性があります。
ack-koordinator は、各コンテナのメモリ制御グループ (memcg) を自動的に構成することで、両方の障害モードに対処します。これにより、3つの Alibaba Cloud Linux カーネル機能が有効になります。
-
Memcg QoS: 最小限のメモリ量をロックし、高優先度コンテナがワーキングセットを保持できるようにします
-
Memcg バックエンド非同期再利用: 制限に達する前に積極的にメモリを再利用し、直接再利用のブロックを回避します
-
Memcg グローバル最小ウォーターマーク評価: コンテナごとの再利用しきい値を調整し、遅延の影響を受けやすい (LS) コンテナが最後に再利用されるようにします
その結果、コンテナ間でより公平なメモリ分散が実現され、オーバーコミット時のアプリケーションのレイテンシが低減されます。
オープンソース Kubernetes メモリ QoS に対する利点
アップストリーム Kubernetes の メモリ QoS 機能は Kubernetes 1.22 以降でサポートされており、cgroup v2 のみをサポートし、手動の kubelet 構成が必要です。これはクラスター内のすべての Pod とノードに適用され、Podごとまたは名前空間ごとの詳細な構成はサポートしていません。
ack-koordinator メモリ QoS 機能は、2つの主要な点でアップストリームの実装を改善しています。
-
より広範なカーネル互換性: cgroup v1 と cgroup v2 の両方のインターフェイスをサポートし、Memcg バックエンド非同期再利用や最小ウォーターマーク評価などの Alibaba Cloud Linux カーネル機能によって支えられています。詳細については、「カーネル機能とインターフェイスの概要」をご参照ください。
-
詳細な構成: Pod アノテーションまたは ConfigMap を使用して、特定の Pod、名前空間、またはクラスター全体のメモリ QoS を個別に構成します。
構成メカニズム
ack-koordinator は、4つの cgroup パラメーターを使用してメモリ QoS ポリシーを適用します。次の表は、各パラメーターが「高度なパラメーター」で説明されている構成オプションにどのようにマッピングされるかを示しています。
| cgroup パラメーター | 制御 | 設定元 |
|---|---|---|
memory.limit_in_bytes |
コンテナの厳密な上限 | Kubernetes (limits.memory から) |
memory.high |
スロットリングしきい値 — ここから再利用が開始されます | throttlingPercent |
memory.wmark_high |
非同期再利用トリガー | wmarkRatio |
memory.min |
解放できないメモリの下限 | minLimitPercent / lowLimitPercent |
構成の優先度
複数の構成ソースが同じ Pod に適用される場合、ack-koordinator は次の優先順位 (最も高いものが最初) を使用します。
-
Pod アノテーション (
koordinator.sh/memoryQOS) -
名前空間レベルの ConfigMap (
ack-slo-pod-config) -
クラスターレベルの ConfigMap (
ack-slo-config)
QoS クラスマッピング
Pod に koordinator.sh/qosClass ラベルがない場合、ack-koordinator は Kubernetes QoS クラスから自動的にマッピングします。
| Kubernetes QoS クラス | koordinator QoS クラス |
|---|---|
| Guaranteed | デフォルトのメモリ QoS 設定 |
| Burstable | LS (遅延の影響を受けやすい) |
| BestEffort | BE (ベストエフォート) |
前提条件
開始する前に、以下を確認してください。
-
Kubernetes 1.18 以降を実行している ACK クラスター。アップグレードについては、「ACK クラスターの手動更新」をご参照ください。
-
ノード OS として Alibaba Cloud Linux。一部の高度なパラメーターは Alibaba Cloud Linux カーネル機能に依存します。詳細については、「高度なパラメーター」をご参照ください。
-
ack-koordinator 0.8.0 以降がインストールされていること。インストール手順については、「ack-koordinator」をご参照ください。
特定の Pod のメモリ QoS を有効にする
Pod スペックに次のアノテーションを追加します。
annotations:
# Enable memory QoS with recommended settings
koordinator.sh/memoryQOS: '{"policy": "auto"}'
# Disable memory QoS
# koordinator.sh/memoryQOS: '{"policy": "none"}'
クラスターのメモリ QoS を有効にする
ack-slo-config ConfigMap を使用して、クラスター内のすべての Pod にメモリ QoS を適用します。
-
configmap.yamlという名前のファイルを作成し、次の内容を記述します。apiVersion: v1 kind: ConfigMap metadata: name: ack-slo-config namespace: kube-system data: resource-qos-config: |- { "clusterStrategy": { "lsClass": { "memoryQOS": { "enable": true } }, "beClass": { "memoryQOS": { "enable": true } } } } -
koordinator.sh/qosClassラベルを使用して、各 Pod の QoS クラスを設定します。apiVersion: v1 kind: Pod metadata: name: pod-demo labels: koordinator.sh/qosClass: 'LS' -
ConfigMap を適用します。
-
ack-slo-configがkube-systemにすでに存在する場合は、関連のない設定を上書きしないように更新します: ``bash kubectl patch cm -n kube-system ack-slo-config --patch "$(cat configmap.yaml)"`` -
存在しない場合は、作成します: ``
bash kubectl apply -f configmap.yaml``
-
-
(オプション) 「高度なパラメーター」を構成します。
名前空間のメモリ QoS を有効にする
ack-slo-pod-config ConfigMap を使用して、特定の名前空間内の Pod のメモリ QoS を有効化または無効化します。
-
ack-slo-pod-config.yamlという名前のファイルを作成し、次の内容を記述します。apiVersion: v1 kind: ConfigMap metadata: name: ack-slo-pod-config namespace: kube-system data: memory-qos: | { "enabledNamespaces": ["allow-ns"], "disabledNamespaces": ["block-ns"] }allow-nsとblock-nsを実際の名前空間名に置き換えます。 -
ConfigMap を適用します。
kubectl patch cm -n kube-system ack-slo-pod-config --patch "$(cat ack-slo-pod-config.yaml)" -
(オプション) 「高度なパラメーター」を構成します。
例: メモリオーバーコミット下の Redis
この例では、ノードのメモリがオーバーコミットされたときに、メモリ QoS が Redis のレイテンシをどのように削減し、スループットを向上させるかを示します。テストでは以下を使用します。
-
8 vCPU と 32 GB のメモリを持つ 2つのノードを備えた ACK Pro マネージドクラスター
-
1つのノードで Redis ワークロードを実行し、もう1つのノードでストレステストを実行
テストの実行
-
redis-demo.yamlという名前のファイルを作成します。apiVersion: v1 kind: ConfigMap metadata: name: redis-demo-config data: redis-config: | appendonly yes appendfsync no --- apiVersion: v1 kind: Pod metadata: name: redis-demo labels: koordinator.sh/qosClass: 'LS' annotations: koordinator.sh/memoryQOS: '{"policy": "auto"}' spec: containers: - name: redis image: redis:5.0.4 command: - redis-server - "/redis-master/redis.conf" env: - name: MASTER value: "true" ports: - containerPort: 6379 resources: limits: cpu: "2" memory: "6Gi" requests: cpu: "2" memory: "2Gi" volumeMounts: - mountPath: /redis-master-data name: data - mountPath: /redis-master name: config volumes: - name: data emptyDir: {} - name: config configMap: name: redis-demo-config items: - key: redis-config path: redis.conf nodeName: # Set to the name of the node running Redis. --- apiVersion: v1 kind: Service metadata: name: redis-demo spec: ports: - name: redis-port port: 6379 protocol: TCP targetPort: 6379 selector: name: redis-demo type: ClusterIP -
Redis をデプロイします。
kubectl apply -f redis-demo.yaml -
Stress ツールを使用してメモリオーバーコミットをシミュレートします。
stress-demo.yamlという名前のファイルを作成します。apiVersion: v1 kind: Pod metadata: name: stress-demo labels: koordinator.sh/qosClass: 'BE' annotations: koordinator.sh/memoryQOS: '{"policy": "auto"}' spec: containers: - args: - '--vm' - '2' - '--vm-bytes' - 11G - '-c' - '2' - '--vm-hang' - '2' command: - stress image: polinux/stress imagePullPolicy: Always name: stress restartPolicy: Always nodeName: # Set to the same node as redis-demo. -
ストレスワークロードをデプロイします。
kubectl apply -f stress-demo.yaml -
ベンチマークを実行する前に、グローバル最小ウォーターマークを確認します。
重要メモリオーバーコミットのシナリオでは、グローバル最小ウォーターマークが低いと、メモリ再利用の前に OOM キラーが実行されます。32 GB のノードの場合、この値を少なくとも 4,000,000 KB に設定してください。
cat /proc/sys/vm/min_free_kbytes期待される出力:
4000000 -
memtier-benchmark ツールをデプロイして、Redis Pod にリクエストを送信します。
apiVersion: v1 kind: Pod metadata: labels: name: memtier-demo name: memtier-demo spec: containers: - command: - memtier_benchmark - '-s' - 'redis-demo' - '--data-size' - '200000' - "--ratio" - "1:4" image: 'redislabs/memtier_benchmark:1.3.0' name: memtier restartPolicy: Never nodeName: # Set to the name of the node sending requests. -
ベンチマーク結果を確認します。
kubectl logs -f memtier-demo -
比較のために、両方の Pod でメモリ QoS を無効にしてテストを繰り返します。
apiVersion: v1 kind: Pod metadata: name: redis-demo labels: koordinator.sh/qosClass: 'LS' annotations: koordinator.sh/memoryQOS: '{"policy": "none"}' spec: ... --- apiVersion: v1 kind: Pod metadata: name: stress-demo labels: koordinator.sh/qosClass: 'BE' annotations: koordinator.sh/memoryQOS: '{"policy": "none"}'
テスト結果
次のデータは参考用です。実際の結果は、ご利用のクラスター構成とワークロードによって異なります。
| メトリック | メモリ QoS 無効 | メモリ QoS 有効 |
|---|---|---|
Latency-avg |
51.32 ms | 47.25 ms |
Throughput-avg |
149.0 MB/s | 161.9 MB/s |
メモリ QoS を有効にすると、メモリオーバーコミット下で Redis のレイテンシが 7.9% 削減され、スループットが 8.7% 向上しました。
高度なパラメーター
次の表に、Pod アノテーションまたは ack-slo-config ConfigMap で設定できる高度なパラメーターを示します。Pod アノテーションは ConfigMap 設定よりも優先されます。
<table> <thead> <tr> <td><p><b>パラメーター</b></p></td> <td><p><b>タイプ</b></p></td> <td><p><b>有効値</b></p></td> <td><p><b>説明</b></p></td> <td><p><b>Pod アノテーション</b></p></td> <td><p><b>ConfigMap</b></p></td> </tr> </thead> <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup> <tbody> <tr> <td><p><code>enable</code></p></td> <td><p>ブール値</p></td> <td> <ul> <li><p><code>true</code></p></li> <li><p><code>false</code></p></li> </ul></td> <td> <ul> <li><p><code>true</code>: クラスター内のすべてのコンテナに対してメモリ QoS を有効にします。コンテナの QoS クラスに対する推奨 memcg 設定が使用されます。</p></li> <li><p><code>false</code>: クラスター内のすべてのコンテナに対してメモリ QoS を無効にします。コンテナの QoS クラスに対する元の memcg 設定が復元されます。</p></li> </ul></td> <td><p><img></p></td> <td><p><img></p></td> </tr> <tr> <td><p><code>policy</code></p></td> <td><p>文字列</p></td> <td> <ul> <li><p><code>auto</code></p></li> <li><p><code>default</code></p></li> <li><p><code>none</code></p></li> </ul></td> <td> <ul> <li><p><code>auto</code>: Pod 内のコンテナに対してメモリ QoS を有効にし、推奨設定を使用します。推奨設定は ack-slo-pod-config ConfigMap で指定された設定よりも優先されます。</p></li> <li><p><code>default</code>: Pod が ack-slo-pod-config ConfigMap で指定された設定を継承することを指定します。</p></li> <li><p><code>none</code>: Pod に対してメモリ QoS を無効にします。関連する memcg 設定は元の設定に復元されます。元の設定は ack-slo-pod-config ConfigMap で指定された設定よりも優先されます。</p></li> </ul></td> <td><p><img></p></td> <td><p><img></p></td> </tr> <tr> <td><p><code>minLimitPercent</code></p></td> <td><p>整数</p></td> <td><p>0\~100</p></td> <td><p>単位: %。デフォルト値: <code>0</code>。デフォルト値は、このパラメーターが無効であることを示します。</p><p>このパラメーターは、Pod のメモリ要求における解放不可の割合を指定します。このパラメーターは、アプリケーションがページキャッシュに敏感なシナリオに適しています。このパラメーターを使用してファイルをキャッシュし、読み書き性能を最適化できます。詳細については、Alibaba Cloud Linux のトピック「<a href="https://www.alibabacloud.com/help/en/document_detail/169536.html#concept-2482889">cgroup v1 インターフェイスの Memcg QoS 機能</a>」をご参照ください。</p><p>解放不可のメモリ量は、次の数式に基づいて計算されます: <code>memory.min の値 = メモリ要求 × minLimitPercent の値 / 100</code>。たとえば、コンテナに対して <code>Memory Request=100MiB</code> および <code>minLimitPercent=100</code> を指定した場合、<code>memory.min の値は 104857600</code> になります。</p></td> <td><p><img></p></td> <td><p><img></p></td> </tr> <tr> <td><p><code>lowLimitPercent</code></p></td> <td><p>整数</p></td> <td><p>0\~100</p></td> <td><p>単位: %。デフォルト値: <code>0</code>。デフォルト値は、このパラメーターが無効であることを示します。</p><p>このパラメーターは、Pod のメモリ要求における比較的解放不可の割合を指定します。詳細については、Alibaba Cloud Linux のトピック「<a href="https://www.alibabacloud.com/help/en/document_detail/169536.html#concept-2482889">cgroup v1 インターフェイスの Memcg QoS 機能</a>」をご参照ください。</p><p>比較的解放不可のメモリ量は、次の数式に基づいて計算されます: <span><code>memory.low の値 = メモリ要求 × lowLimitPercent の値 / 100</code></span>。たとえば、コンテナに対して <span><code>Memory Request=100MiB</code></span> および <span><code>lowLimitPercent=100</code></span> を指定した場合、<span><code>memory.low の値は 104857600</code></span> になります。</p></td> <td><p><img></p></td> <td><p><img></p></td> </tr> <tr> <td><p><code>throttlingPercent</code></p></td> <td><p>整数</p></td> <td><p>0\~100</p></td> <td><p>単位: %。デフォルト値: <code>0</code>。デフォルト値は、このパラメーターが無効であることを示します。</p><p>このパラメーターは、コンテナのメモリ使用量とコンテナのメモリ制限の比率に対するメモリ速度制限しきい値を指定します。コンテナのメモリ使用量がメモリ速度制限しきい値を超えると、そのコンテナで使用されているメモリが解放されます。このパラメーターは、コンテナのメモリ過剰割り当てシナリオに適しています。このパラメーターを使用して、cgroups による OOM の発生を防止できます。詳細については、Alibaba Cloud Linux のトピック「<a href="https://www.alibabacloud.com/help/en/document_detail/169536.html#concept-2482889">cgroup v1 インターフェイスの Memcg QoS 機能</a>」をご参照ください。</p><p>メモリ使用量に対するメモリ速度制限しきい値は、次の数式に基づいて計算されます: <code>memory.high の値 = メモリ制限 × throttlingPercent の値 / 100</code>。たとえば、コンテナに対して <code>Memory Limit=100MiB</code> および <code>throttlingPercent=80</code> を指定した場合、<code>memory.high の値は 83886080 (80 MiB)</code> になります。</p></td> <td><p><img></p></td> <td><p><img></p></td> </tr> <tr> <td><p><code>wmarkRatio</code></p></td> <td><p>整数</p></td> <td><p>0\~100</p></td> <td><p>単位: %。デフォルト値: <code>95</code>。<code>0</code> の値は、このパラメーターが無効であることを示します。メモリ使用量が解放しきい値を超えると、memcg バックエンドの非同期解放機能がトリガーされます。</p><p>このパラメーターは、メモリ使用量からメモリ制限または <code>memory.high</code> の値への非同期メモリ解放しきい値を指定します。詳細については、Alibaba Cloud Linux のトピック「<a href="https://www.alibabacloud.com/help/en/document_detail/169535.html#task-2487938">Memcg バックエンドの非同期解放</a>」をご参照ください。</p><p>throttlingPercent が無効の場合、メモリ使用量に対するメモリ解放しきい値は、次の数式に基づいて計算されます: memory.wmark_high の値 = メモリ制限 × wmarkRatio / 100。throttlingPercent が有効の場合、メモリ使用量に対するメモリ解放しきい値は、次の数式に基づいて計算されます: <code>memory.wmark_high の値 = memory.high の値 × wmarkRatio / 100</code>。たとえば、コンテナに対して <code>Memory Limit=100MiB</code> および <code>wmarkRatio=95,throttlingPercent=80</code> を指定した場合、<code>memory.high で指定されたメモリ速度制限しきい値は 83886080 (80 MiB)</code>、メモリ解放比率 <code>memory.wmark_ratio は 95</code>、<code>memory.wmark_high で指定されたメモリ解放しきい値は 79691776 (76 MiB)</code> になります。</p></td> <td><p><img></p></td> <td><p><img></p></td> </tr> <tr> <td><p><code>wmarkMinAdj</code></p></td> <td><p>整数</p></td> <td><p>-25\~50</p></td> <td><p>単位: %。デフォルト値は、<code>LS</code> QoS クラスでは <code>-25</code>、<code>BE</code> QoS クラスでは <code>50</code> です。<code>0</code> の値は、このパラメーターが無効であることを示します。</p><p>このパラメーターは、コンテナに対するグローバル最小ウォーターマークの調整を指定します。負の値はグローバル最小ウォーターマークを低下させ、そのためコンテナのメモリ解放を遅らせます。正の値はグローバル最小ウォーターマークを増加させ、そのためコンテナのメモリ解放を早めます。詳細については、Alibaba Cloud Linux のトピック「<a href="https://www.alibabacloud.com/help/en/document_detail/169537.html#task-2492619">Memcg グローバル最小ウォーターマーク評価</a>」をご参照ください。</p><p>たとえば、QoS クラスが LS の Pod を作成した場合、このパラメーターのデフォルト設定は <code>memory.wmark_min_adj=-25</code> となり、これは Pod 内のコンテナの最小ウォーターマークが 25% 低下することを意味します。</p></td> <td><p><img></p></td> <td><p><img></p></td> </tr> </tbody> </table>
よくある質問
ack-koordinator にアップグレードした後も、ack-slo-manager のメモリ QoS 構成は有効ですか?
はい。ack-koordinator は、ack-slo-manager 0.8.0 以前で使用されていたアノテーションベースのプロトコルと下位互換性があります。
-
alibabacloud.com/qosClass— QoS クラスを設定します -
alibabacloud.com/memoryQOS— メモリ QoS を構成します
次の表は、各バージョンがサポートするプロトコルを示しています。
| コンポーネントバージョン | alibabacloud.com プロトコル | koordinator.sh プロトコル |
|---|---|---|
| ≥ 0.3.0 and < 0.8.0 | ✓ | × |
| ≥ 0.8.0 | ✓ | ✓ |
alibabacloud.com プロトコルの互換性サポートは、2023年7月30日に終了しました。構成を koordinator.sh プロトコルへ移行してください。
課金
ack-koordinator コンポーネントのインストールまたは使用には料金はかかりません。ただし、次のケースでは費用が発生する場合があります。
-
ノードリソース使用量: ack-koordinator はワーカーノードで実行される非管理コンポーネントです。インストール時に各モジュールのリソースリクエストを構成できます。
-
Prometheusメトリック: ack-koordinator の Prometheusメトリックを有効にし、Managed Service for Prometheus を使用する場合、メトリックはカスタムメトリックとして課金されます。この機能を有効にする前に、Managed Service for Prometheus の課金ルールを確認してください。使用量をモニターするには、「観測可能なデータ量と請求書の照会」をご参照ください。
次のステップ
-
カーネル機能とインターフェイスの概要 — ACK メモリ QoS に必要なカーネル機能
-
コンテナの CPU QoS を有効にする — 再利用されたリソースを制限および排除して、遅延の影響を受けやすいワークロードを保護します