シリーズ最終回に向けて
Part 1ではコンテナランタイムとcgroupsの基礎、Part 2ではネットワークスタックとeBPFによる可観測性を取り上げた。最終回となるPart 3では、大規模クラスタ運用において最も見落とされがちなレイヤ──CPUアーキテクチャとカーネルチューニング──に踏み込む。ここを押さえることで、スループットとレイテンシの両面で劇的な改善が見込める。
NUMAアーキテクチャとコンテナスケジューリング
現代のサーバーCPUはNUMA(Non-Uniform Memory Access)構成を採用している。ソケット間のメモリアクセスはローカルアクセスと比較して2倍以上のレイテンシが発生するケースがある [Source: https://www.kernel.org/doc/html/latest/admin-guide/mm/numa_memory_policy.html]。Kubernetesのデフォルト設定ではNUMAトポロジーを意識しないため、レイテンシクリティカルなワークロードではTopologyManagerを有効化する必要がある。
# kubelet設定例 (kubelet-config.yaml) apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration topologyManagerPolicy: single-numa-node topologyManagerScope: pod cpuManagerPolicy: static single-numa-nodeポリシーを指定することで、Podのすべてのリソース(CPU・メモリ・デバイス)を単一のNUMAノードに固定できる。ただしリソース断片化が発生しやすいため、Guaranteed QoSクラスのPodにのみ適用するのが現実的だ。
ARM vs x86: マルチアーキテクチャ運用の現実
AWS Graviton3やAmpere Altraの普及に伴い、x86とARMが混在するクラスタが増えている。コンテナイメージはアーキテクチャ固有のバイナリを含むため、docker manifestによるマルチプラットフォームイメージのビルドが不可欠だ [Source: https://docs.docker.com/build/building/multi-platform/]。
# BuildKitによるマルチアーキテクチャビルド docker buildx create --use --name multi-builder docker buildx build \ --platform linux/amd64,linux/arm64 \ --tag myregistry/myapp:latest \ --push . KubernetesではNodeのkubernetes.io/archラベルを使い、ワークロードを適切なアーキテクチャに配置できる。
affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - arm64 ARM向けにコンパイルされたGoバイナリは、同等のx86バイナリと比較してCPU効率が向上するケースが多い。ただしサードパーティライブラリのARM対応状況は事前に確認が必要だ。
カーネルパラメータの実践的チューニング
大規模コンテナ環境では以下のカーネルパラメータが特に影響を与える。
# /etc/sysctl.d/99-container-tuning.conf # 接続キューのバックログを増やす net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 # TIME_WAIT状態のソケット再利用 net.ipv4.tcp_tw_reuse = 1 # ファイルディスクリプタ上限 fs.file-max = 2097152 # inotifyウォッチャー数(ログ収集エージェント向け) fs.inotify.max_user_watches = 1048576 fs.inotify.max_user_instances = 8192 # 透過的ヒュージページの無効化(レイテンシ安定化) vm.nr_hugepages = 0 透過的ヒュージページ(THP)はスループット重視のワークロードには有効だが、Redisなどのインメモリデータストアではレイテンシのスパイクを引き起こすことが知られている。用途に応じた設定が求められる。
cgroups v2によるリソース制御の精緻化
Linuxカーネル5.8以降でcgroups v2が安定版となり、メモリ・CPU・I/Oの統合的な制御が可能になった。特にPSI(Pressure Stall Information)メトリクスはリソース競合の早期検知に有効だ。
# PSIメトリクスの確認 cat /sys/fs/cgroup/kubepods/pod<UID>/memory.pressure # 出力例: # some avg10=0.12 avg60=0.05 avg300=0.01 total=12345678 # full avg10=0.00 avg60=0.00 avg300=0.00 total=0 someはいずれかのタスクが待機している割合、fullはすべてのタスクが待機している割合を示す。これをPrometheusで収集し、full avg60 > 5をアラート閾値とする運用が実績ある手法だ。
シリーズ総括
3回にわたってコンテナ大規模運用の技術的基盤を掘り下げてきた。要点を整理する。
- Part 1: cgroups・namespaceによるプロセス分離の仕組みとランタイムの選択
- Part 2: CNIプラグインとeBPFを活用したネットワーク可観測性
- Part 3: NUMAトポロジー、マルチアーキテクチャ対応、カーネルパラメータとcgroups v2
インフラの複雑性は増す一方だが、各レイヤの原理を理解することで障害の根本原因特定と性能改善が格段に容易になる。AIツールを活用したコードレビューや自動化が普及する現在においても、低レイヤの知識はエンジニアの差別化要因であり続ける。次の技術的挑戦に向けて、本シリーズが実践的な足がかりとなれば幸いだ。
Category: 開発 | Tags: kubernetes, linux, container
0 件のコメント:
コメントを投稿