ack-koordinator を使用して、遅延の影響を受けやすいコンテナのメモリを優先し、競合時の OOM エラーを削減します。
仕組み
Kubernetes は各 Pod にメモリリクエストとメモリリミットを割り当てます。メモリ負荷が高い状況では、次の 2 種類の障害モードが発生します。
-
コンテナレベルの負荷:コンテナのメモリ使用量 (ページキャッシュを含む) がリミットに近づくと、OS は memcg レベルの直接再利用をトリガーし、プロセスをブロックします。割り当てが再利用を上回ると、OOM エラーが発生して Pod が終了します。
-
ノードレベルの負荷:コンテナのメモリリミットの合計がノードの物理メモリを超えると、カーネルはコンテナ間で無差別にメモリを再利用し、パフォーマンスが低下し、OOM エラーがトリガーされる可能性があります。
ack-koordinator は、コンテナごとにメモリコントロールグループ (memcg) を設定することで、これら両方の問題に対処します。これには、3 つの Alibaba Cloud Linux (Alinux) カーネル機能が使用されます。
-
Memcg QoS:最小メモリ量をロックし、優先度の高いコンテナがワーキングセットを保持できるようにします。
-
Memcg バックエンド非同期再利用:リミットに達する前に積極的にメモリを再利用し、直接再利用によるブロッキングを回避します。
-
Memcg グローバル最小ウォーターマーク評価:コンテナごとの再利用しきい値を調整し、遅延の影響を受けやすい (LS) コンテナが最後に再利用されるようにします。
これにより、オーバーコミット時のメモリ配分がより公平になり、レイテンシーが低下します。
オープンソースの Kubernetes メモリ QoS に対する利点
アップストリームの Kubernetes の メモリ QoS 機能 (Kubernetes 1.22 以降) は cgroup v2 のみをサポートし、手動での kubelet 設定が必要で、Pod 単位または名前空間単位の粒度には対応していません。
ack-koordinator は、次の 2 つの点でアップストリームの実装を改善しています。
-
幅広いカーネル互換性:cgroup v1 と v2 をサポートし、memcg バックエンド非同期再利用や最小ウォーターマーク評価などの Alinux カーネル機能によって支えられています。詳細については、「カーネル機能とインターフェイスの概要」をご参照ください。
-
詳細な設定:Pod アノテーションまたは ConfigMap を通じて、Pod、名前空間、またはクラスターごとにメモリ QoS を設定できます。
設定メカニズム
ack-koordinator は、メモリ QoS に 4 つの cgroup パラメーターを使用します。それぞれが「詳細パラメーター」の設定オプションにマッピングされます。
| 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 以降を実行している Container Service for Kubernetes (ACK) クラスター。詳細については、「ACK クラスターの手動更新」をご参照ください。
-
ノード OS としての Alinux。一部の高度なパラメーターは Alinux カーネル機能に依存します。詳細については、「詳細パラメーター」をご参照ください。
-
ack-koordinator 0.8.0 以降がインストールされていること。詳細については、「ack-koordinator」をご参照ください。
特定の Pod のメモリ QoS の有効化
Pod 仕様に次のアノテーションを追加します。
annotations:
# 推奨設定でメモリ QoS を有効化
koordinator.sh/memoryQOS: '{"policy": "auto"}'
# メモリ 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 } } } } -
各 Pod の QoS クラスを
koordinator.sh/qosClassラベルで設定します。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 のレイテンシーを削減し、スループットを向上させる方法を示します。テストでは以下を使用します。
-
2 つのノード (それぞれ 8 vCPU、32 GB) を持つ 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: # 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: # redis-demo と同じノードに設定します。 -
ストレステストのワークロードをデプロイします。
kubectl apply -f stress-demo.yaml -
ベンチマークを実行する前に、グローバル最小ウォーターマークを確認します。
重要メモリオーバーコミットのシナリオでは、グローバル最小ウォーターマークが低いと、メモリ再利用の前に OOM killer が実行されます。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: # リクエストを送信するノードの名前に設定します。 -
ベンチマークの結果を確認します。
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 アノテーションが優先されます。
<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>: 推奨される memcg 設定ですべてのコンテナのメモリ QoS を有効にします。</p></li> <li><p><code>false</code>: すべてのコンテナのメモリ 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>: 推奨設定でメモリ QoS を有効にし、ack-slo-pod-config ConfigMap を上書きします。</p></li> <li><p><code>default</code>: ack-slo-pod-config ConfigMap から設定を継承します。</p></li> <li><p><code>none</code>: メモリ 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 のメモリリクエストの回収不能な割合。 これを使用して、ページキャッシュの影響を受けやすいアプリケーションのファイルをキャッシュします。 詳細については、「<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 のメモリリクエストの相対的に回収不能な割合。 詳細については、「<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>コンテナの使用量の制限値に対する比率としてのメモリ速度制限のしきい値。 超過すると、メモリが回収されます。 オーバーコミットのシナリオで cgroup レベルの OOM を防ぎます。 詳細については、「<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> に対する使用量の比率。 詳細については、「<a href="https://www.alibabacloud.com/help/en/document_detail/169535.html#task-2487938">Memcg バックエンドの非同期回収</a>」をご参照ください。 </p><p>throttlingPercent が無効な場合、数式は次のようになります: Value of memory.wmark_high = Memory limit × wmarkRatio/100。 throttlingPercent が有効な場合、数式は <code>Value of memory.wmark_high = Value of 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>コンテナごとのグローバル最小ウォーターマークを調整します。 負の値を指定すると回収が延期され、正の値を指定すると回収が早まります。 詳細については、「<a href="https://www.alibabacloud.com/help/en/document_detail/169537.html#task-2492619">Memcg グローバル最小ウォーターマーク評価</a>」をご参照ください。 </p><p>たとえば、LS Pod のデフォルトは <code>memory.wmark_min_adj=-25</code> で、最小ウォーターマークを 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 以上 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 の有効化 — 再利用されたリソースを制限および退避させて、遅延の影響を受けやすいワークロードを保護します