第8章 CPU マネージャーおよび Topology Manager の使用
CPU マネージャーは、CPU グループを管理して、ワークロードを特定の CPU に制限します。
CPU マネージャーは、以下のような属性が含まれるワークロードに有用です。
- できるだけ長い CPU 時間が必要な場合
- プロセッサーのキャッシュミスの影響を受ける場合
- レイテンシーが低いネットワークアプリケーションの場合
- 他のプロセスと連携し、単一のプロセッサーキャッシュを共有することに利点がある場合
Topology Manager は、CPU マネージャー、デバイスマネージャー、およびその他の Hint Provider からヒントを収集し、同じ Non-Uniform Memory Access (NUMA) ノード上のすべての QoS (Quality of Service) クラスについて CPU、SR-IOV VF、その他デバイスリソースなどの Pod リソースを調整します。
Topology Manager は、収集したヒントのトポロジー情報を使用し、設定される Topology Manager ポリシーおよび要求される Pod リソースに基づいて、pod がノードから許可されるか、拒否されるかどうかを判別します。
Topology Manager は、ハードウェアアクセラレーターを使用して低遅延 (latency-critical) の実行と高スループットの並列計算をサポートするワークロードの場合に役立ちます。
Topology Manager を使用するには、static
ポリシーで CPU マネージャーを設定する必要があります。
8.1. CPU マネージャーの設定
CPU マネージャーを設定するには、KubeletConfig カスタムリソース (CR) を作成し、それを目的のノードセットに適用します。
手順
次のコマンドを実行してノードにラベルを付けます。
# oc label node perf-node.example.com cpumanager=true
すべてのコンピュートノードに対して CPU マネージャーを有効にするには、次のコマンドを実行して CR を編集します。
# oc edit machineconfigpool worker
custom-kubelet: cpumanager-enabled
ラベルをmetadata.labels
セクションに追加します。metadata: creationTimestamp: 2020-xx-xxx generation: 3 labels: custom-kubelet: cpumanager-enabled
KubeletConfig
、cpumanager-kubeletconfig.yaml
、カスタムリソース (CR) を作成します。直前の手順で作成したラベルを参照し、適切なノードを新規の kubelet 設定で更新します。machineConfigPoolSelector
セクションを参照してください。apiVersion: machineconfiguration.openshift.io/v1 kind: KubeletConfig metadata: name: cpumanager-enabled spec: machineConfigPoolSelector: matchLabels: custom-kubelet: cpumanager-enabled kubeletConfig: cpuManagerPolicy: static 1 cpuManagerReconcilePeriod: 5s 2
次のコマンドを実行して、動的 kubelet 設定を作成します。
# oc create -f cpumanager-kubeletconfig.yaml
これにより、CPU マネージャー機能が kubelet 設定に追加され、必要な場合には Machine Config Operator (MCO) がノードを再起動します。CPU マネージャーを有効にするために再起動する必要はありません。
次のコマンドを実行して、マージされた kubelet 設定を確認します。
# oc get machineconfig 99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet -o json | grep ownerReference -A7
出力例
"ownerReferences": [ { "apiVersion": "machineconfiguration.openshift.io/v1", "kind": "KubeletConfig", "name": "cpumanager-enabled", "uid": "7ed5616d-6b72-11e9-aae1-021e1ce18878" } ]
次のコマンドを実行して、更新された
kubelet.conf
ファイルをコンピュートノードで確認します。# oc debug node/perf-node.example.com sh-4.2# cat /host/etc/kubernetes/kubelet.conf | grep cpuManager
出力例
cpuManagerPolicy: static 1 cpuManagerReconcilePeriod: 5s 2
次のコマンドを実行してプロジェクトを作成します。
$ oc new-project <project_name>
コア 1 つまたは複数を要求する Pod を作成します。制限および要求の CPU の値は整数にする必要があります。これは、対象の Pod 専用のコア数です。
# cat cpumanager-pod.yaml
出力例
apiVersion: v1 kind: Pod metadata: generateName: cpumanager- spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: cpumanager image: gcr.io/google_containers/pause:3.2 resources: requests: cpu: 1 memory: "1G" limits: cpu: 1 memory: "1G" securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] nodeSelector: cpumanager: "true"
Pod を作成します。
# oc create -f cpumanager-pod.yaml
検証
次のコマンドを実行して、ラベルを付けたノードに Pod がスケジュールされていることを確認します。
# oc describe pod cpumanager
出力例
Name: cpumanager-6cqz7 Namespace: default Priority: 0 PriorityClassName: <none> Node: perf-node.example.com/xxx.xx.xx.xxx ... Limits: cpu: 1 memory: 1G Requests: cpu: 1 memory: 1G ... QoS Class: Guaranteed Node-Selectors: cpumanager=true
次のコマンドを実行して、CPU が Pod 専用として割り当てられていることを確認します。
# oc describe node --selector='cpumanager=true' | grep -i cpumanager- -B2
出力例
NAMESPACE NAME CPU Requests CPU Limits Memory Requests Memory Limits Age cpuman cpumanager-mlrrz 1 (28%) 1 (28%) 1G (13%) 1G (13%) 27m
cgroups
が正しく設定されていることを確認します。次のコマンドを実行して、pause
プロセスのプロセス ID (PID) を取得します。# oc debug node/perf-node.example.com
sh-4.2# systemctl status | grep -B5 pause
注記出力で複数の pause プロセスエントリーが返される場合は、正しい一時停止プロセスを特定する必要があります。
出力例
# ├─init.scope │ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 17 └─kubepods.slice ├─kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice │ ├─crio-b5437308f1a574c542bdf08563b865c0345c8f8c0b0a655612c.scope │ └─32706 /pause
次のコマンドを実行して、サービス品質 (QoS) 層 (
Guaranteed
) の Pod がkubepods.slice
サブディレクトリー内に配置されていることを確認します。# cd /sys/fs/cgroup/kubepods.slice/kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice/crio-b5437308f1ad1a7db0574c542bdf08563b865c0345c86e9585f8c0b0a655612c.scope
# for i in `ls cpuset.cpus cgroup.procs` ; do echo -n "$i "; cat $i ; done
注記他の QoS 階層の Pod は、親
kubepods
の子であるcgroups
に配置されます。出力例
cpuset.cpus 1 tasks 32706
次のコマンドを実行して、タスクに許可されている CPU リストを確認します。
# grep ^Cpus_allowed_list /proc/32706/status
出力例
Cpus_allowed_list: 1
システム上の別の Pod が、
Guaranteed
Pod に割り当てられたコアで実行できないことを確認します。たとえば、besteffort
QoS 階層の Pod を検証するには、次のコマンドを実行します。# cat /sys/fs/cgroup/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podc494a073_6b77_11e9_98c0_06bba5c387ea.slice/crio-c56982f57b75a2420947f0afc6cafe7534c5734efc34157525fa9abbf99e3849.scope/cpuset.cpus
# oc describe node perf-node.example.com
出力例
... Capacity: attachable-volumes-aws-ebs: 39 cpu: 2 ephemeral-storage: 124768236Ki hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 8162900Ki pods: 250 Allocatable: attachable-volumes-aws-ebs: 39 cpu: 1500m ephemeral-storage: 124768236Ki hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 7548500Ki pods: 250 ------- ---- ------------ ---------- --------------- ------------- --- default cpumanager-6cqz7 1 (66%) 1 (66%) 1G (12%) 1G (12%) 29m Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 1440m (96%) 1 (66%)
この仮想マシンには、2 つの CPU コアがあります。
system-reserved
設定は 500 ミリコアを予約し、Node Allocatable
の量になるようにノードの全容量からコアの半分を引きます。ここでAllocatable CPU
は 1500 ミリコアであることを確認できます。これは、それぞれがコアを 1 つ受け入れるので、CPU マネージャー Pod の 1 つを実行できることを意味します。1 つのコア全体は 1000 ミリコアに相当します。2 つ目の Pod をスケジュールしようとする場合、システムは Pod を受け入れますが、これがスケジュールされることはありません。NAME READY STATUS RESTARTS AGE cpumanager-6cqz7 1/1 Running 0 33m cpumanager-7qc2t 0/1 Pending 0 11s