chroju.dev/blog

the world as code

Kubernetes のアラート戦略

何番煎じだという話だし、あまり目新しいことも書ける気はしないが、自分の思考整理のために書く。あまり環境依存の話にはしないようにするつもりだが、マネージド Kubernetes を基本として考えている(セルフホストはあまり経験がない)。

ちなみにここでテーマにするのは「アラート戦略」であり、「監視戦略」ではない。何を「アラート」するべきかという観点で書いていく。

Kubernetes の監視レイヤー

ひとえに「Kubernetes の監視」と言ってもレイヤーが複数ある。

  1. Kubernetes 自体が正常動作しているか(コントロールプレーン)
  2. Kubernetes クラスタが正常動作しているか(各種ソフトウェア)
  3. ワーカーノードが正常動作しているか
  4. ワーカーノード上にデプロイしたコンテナが正常動作しているか
  5. コンテナが正常にサービスを提供できているか

1点目はマネージド Kubernetes を利用している場合には、不要かもしれない。ただ、その場合も監査や分析用にログ、メトリクスの出力と保存は行っていたほうがいいだろう。3点目に関しても、例えば EKS の Managed Node Group で自動制御となれば、基本的にはマネージドで動作保証されるので、監視する観点は少なくなる。このように1,3点目に関しては、 Kubernetes クラスタとして何を使うかにより、必要な監視に幅が出てくる。

2点目に関しては、 Kubernetes のクラスタ動作を制御するために追加で導入するソフトウェア、例えば descheduler のようなものを想定している。このようなソフトウェアは正確には「Kubernetes」という言葉が表す範囲の外ではあるが、クラスタの動作をより低いレイヤーで制御するものであり、かつ、マネージドの領域ではないので、マネージド Kubernetes を使っていたとしても独自に監視が必要になってくる。

4点目以降は、どのようなクラスタを選んでも基本的には監視が必要になる。5点目についてはアプリケーションレイヤーの話になるので、 Kubernetes 固有の戦略というよりは、一般的な外形監視などで要件を満たせる場合も多い。

アラートの基本戦略

一般的なアラート戦略は Monitoring 101: Alerting on What Matters | Datadog の内容をよく参考にしている。

  • アラートはレベル分けし、最も緊急のアラートだけを即時通知(ページング)する
  • アラートは障害の原因ではなく症状に対して設定する

特に2点目が重要で、一般的なアプリケーションであれば CPU 使用率の高騰ではなく、それによって引き起こされるアプリケーションの応答遅延のほうを監視するべきだ、ということになる。なぜなら CPU 使用率高騰は、必ずしもユーザー影響を及ぼすとは限らず、偽陽性のアラートになる可能性があるからだ。

Kubernetes においては、先のようにレイヤーが複数に渡るため、「原因」と「症状」が複雑に絡み合う。例えばワーカーノードのスケーリング台数が上限に到達してしまいスケールできず、新たな Pod が起動できなくなった結果、アプリケーションが稼働しなくなったとする。この場合、 Pod が起動できなくなったことはアプリケーションレイヤーからすれば「原因」だが、コンテナレイヤーや、 Kubernetes の正常稼働という観点からすれば「症状」だ。このように、レイヤー別で監視するべき「症状」を考えていく必要がある。

また1点目に関しても、 Kubernetes には Reconcile Loop の概念があるため、何らかの症状が発生したとしても、自動的に回復する場合が少なくなく、そういったものについてはページングは必要なく、翌営業日以降対応できるようチケットを切るなり、チャットに通知するなりでよい。 Reconcile Loop が正常に動作していない場合や、 Reconcile Loop が及ばない範囲の障害が主にページングの対象となる。

レイヤー別のアラート戦略

以上を踏まえてレイヤー別のアラート戦略を考える。

ワーカーノードの正常動作

ワーカーノードに関しては、何らかのオーケストレーションを利用していない場合は、通常の Linux サーバーと同等の監視が必要になると思われるが、運用経験に乏しいので深く踏み込まないことにする。

EKS Managed Node Group のようなオーケストレーションを利用しており、 Cluster Autoscaler を導入していれば、ノードのダウンや不足は自動的に解消されるので、監視が必要な範囲は限られてはくるが、ゼロではない。

  • ノード台数 / オーケストレーション最大台数
  • ノードのディスク使用率

Kubernetes クラスタにアプリケーションを増やしていけば、いつかはノード台数が設定の最大台数まで達し、それ以上スケールできなくなるおそれがある。そうなる前に設定変更をトリガーできるようにしたい。また、コンテナイメージの pull が積もり、ノードのディスク使用率がかさむと、 CPU やメモリといったリソースを活用しきっていないうちにノードが利用不可になってしまう場合もありえる。いずれもページングの対象ではないだろうが、対応のためにアラートは必要になる。

