Kubernetesでは、リソースリクエストとコンテナーの制限を指定できます。 アプリケーションで使用可能なメモリは、ページキャッシュの再利用や他のアプリケーションによる過剰なメモリ消費など、さまざまな要因に依存します。 極端な場合、ノードのメモリ不足によりメモリ不足 (OOM) エラーが発生し、ノード上のアプリケーションのパフォーマンスが低下します。 ack-koordinatorコンポーネントは、コンテナーのメモリサービス品質 (QoS) 機能を提供します。 コンポーネントを使用して、ビジネス要件に基づいて異なるQoSクラスを異なるコンテナーに割り当てることができます。 これにより、公平なメモリ割り当てを確保しながら、QoSクラスの高いアプリケーションのメモリ要求に優先順位を付けることができます。
メモリQoS機能をよりよく理解して使用するために、Kubernetes公式ドキュメントのPod Quality of Service ClassesおよびAssign memory Resources To Containers and Podのトピックを最初に読むことをお勧めします。
機能紹介
なぜメモリQoS?
Kubernetesクラスターでポッドを効率的かつ安全に実行できるようにするため、Kubernetesではリソースリクエストとポッドの制限を指定できます。 次の図は、ポッドのメモリ要求と制限を示しています。
メモリ要求 (requests. Memory): ポッドのメモリ要求は、ポッドのスケジューリングプロセス中に有効になります。 システムは、ポッドのメモリ要求を満たすノードにポッドをスケジュールします。
メモリ制限 (requests. Memory): ポッドのメモリ制限により、ポッドがノードで使用できるメモリの量が制限されます。 cgroupファイルのmemory.limit_in_bytesパラメーターには、ポッドで使用できるメモリの上限を指定します。
コンテナのメモリ使用量は、コンテナのメモリ制限とノードのメモリ容量によって異なります。
コンテナーのメモリ制限: ページキャッシュを含め、コンテナーが使用するメモリの量がコンテナーのメモリ制限に達すると、ポッドに対してメモリ制御グループ (memcg) レベルの直接メモリ再利用がトリガーされます。 その結果、ポッド内のプロセスがブロックされます。 この場合、ポッドがメモリを再要求するよりも速い速度でメモリを申請すると、OOMエラーが発生し、ポッドは終了します。
ノードメモリ容量: コンテナのメモリ制限は、コンテナのメモリ要求よりも大きくすることができます。 複数のコンテナがノードにデプロイされている場合、コンテナのメモリ制限の合計がノードのメモリ容量を超える可能性があります。 ノード上の全体的なメモリ使用量が過度に高い場合、OSカーネルはコンテナからメモリを再利用することができる。 その結果、アプリケーションのパフォーマンスが低下します。 極端な場合、ノードのメモリ不足によりOOMエラーが発生し、アプリケーションが終了します。
機能の説明
アプリケーションのパフォーマンスとノードの安定性を向上させるために、ack-koordinatorは、さまざまなAlibaba Cloud Linuxカーネルバージョンで実行されるコンテナーのメモリQoS機能を提供します。 ack-koordinatorは、コンテナーの設定に基づいてmemcgを自動的に設定し、Memcg QoS、Memcgバックエンド非同期再利用、Memcgグローバル最小透かし評価などの他の機能を有効にします。 これにより、コンテナ間での公平なメモリスケジューリングを確保しながら、メモリ依存アプリケーションのパフォーマンスが最適化されます。
メモリ再利用とメモリロックポリシー
メモリQoS機能では、複数のcgroupパラメーターを設定する必要があります。
memory.limit_in_bytes: ポッドで使用できるメモリの上限。
memory.high: メモリ調整しきい値。 OSカーネルは、メモリ使用量がこの値を超えないようにメモリを再利用します。
memory.wma rk_high: メモリ再利用しきい値 (
wmarkRatio
) 。 再利用可能メモリに対して非同期再利用が実行され、メモリ使用量がしきい値を下回るようにします。memory.min: メモリロックしきい値。 絶対ロックしきい値 (
minLimitPercent
) と相対ロックしきい値 (lowLimitPercent
) を設定できます。
上記のパラメーターの詳細については、「詳細パラメーター」をご参照ください。
メモリQoS機能は、次の利点を提供します。
ポッドによって使用されるメモリがポッドのメモリ制限に到達しようとしている場合、memcgは特定のメモリ量に対して非同期再利用を実行します。 これは、ポッドによって使用されるすべてのメモリの再利用を防ぎ、したがって、直接メモリ再利用によって引き起こされるアプリケーションパフォーマンスへの悪影響を最小限に抑える。
メモリの再利用は、ポッド間でより公平に実行されます。 ノードで使用可能なメモリが不足すると、メモリ要求よりも多くのメモリを使用するポッドで最初にメモリ再利用が実行されます。 これにより、ポッドが大量のメモリを適用する場合に、ノード上に十分なメモリが確保されます。
システムがメモリを再利用すると、システムは、GuaranteedポッドやBurstableポッドなど、レイテンシに敏感な (LS) ポッドのメモリ要求に優先順位を付けます。
柔軟な構成とマルチ環境互換性
メモリQoS機能はKubernetes 1.22でサポートされ、cgroup v2のみをサポートします。 メモリQoSを有効にするには、手動でkubeletを設定する必要があります。 メモリQoSは、クラスター内のすべてのポッドとノードで有効になるため、詳細な設定はサポートされません。 オープンソースKubernetesが提供するメモリQoS機能と比較して、ack-koordinatorが提供するメモリQoS機能は、次の観点から最適化されています。
Alibaba Cloud Linuxに基づくmemcgバックエンド非同期リクラメーションや最小透かし評価などの高度な機能を提供し、cgroup v1およびcgroup v2インターフェイスと互換性があります。 Container Service For Kubernetes (ACK) のメモリQoS機能に必要なOSカーネル機能の詳細については、「カーネル機能とインターフェイスの概要」をご参照ください。
アノテーションまたはConfigMapsを使用して、特定のポッド、名前空間、またはクラスター内のコンテナのきめ細かいメモリQoSを簡単かつ柔軟に設定できます。
前提条件
次の要件を満たすACKクラスターが作成されます。
Kubernetesバージョン: 1.18以降。 ACKクラスターの更新方法の詳細については、「ACKクラスターの手動更新」をご参照ください。
OS: Alibaba Cloud Linux。 メモリQoS機能に必要な一部のパラメータは、Alibaba Cloud Linuxに依存しています。 詳細については、「高度なパラメーター」をご参照ください。
ack-koordinator 0.8.0以降がインストールされています。 詳細については、「ack-koordinator (FAK ack-slo-manager) 」をご参照ください。
課金
ack-koordinatorコンポーネントをインストールまたは使用する場合、料金はかかりません。 ただし、次のシナリオでは料金が請求される場合があります。
ack-koordinatorは、インストール後にワーカーノードリソースを占有する管理対象外のコンポーネントです。 コンポーネントのインストール時に、各モジュールが要求するリソースの量を指定できます。
既定では、ack-koordinatorは、リソースプロファイリングや細粒度スケジューリングなどの機能のモニタリングメトリックをPrometheusメトリックとして公開します。 ack-koordinatorのPrometheusメトリクスを有効にし、PrometheusのManaged Serviceを使用する場合、これらのメトリクスはカスタムメトリクスと見なされ、料金が課金されます。 料金は、クラスターのサイズやアプリケーションの数などの要因によって異なります。 Prometheusメトリクスを有効にする前に、Prometheusのマネージドサービスの課金トピックを読んで、カスタムメトリクスの無料クォータと課金ルールについて確認することをお勧めします。 リソース使用量を監視および管理する方法の詳細については、「観察可能なデータ量と請求書の照会」をご参照ください。
使用上の注意
ポッドのメモリQoS機能を有効にすると、指定された比率とポッドパラメータに基づいてcgroupパラメータが自動的に設定されます。 このセクションでは、特定のポッド、名前空間、またはクラスター内のコンテナーのメモリQoSを有効にする方法について説明します。
アノテーションを使用して特定のポッド内のコンテナのメモリQoSを有効にする
次のポッド注釈を使用して、特定のポッド内のコンテナのメモリQoSを有効にできます。
annotations:
# To enable memory QoS for the containers in a pod, set the value to auto.
koordinator.sh/memoryQOS: '{"policy": "auto"}'
# To disable memory QoS for the containers in a pod, set the value to none.
koordinator.sh/memoryQOS: '{"policy": "none"}'
ConfigMapsを使用して特定のクラスターのコンテナーのメモリQoSを有効にする
ConfigMapを設定して、特定のクラスター内のすべてのコンテナーのメモリQoSを有効にできます。 koordinator.sh/qosClass
ポッドラベルを使用して、アプリケーションの特性に基づいてメモリQoSパラメータを一元管理できます。 koordinator.sh/qosClass
ラベルの値をLS
またはBE
に設定した場合、メモリQoSを有効にするためのアノテーションは必要ありません。
次のサンプルConfigMapは、特定のクラスター内のコンテナーのメモリQoSを有効にする方法の例を示しています。
apiVersion: v1 data: resource-qos-config: |- { "clusterStrategy": { "lsClass": { "memoryQOS": { "enable": true } }, "beClass": { "memoryQOS": { "enable": true } } } } kind: ConfigMap metadata: name: ack-slo-config namespace: kube-system
ポッドYAMLテンプレートを使用して、QoSクラスを
LS
またはBE
に設定します。説明ポッドに
koordinator.sh/qosClass
ラベルがない場合、ack-koordinatorはポッドの元のQoSクラスに基づいてメモリQoSパラメーターを構成します。保証
ポッドには、デフォルトのメモリQoS設定が割り当てられます。 バースト可能ポッドには、LS
QoSクラスのデフォルトのメモリQoS設定が割り当てられます。 BestEffortポッドには、BE
QoSクラスのデフォルトのメモリQoS設定が割り当てられます。apiVersion: v1 kind: Pod metadata: name: pod-demo labels: koordinator.sh/qosClass: 'LS' # Set the QoS class of the pod to LS.
ack-slo-config
ConfigMapがkube-system
名前空間に存在するかどうかを確認します。ack-slo-config ConfigMapが存在する場合は、kubectl patchコマンドを実行してConfigMapを更新することを推奨します。 これにより、ConfigMapの他の設定の変更が回避されます。
kubectl patch cm -n kube-system ack-slo-config --patch "$(cat configmap.yaml)"
ack-slo-config ConfigMapが存在しない場合は、次のコマンドを実行してConfigMapを作成します。
kubectl apply -f configmap.yaml
必要に応じて、 詳細パラメーターを設定します。
ConfigMapsを使用して特定の名前空間のコンテナのメモリQoSを有効にする
特定の名前空間のLS
およびBE
QoSクラスのポッドのメモリQoSを有効または無効にする場合は、ConfigMapで名前空間を指定します。
次のサンプルConfigMapは、特定のクラスター内のコンテナーのメモリQoSを有効にする方法の例を示しています。
apiVersion: v1 data: resource-qos-config: |- { "clusterStrategy": { "lsClass": { "memoryQOS": { "enable": true } }, "beClass": { "memoryQOS": { "enable": true } } } } kind: ConfigMap metadata: name: ack-slo-config namespace: kube-system
ack-slo-pod-config.yamlという名前のファイルを作成し、次の内容をファイルにコピーします。
次のコードブロックは、kube-system名前空間のコンテナのメモリQoSを有効または無効にするために使用されます。
apiVersion: v1 kind: ConfigMap metadata: name: ack-slo-pod-config namespace: kube-system # You need to manually create the namespace during the first time. data: # Enable or disable memory QoS for containers in a specific namespace. memory-qos: | { "enabledNamespaces": ["allow-ns"], "disabledNamespaces": ["block-ns"] }
次のコマンドを実行して、ConfigMapを更新します。
kubectl patch cm -n kube-system ack-slo-pod-config --patch "$(cat ack-slo-pod-config.yaml)"
必要に応じて、 詳細パラメーターを設定します。
例:
このセクションでは、例としてRedisポッドを使用します。 次の条件を使用して、メモリオーバーコミットシナリオでメモリQoSを有効にする前とメモリQoSを有効にする後のポッドのレイテンシとスループットを比較します。
ACK Proクラスターが使用されます。
クラスターには2つのノードがあり、それぞれに8つのvCPUと32 GBのメモリがあります。 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' # Set the QoS class of the Redis pod to LS. annotations: koordinator.sh/memoryQOS: '{"policy": "auto"}' # Add this annotation to enable memory QoS. 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 nodeName to the name of the tested node. --- 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 Serverをデプロイします。
クラスター内からredis-demo Serviceにアクセスできます。
kubectl apply -f redis-demo.yaml
メモリのオーバーコミットメントをシミュレートします。
Stressツールを使用して、メモリの負荷を増やし、メモリの再利用をトリガーします。 ノード上のすべてのポッドのメモリ制限の合計が、ノードの物理メモリを超えています。
stress-demo.yamlという名前のファイルを作成し、次の内容をファイルにコピーします。
apiVersion: v1 kind: Pod metadata: name: stress-demo labels: koordinator.sh/qosClass: 'BE' # Set the QoS class of the Stress pod to BE. annotations: koordinator.sh/memoryQOS: '{"policy": "auto"}' # Add this annotation to enable memory QoS. 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 nodeName to the name of the tested node, which is the node on which the Redis pod is deployed.
次のコマンドを実行してstress-demoをデプロイします。
kubectl apply -f stress-demo.yaml
次のコマンドを実行して、ノードのグローバル最小透かしを照会します。
説明メモリのオーバーコミットシナリオでは、ノードのグローバル最小透かしが低い値に設定されている場合、メモリの再利用が実行される前であっても、ノード上のすべてのポッドに対してOOMキラーがトリガーされる可能性があります。 したがって、グローバル最小透かしを高い値に設定することを推奨します。 この例では、32 GiBのメモリを持つテスト済みノードのグローバル最小透かしが4,000,000 KBに設定されます。
cat /proc/sys/vm/min_free_kbytes
期待される出力:
4000000
次のYAMLテンプレートを使用して、テスト対象ノードにリクエストを送信するmemtier-benchmarkツールをデプロイします。
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 nodeName to the name of the node that is used to send requests.
次のコマンドを実行して、memtier-benchmarkからテスト結果を照会します。
kubectl logs -f memtier-demo
次のYAMLテンプレートを使用して、RedisポッドとStressポッドのメモリQoSを無効にします。 次に、ストレステストを再度実行し、結果を比較します。
apiVersion: v1 kind: Pod metadata: name: redis-demo labels: koordinator.sh/qosClass: 'LS' annotations: koordinator.sh/memoryQOS: '{"policy": "none"}' # Disable memory QoS. spec: ... --- apiVersion: v1 kind: Pod metadata: name: stress-demo labels: koordinator.sh/qosClass: 'BE' annotations: koordinator.sh/memoryQOS: '{"policy": "none"}' # Disable memory QoS.
分析結果
次の表に、メモリQoSが有効および無効の場合のストレステストの結果を示します。
無効: ポッドのメモリQoSポリシーが
none
に設定されています。有効: ポッドのメモリQoSポリシーが
auto
に設定され、推奨されるメモリQoS設定が使用されます。
次のテーブルのデータは参照だけのためです。 テスト環境で生成された実際のデータが優先されます。
メトリクス | 無効 | 有効 |
| 51.32 ms | 47.25 ms |
| 149.0 MB/s | 161.9 MB/s |
この表は、メモリQoSを有効にすると、Redisポッドのレイテンシが7.9% 削減され、Redisポッドのスループットが8.7% 増加することを示しています。 これは、メモリQoS機能がメモリオーバーコミットシナリオでアプリケーションのパフォーマンスを最適化できることを示しています。
高度なパラメーター
特定のポッドまたはクラスター内のコンテナーのメモリQoSを有効にできます。 ポッド注釈とConfigMapsの両方を使用してメモリQoSパラメータを設定する場合、ポッド注釈が優先されます。 メモリQoSを設定するポッド注釈が追加されていない場合、ack-koordinatorは特定の名前空間のConfigMapsからメモリQoSパラメータを取得します。 名前空間のConfigMapsに設定が存在しない場合、ack-koordinatorは指定されたクラスターのConfigMapsからメモリQoSパラメーターを取得します。
[アノテーション] 列と [ConfigMap] 列は、アノテーションとConfigMapを使用してパラメーターを設定できるかどうかを示します。 はサポートされ、はサポートされていません。
パラメーター | タイプ | 値の範囲 | 説明 | ポッド注釈 | 設定マップ |
| Boolean |
|
| ||
| String |
|
| ||
| Int | 0~100 | 単位: % 。 デフォルト値: このパラメータには、ポッドのメモリ要求の再生不可能な割合を指定します。 このパラメーターは、アプリケーションがページキャッシュに敏感なシナリオに適しています。 このパラメーターを使用してファイルをキャッシュし、読み書きのパフォーマンスを最適化できます。 詳細については、Alibaba Cloud Linuxのトピック「cgroup v1インターフェイスのMemcg QoS機能」をご参照ください。 再生不能メモリの量は、以下の式に基づいて計算される。 | ||
| Int | 0~100 | 単位: % 。 デフォルト値: このパラメータは、ポッドのメモリ要求のうち、再生不可能な割合を指定します。 詳細については、Alibaba Cloud Linuxのトピック「cgroup v1インターフェイスのMemcg QoS機能」をご参照ください。 相対的に再生不能なメモリの量は、以下の式に基づいて計算される。 | ||
| Int | 0~100 | 単位: % 。 デフォルト値: このパラメーターには、コンテナーのメモリ使用量とコンテナーのメモリ制限の比率のメモリスロットリングしきい値を指定します。 コンテナのメモリ使用量がメモリスロットリングしきい値を超えると、コンテナで使用されているメモリが再利用されます。 このパラメーターは、コンテナーメモリのオーバーコミットシナリオに適しています。 このパラメーターを使用すると、cgroupsがOOMをトリガーしないようにできます。詳細については、Alibaba Cloud Linuxのトピック「cgroup v1インターフェイスのMemcg QoS機能」をご参照ください。 メモリ使用量のメモリスロットリングしきい値は、次の式に基づいて計算されます。 | ||
| Int | 0~100 | 単位: % 。 デフォルト値: このパラメーターには、メモリ使用量からメモリ制限、またはメモリ使用量から throttlingPercentが無効になっている場合、メモリ使用量のメモリ再利用しきい値は、次の式に基づいて計算されます。memory.wma rk_high=メモリ制限 × wmarkRatio/100。 throttlingPercentが有効になっている場合、メモリ使用量のメモリ再利用しきい値は、次の式に基づいて計算されます。 | ||
| Int | -25 ~ 50 | 単位: % 。 デフォルト値は、 このパラメータは、コンテナのグローバル最小透かしの調整を指定します。 負の値は、グローバル最小透かしを減少させ、したがって、コンテナのメモリ再利用を延期する。 正の値は、グローバル最小透かしを増加させ、したがって、コンテナのメモリ再利用に先行する。 詳細については、Alibaba Cloud Linuxのトピック「Memcg global minimum watermark rating」をご参照ください。 たとえば、QoSクラスがLSであるポッドを作成する場合、このパラメーターのデフォルト設定は |
よくある質問
ack-slo-managerからack-koordinatorにアップグレードした後も、以前のバージョンのack-slo-managerプロトコルに基づいて有効になっているメモリQoS機能はサポートされますか?
以前のバージョン (≦ 0.8.0) のack-slo-managerプロトコルでは、次のポッド注釈が使用されます。
alibabacloud.com/qosClass
alibabacloud.com/memoryQOS
ack-koordinatorは、以前のバージョンのack-slo-managerプロトコルと互換性があります。 ack-slo-managerからack-koordinatorにシームレスにアップグレードできます。 ack-koordinatorは、2023年7月30日までの以前のプロトコルバージョンと互換性があります。 以前のプロトコルバージョンのリソースパラメーターを最新バージョンにアップグレードすることを推奨します。
次の表は、異なるバージョンのack-koordinatorとメモリQoS機能の互換性を示しています。
ack-koordinatorバージョン | alibabacloud.comプロトコル | koordinator.shプロトコル |
≥ 0.3.0および <0.8.0 | ✓ | × |
≥ 0.8.0 | ✓ | ✓ |