Skip to main content

HPAがサイドカーの分まで合算してスケールしていた。KubernetesのContainerResourceという盲点

1. HPAの「利用率」は、サイドカーの分まで含んで計算されている

section01

KubernetesのHPA(HorizontalPodAutoscaler)を運用していて、「CPU使用率がしきい値を超えているはずなのにスケールしない」「逆に思ったより早くスケールアウトする」と感じたことはないだろうか。原因の多くは、HPAの標準的なResourceメトリクスがPod内の全コンテナの使用量を合算して利用率を計算している、という仕様そのものにある。

標準のResourceメトリクスは sum(全コンテナの使用量) / sum(全コンテナの要求値) で利用率を算出する(Kubernetes公式ドキュメント)。アプリケーションコンテナ1つだけなら問題にならないが、サービスメッシュのサイドカープロキシやログ収集エージェントなど、複数コンテナを1つのPodに同居させる構成が当たり前になった今、この合算方式は判断を狂わせる。

具体的な数値で見てみよう。APIコンテナが500m要求・350m使用、ログエージェントが200m要求・20m使用というPodがあるとする。Pod全体で見た利用率は370m ÷ 700m ≈ **52.9%**だが、アプリコンテナ単体の利用率は350m ÷ 500m = **70%**になる(oneuptime.comの解説)。同じ負荷状況でも、見る対象によってスケーリング判断がまったく変わってしまうのだ。

2. なぜ気づきにくいのか — サービスメッシュという"見えない同居人"

section02

この問題が特に表面化しやすいのが、Istioなどのサービスメッシュを導入したタイミングだ。Istioの公式パフォーマンスドキュメントによれば、典型的な負荷条件下でサイドカープロキシ1つあたり約0.2 vCPU・60MBのメモリを消費する(Istio公式ドキュメント)。これ自体は小さな数字に見えるが、HPAのCPU利用率計算に混ざり込むことで、アプリコンテナの実際の負荷が見えにくくなる。

Google CloudのCloud Service Mesh運用ガイドでも、サイドカープロキシのリソース消費がHPAの計算に影響するため、リソースリクエスト/リミットを明示的に定義してリソース競合を防ぐことが推奨されている(Google Cloud公式ドキュメント)。しかし多くのチームは、サービスメッシュを導入した後に「なぜかHPAの挙動が変わった」と気づくまで、この合算の影響に気づきにくい。ログ収集エージェントやセキュリティエージェントなど、サイドカーパターンを使う構成が増えるほど、この"希薄化"の影響は大きくなる。

Kubo のようなK3sベースのマネージドKubernetesでも、Prometheus + Grafanaを標準搭載した構成でサービスメッシュやログ収集スタックを組み合わせる運用は珍しくない。標準のHPA仕様を正しく理解しておくことは、こうした構成での本番運用において避けて通れない。

3. ContainerResourceメトリクスで「対象コンテナだけ」を見る

section03

この"希薄化"問題に対する公式な解決策が、ContainerResource タイプのメトリクスだ。Kubernetesのこの機能は、Pod全体ではなく特定のコンテナのリソース使用量だけを対象にHPAのスケーリング判定を行える(KEP-1610: Container Resource based Autoscaling)。

このKEPの提案背景には、まさに「サイドカーコンテナはメインアプリの負荷と相関しないリソース消費をする」という課題が明記されている。機能としてはKubernetes 1.20でalpha導入され、1.27でbeta化、そして**1.30でStable(GA)**に到達した(Kubernetes公式ブログ)。設定は次のように、対象コンテナ名を明示するだけでよい。

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: ContainerResource
    containerResource:
      container: app-container
      target:
        type: Utilization
        averageUtilization: 70
      name: cpu

実務上、注意すべき点が1つある。対象コンテナに resource request が設定されていないと、そのPodの利用率は「undefined」となりHPAが動作しない。また、コンテナ名を変更する際はロールアウト前にHPA定義を更新しておく必要がある(Kubernetes公式ドキュメント)。この更新を忘れると、サイレントにHPAが機能しなくなるため見落としやすい落とし穴だ。DoiTのブログでも同様の設定例が紹介されており、前提条件としてKubernetes 1.27以上とMetrics Serverの導入が必要だと説明されている(DoiT Cloud Intelligence)。

いずれの方式でも、HPAはMetrics Serverが提供するMetrics APIを通じてリソース使用量を取得している(Kubernetesのresource metrics pipeline解説)。ContainerResourceメトリクスはこのパイプラインの上で、集計の粒度をPod単位からコンテナ単位に変えているにすぎない。追加のエージェントやツールは不要で、既存のMetrics Serverがあればそのまま使える。

4. K3s/Kuboでの考え方 — 標準Kubernetesの機能なのでそのまま使える

section04

ここまで解説した内容は、HPAというKubernetes本体(kube-controller-manager)の機能に関する話であり、特定のディストリビューションに依存しない。K3sはmetrics-serverを標準コンポーネントとして同梱しているため(K3s公式リポジトリ)、ContainerResourceメトリクスも追加設定なしでそのまま利用できる。

これはKuboのようなK3sベースのマネージドKubernetesを選ぶ理由の一つでもある。標準Kubernetesの機能がそのまま動くため、ベンダー独自の制約を気にせずHPAの設計を本などの公式情報どおりに進められる。特にKubo CloudはPrometheus + Grafanaを標準搭載しているため、ContainerResourceメトリクスに切り替えた後の効果を、既存のモニタリングスタックですぐに確認できる点も実務上のメリットになる。

サービスメッシュやログ収集エージェントを組み合わせた本番構成を今まさに設計している、あるいは「HPAの挙動がなぜか期待通りでない」という課題を抱えているなら、こうした運用をコスト効率よく実践できる基盤としてKuboを検討する価値はあるはずだ。

5. まとめ

HPAの標準的なResourceメトリクスは、Pod内の全コンテナの使用量を合算して利用率を計算する。この仕様は、サイドカープロキシやログエージェントを伴う現代的なPod構成では、スケーリング判断を「希薄化」させる原因になる。ContainerResourceメトリクス(Kubernetes 1.30でStable化)に切り替えることで、メインアプリケーションコンテナだけに焦点を当てたスケーリングが可能になる。

この仕組みはKubernetes本体の機能であり、K3sやKuboのようなマネージドK8s環境でもそのまま適用できる。サービスメッシュやObservabilityスタックを使う本番運用を設計する際は、「何に対する何%か」を常に意識しておきたい。運用基盤そのものを見直したい場合は、標準Kubernetesの機能がフルに使えるKuboのようなマネージドK3sサービスも選択肢に入れてみてほしい。月額48,000円〜という価格で、EKSやAKSと同等のHPA設計をそのまま持ち込める。お問い合わせから、具体的な構成についての相談も可能だ。

Related articles

← Back to all posts