Kubernetes クラスタ制御のための各種ソフトウェア

先述の descheduler のようなソフトウェアだが、これはソフトウェアの種類により監視項目も変わってくるので、一概に言えるものではない。知らぬ間に停まっていた、正常に動作していなかったということがないように、何らかの手段で監視するほうが望ましいと思われる。

主に考えられる手段としてはログに出力されるエラーによるアラート、何らかの通信を受けるソフトウェアであれば、疎通可能であるか、などだろうか。また Prometheus が scrape できるような OpenMetrics の形でメトリクスを提供しているソフトウェアもあるので、その場合は分析用にメトリクスも取得しておきたい。 descheduler であれば、 https://localhost:10258/metrics で2種類のメトリクスを提供している。

個人的にはこのレイヤーの監視が最も重要だと考えている。このレイヤーは仮にエラーであっても、クラスタ自体の稼働、アプリケーションの稼働には影響を及ぼさない可能性があり、適切に監視しなければ見過ごしやすいからだ。

コンテナの正常動作

ひとえにコンテナといっても Deployment, Job, DaemonSet など、起動方法は様々であり、それぞれに応じた監視が必要になってくる。

  • Deployment の available / desired
  • DaemonSet の unavailable
  • Job, Cronjob の failed
  • CrashLoopBackoff の発生
  • ImagePullBackoff の発生
  • Restart の頻発

Deployment については desired と同数の Pod が available になっていない状態が継続している場合、 Reconcile Loop が何らかの異常をきたしている可能性があるので、監視しておきたい。ただし、一時的にコンテナがダウンした場合や、 Horizontal Pod Autoscaler で desired が拡張され、一時的に available が不足するといった場合もあるので、閾値は多少ゆるめでいいと考えている。アプリケーションの提供に必要十分な数の Pod が起動していないのであれば、それはアプリケーションレイヤーで監視するべきであり、ここでは「Deployment の Reconcile Loop が長期間正常に動作していない」という「症状」に着目すればいい。

その他のリソースについても同様に、 Reconcile Loop が働いていない場合にアラートすると考える。 DaemonSet であれば unavailable >= 1 が継続している場合、 Job や CronJob であれば failed が多発している場合などだ。これらについては僕としてはページング相当と考えている。

CrashLoopBackoff や ImagePullBackoff は悩ましいところではある。 CrashLoopBackoff, ImagePullBackoff は「コンテナが起動できない」という症状に対する原因に近いと思われるからだ。しかし、例えば Deployment のローリングアップデート中、これらのエラーで新規 Pod がずっと起動できないような場合であれば、 available / desired では検知できないが、こちらの監視でカバーができるし、必要に応じてアラートを上げても良いのではないだろうか(もちろん、 CD pipeline でアラートが上げられるならそちらでも良いが)。 ImagePullBackoff の発生は多くはないだろうが、コンテナレジストリの障害など、発生するパターンがゼロではない。あるいは Restart が多発しているような場合にアラートする手もある。

アプリケーションの正常動作

このレイヤーは基本的なアプリケーション監視の考え方とほぼ同等だが、1つ考えておきたいのは、 Readiness / Liveness probe と適切に組み合わせる点だ。Liveness probe では、応答に失敗する Pod を自動的に Restart させることができるので、 Restart により修復できるような可能性があれば、 probe 側で適切に監視させ、その上で一定時間修復されないような場合に、監視ツールからアラートを上げるような仕組みにしておきたい。 Readiness probe は、何らかの原因で一時的に応答できなくなる場合のある Pod に設定することで、外部からのリクエストが受け付けられないような状態を避けることができ、結果的に外部からの監視で偽陽性アラートが発生するのを抑えられる可能性がある。

Conclusion

Kubernetes の場合も「症状についてアラートする」「対処が必要なアラートについてページングする」という原則を忘れなければ、一貫した監視戦略を練っていくことができる。気をつけなくてはならないのは、 Reconcile Loop やマネージド Kubernetes の機能により、「対処が必要」な範囲を適切に見極める必要があることと、監視に必要なログやメトリクスの収集方法が、ソフトウェアやレイヤーに応じて異なってくることであり、このあたり難しさを感じている。メトリクスであれば kube-state-metrics の全容のみならず、ホスト側のメトリクス、さらに先述のような OpenMetrics を提供しているアプリケーションもある。まずはメトリクスやログをきちんと収集して可観測性を高めた上で、手持ちの材料を踏まえた監視戦略を都度適切に考えるようにしていきたい。

参考文献