Kubernetes では、コンテナーのリソースリクエストと制限を指定できます。アプリケーションで使用可能なメモリは、ページキャッシュの再利用や他のアプリケーションによる過剰なメモリ消費など、さまざまな要因によって異なります。極端なケースでは、ノードのメモリ不足が原因でメモリ不足 (OOM) エラーが発生し、ノード上のアプリケーションのパフォーマンスが低下します。ack-koordinator コンポーネントは、コンテナーのメモリ QoS (Quality of Service) 機能を提供します。このコンポーネントを使用すると、ビジネス要件に基づいて異なるコンテナーに異なる QoS クラスを割り当てることができます。これにより、メモリ割り当ての公平性を確保しながら、QoS クラスが高いアプリケーションのメモリリクエストを優先させることができます。
メモリ QoS 機能について理解し、使用するために、まず Kubernetes 公式ドキュメントの次のトピックをお読みになることをお勧めします。ポッドのサービス品質クラス および コンテナーとポッドへのメモリリソースの割り当て。
機能紹介
メモリ QoS の理由
ポッドが Kubernetes クラスターで効率的かつ安全に実行できるように、Kubernetes ではポッドのリソースリクエストと制限を指定できます。次の図は、ポッドのメモリリクエストと制限を示しています。
メモリリクエスト (requests.memory): ポッドのメモリリクエストは、ポッドのスケジューリングプロセス中に有効になります。システムは、ポッドのメモリリクエストを満たすノードにポッドをスケジュールします。
メモリ制限 (requests.memory): ポッドのメモリ制限は、ポッドがノードで使用できるメモリの量を制限します。cgroup ファイルの memory.limit_in_bytes パラメーターは、ポッドが使用できるメモリーの上限を指定します。
コンテナーのメモリ使用量は、コンテナーのメモリ制限とノードのメモリ容量によって異なります。
コンテナーのメモリ制限: コンテナーが使用するメモリの量がページキャッシュを含めてコンテナーのメモリ制限に達しようとしている場合、ポッドに対して memcg (メモリ コントロール グループ) レベルの直接メモリ再利用がトリガーされます。その結果、ポッド内のプロセスがブロックされます。この場合、ポッドがメモリを再利用するよりも速い速度でメモリを申請すると、OOM エラーが発生し、ポッドは終了します。
ノードのメモリ容量: コンテナーのメモリ制限は、コンテナーのメモリリクエストよりも大きくなる可能性があります。複数のコンテナーが 1 つのノードにデプロイされている場合、コンテナーのメモリ制限の合計がノードのメモリ容量を超える可能性があります。ノード全体のメモリ使用量が過度に高い場合、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.wmark_high: メモリ再利用のしきい値 (
wmarkRatio)。再利用可能なメモリに対して非同期再利用が実行され、メモリ使用量がしきい値を下回るようにします。memory.min: メモリロックのしきい値。絶対ロックしきい値 (
minLimitPercent) と相対ロックしきい値 (lowLimitPercent) を構成できます。
上記のパラメーターの詳細については、「詳細パラメーター」をご参照ください。
メモリ QoS 機能には、次の利点があります。
ポッドが使用するメモリがポッドのメモリ制限に達しようとしている場合、memcg は特定量のメモリに対して非同期再利用を実行します。これにより、ポッドで使用されるすべてのメモリの再利用を防ぎ、直接メモリ再利用によって引き起こされるアプリケーション パフォーマンスへの悪影響を最小限に抑えます。
ポッド間でより公平にメモリ再利用が実行されます。ノードで使用可能なメモリが不足すると、まずメモリリクエストよりも多くのメモリを使用しているポッドに対してメモリ再利用が実行されます。これにより、ポッドが大量のメモリを申請する場合に、ノードに十分なメモリが確保されます。
システムがメモリを再利用する場合、システムは Guaranteed ポッドと Burstable ポッドを含む、LS (Latency-Sensitive) ポッドのメモリリクエストを優先します。
柔軟な構成とマルチ環境互換性
メモリ 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 カーネル機能の詳細については、「カーネル機能とインターフェースの概要」をご参照ください。
アノテーションまたは ConfigMap を使用して、特定のポッド、名前空間、またはクラスター内のコンテナーに対して、簡単かつ柔軟にきめ細かいメモリ 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 メトリックを有効にする と、Managed Service for Prometheus を使用する場合、これらのメトリックは カスタムメトリック と見なされ、これらのメトリックに対して料金が発生します。料金は、クラスターのサイズやアプリケーションの数などの要因によって異なります。Prometheus メトリックを有効にする前に、Managed Service for Prometheus の 課金 に関するトピックを読み、カスタムメトリックの無料枠と課金ルールについて理解することをお勧めします。リソース使用量の監視と管理方法の詳細については、「監視対象データ量と料金をクエリする」をご参照ください。
使用上の注意
ポッドのメモリ QoS 機能を有効にすると、指定された比率とポッドパラメーターに基づいて cgroup パラメーターが自動的に構成されます。このセクションでは、特定のポッド、名前空間、またはクラスター内のコンテナーのメモリ QoS を有効にする方法について説明します。
アノテーションを使用して特定のポッド内のコンテナーのメモリ QoS を有効にする
次のポッドアノテーションを使用して、特定のポッド内のコンテナーのメモリ QoS を有効にすることができます。
annotations:
# ポッド内のコンテナーのメモリ QoS を有効にするには、値を auto に設定します。
koordinator.sh/memoryQOS: '{"policy": "auto"}'
# ポッド内のコンテナーのメモリ QoS を無効にするには、値を none に設定します。
koordinator.sh/memoryQOS: '{"policy": "none"}'ConfigMap を使用して特定のクラスター内のコンテナーのメモリ QoS を有効にする
koordinator.sh/qosClass ポッドラベルを使用して ConfigMap を構成し、アプリケーションの特性に基づいてメモリ 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 パラメーターを構成します。Guaranteedポッドには、デフォルトのメモリ QoS 設定が割り当てられます。Burstable ポッドには、LSQoS クラスのデフォルトのメモリ QoS 設定が割り当てられます。BestEffort ポッドには、BEQoS クラスのデフォルトのメモリ QoS 設定が割り当てられます。apiVersion: v1 kind: Pod metadata: name: pod-demo labels: koordinator.sh/qosClass: 'LS' # ポッドの QoS クラスを LS に設定します。kube-system名前空間にack-slo-configConfigMap が存在するかどうかを確認します。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
オプション。詳細パラメーター を構成します。
ConfigMap を使用して特定の名前空間内のコンテナーのメモリ 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-systemack-slo-pod-config.yaml という名前のファイルを作成し、次の内容をファイルにコピーします。
次のコードブロックは、kube-system 名前空間内のコンテナーのメモリ QoS を有効または無効にするために使用されます。
apiVersion: v1 kind: ConfigMap metadata: name: ack-slo-pod-config namespace: kube-system # 初回は名前空間を手動で作成する必要があります。 data: # 特定の名前空間内のコンテナーのメモリ QoS を有効または無効にします。 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 を有効にする前と有効にした後でのポッドのレイテンシとスループットを比較するために、次の条件を使用します。
ACK Pro マネージドクラスター が使用されます。
クラスターには 2 つのノードが含まれており、各ノードには 8 個の vCPU と 32 GB のメモリがあります。1 つのノードはストレステストを実行するために使用されます。もう 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' # Redis ポッドの QoS クラスを LS に設定します。 annotations: koordinator.sh/memoryQOS: '{"policy": "auto"}' # このアノテーションを追加してメモリ 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: # nodeName をテスト対象ノードの名前に設定します。 --- 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 サーバーをデプロイします。
クラスター内から redis-demo サービスにアクセスできます。
kubectl apply -f redis-demo.yamlメモリオーバーコミットをシミュレートします。
Stress ツールを使用してメモリへの負荷を増加させ、メモリ再利用をトリガーします。ノード上のすべてのポッドのメモリ制限の合計が、ノードの物理メモリを超えています。
stress-demo.yaml という名前のファイルを作成し、次の内容をファイルにコピーします。
apiVersion: v1 kind: Pod metadata: name: stress-demo labels: koordinator.sh/qosClass: 'BE' # Stress ポッドの QoS クラスを BE に設定します。 annotations: koordinator.sh/memoryQOS: '{"policy": "auto"}' # このアノテーションを追加してメモリ 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: # nodeName をテスト対象ノードの名前に設定します。これは、Redis ポッドがデプロイされているノードです。次のコマンドを実行して 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: # nodeName をリクエストを送信するために使用されるノードの名前に設定します。次のコマンドを実行して、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"}' # メモリ QoS を無効にします。 spec: ... --- apiVersion: v1 kind: Pod metadata: name: stress-demo labels: koordinator.sh/qosClass: 'BE' annotations: koordinator.sh/memoryQOS: '{"policy": "none"}' # メモリ 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% 削減され、スループットが 8.7% 向上し、すべてのメトリックが大幅に改善されることを示しています。
詳細パラメーター
特定のポッドまたはクラスター内のコンテナーのメモリ QoS を有効にすることができます。ポッドアノテーションと ConfigMap の両方を使用してメモリ QoS パラメーターを構成する場合、ポッドアノテーションが優先されます。メモリ QoS を構成するためのポッドアノテーションが追加されていない場合、ack-koordinator は特定の名前空間の ConfigMap からメモリ QoS パラメーターを取得します。名前空間の ConfigMap に構成が存在しない場合、ack-koordinator は指定されたクラスターの ConfigMap からメモリ QoS パラメーターを取得します。
アノテーション 列と ConfigMap 列は、アノテーションと ConfigMap を使用してパラメーターを構成できるかどうかを示します。
はサポートされていることを示し、
はサポートされていないことを示します。
パラメーター | タイプ | 有効値 | 説明 | ポッドアノテーション | ConfigMap |
| ブール値 |
|
|
|
|
| 文字列 |
|
|
|
|
| 整数 | 0~100 | 単位: %。デフォルト値: このパラメーターは、ポッドのメモリリクエストの再利用不可能な割合を指定します。このパラメーターは、アプリケーションがページキャッシュの影響を受けやすいシナリオに適しています。このパラメーターを使用して、ファイルを読み書きパフォーマンスを最適化するためにキャッシュできます。詳細については、Alibaba Cloud Linux のトピック cgroup v1 インターフェースの Memcg QoS 機能 をご参照ください。 再利用不可能なメモリの量は、次の式に基づいて計算されます。 |
|
|
| 整数 | 0~100 | 単位: %。デフォルト値: このパラメーターは、ポッドのメモリリクエストの相対的に再利用不可能な割合を指定します。詳細については、Alibaba Cloud Linux のトピック cgroup v1 インターフェースの Memcg QoS 機能 をご参照ください。 相対的に再利用不可能なメモリの量は、次の式に基づいて計算されます。 |
|
|
| 整数 | 0~100 | 単位: %。デフォルト値: このパラメーターは、コンテナーのメモリ使用量のコンテナーのメモリ制限に対する比率のメモリ調整のしきい値を指定します。コンテナーのメモリ使用量がメモリ調整のしきい値を超えると、コンテナーで使用されているメモリが再利用されます。このパラメーターは、コンテナーのメモリオーバーコミットシナリオに適しています。このパラメーターを使用して、cgroup が OOM をトリガーするのを防ぐことができます。詳細については、Alibaba Cloud Linux のトピック cgroup v1 インターフェースの Memcg QoS 機能 をご参照ください。 メモリ使用量のメモリ調整のしきい値は、次の式に基づいて計算されます。 |
|
|
| 整数 | 0~100 | 単位: %。デフォルト値: このパラメーターは、メモリ使用量のメモリ制限に対する比率、またはメモリ使用量の throttlingPercent が無効になっている場合、メモリ使用量のメモリ再利用のしきい値は、次の式に基づいて計算されます。memory.wmark_high の値 = メモリ制限 × wmarkRatio / 100。throttlingPercent が有効になっている場合、メモリ使用量のメモリ再利用のしきい値は、次の式に基づいて計算されます。 |
|
|
| 整数 | -25~50 | 単位: %。 このパラメーターは、コンテナーのグローバル最小ウォーターマークへの調整を指定します。負の値はグローバル最小ウォーターマークを減少させるため、コンテナーのメモリ再利用が延期されます。正の値はグローバル最小ウォーターマークを増加させるため、コンテナーのメモリ再利用が早まります。詳細については、Alibaba Cloud Linux のトピック Memcg グローバル最小ウォーターマークレーティング をご参照ください。 たとえば、QoS クラスが LS のポッドを作成する場合、このパラメーターのデフォルト設定は |
|
|
よくある質問
ack-slo-manager から ack-koordinator にアップグレードした後も、ack-slo-manager プロトコルのレガシーバージョンに基づいて有効になっているメモリ QoS 機能は引き続きサポートされますか?
ack-slo-manager バージョン 0.8.0 以前では、次のポッド構成が使用されます。
ポッドアノテーション
alibabacloud.com/qosClassを使用して QoS クラスを定義するポッドアノテーション
alibabacloud.com/memoryQOSを使用してメモリ QoS を構成する
ack-koordinator は、ack-slo-manager で使用されるこれらのアノテーションベースのプロトコルとの下位互換性を維持しています。ack-slo-manager から ack-koordinator にシームレスにアップグレードできます。ただし、互換性サポートは 2023 年 7 月 30 日に終了します。リソースパラメーターを新しいパラメーターに移行することをお勧めします。
次の表は、異なるコンポーネントバージョンとメモリ QoS 機能間の互換性を示しています。
コンポーネントバージョン | alibabacloud.com プロトコル | koordinator.sh プロトコル |
≥ 0.3.0 and < 0.8.0 | ✓ | × |
≥ 0.8.0 | ✓ | ✓ |