我々は Kubernetes の何を監視すればいいのか?

Posted on

freee では仮想マシンのインフラ監視に Mackerel を使っていますが、Kubernetes を使っているところは前例にとらわれずゼロベースで見直そうとしています。現状は Elastic Stack と Mackerel のハイブリット構成になっています。

どの SaaS を使うかを決める前に、そもそも Kubernetes の何を監視すればいいのか? というところから考え直しています。宣言的なマニフェストにより Kubernetes が自律的にあるべき状態を保ってくれるのであれば、これまでの監視とは異なってくるはずです。

監視の観点として、ここでは通知レベルを用いて次の 3 つに分類します。

  • None: メトリクスは収集するが通知しない
  • Notice: メトリクスを収集し、注意喚起レベルで通知する。緊急の対応を必要とせず、夜間のオンコールはしない
  • Alert: メトリクスを収集し、警告レベルで通知する。エンジニアによる即座な対応を必要とし、夜間はオンコールする

この記事では、アプリケーションレイヤーについては触れません。また、EKS や GKE といったマネージドサービスを前提としているため、コントロールプレーンの監視についても触れません。ちなみに、freee では EKS を使っています。

監視を見直すにあたって、O'Reilly の「入門 監視」がとても参考になりました。まだ読んでいない人はぜひ。

通知レベル: None

通知レベルが None のメトリクスは基本的に収集するだけです。メトリクスが重要ではないという意味ではなく、ユーザー視点により近いところで通知を設定するためです。

たとえば、仮想マシンのインフラではメモリ使用率を監視することが多いですが、Cluster Autoscaler が設定された Kubernetes クラスタではノードが増えることで自動的に解消します。ここで注目すべきは、メモリ使用率が上がっていることではなく、それによって例えばレスポンスタイムが悪化していないかどうかが重要です。

クラスタ

  • ノード数
    • 前提として Cluster Autoscaler でノード数が増減する
    • 何らかの理由で Cluster Autoscaler が動いていない場合は Deployment の監視で気付ける
  • コンテナ数
    • コンテナ数を維持するのは Deployment や DaemonSet の役割なので個別には監視しない
  • CPU, メモリ使用率
    • リソースが割り当てられないとき (e.g. PodExceedsFreeCPU) は Cluster Autoscaler がノードを増やすので基本的には放置でよい
  • ネットワークイン / アウト
  • ストレージの読み書き

コンテナ

  • CPU, メモリ使用率
    • Resource requests / Resource limits が適切か見る

通知レベル: Notice

通知レベルが Notice のメトリクスは、緊急の対応は不要ですが放置するとユーザーに影響が出かねないものです。 Kubernetes の自律システムでは復旧できないことが起きていて、エンジニアのフォローを必要とします。

コンテナに関する通知の初動対応は、そのプロダクトのエンジニアが担当するイメージです(見てわかるとおり運用保守に近い)。

クラスタ

  • Kubernetes のバージョン
    • EOL を迎えたバージョンを使っていないか
  • ファイルシステム使用率
  • ログエージェントのエラー
    • DaemonSet で配置したログエージェントがエラーになると、コンテナのログを欠損しかねない
    • コントロールプレーンのログは AWS が CloudWatch Logs に保存してくれるので任せる

コンテナ

  • Pod のイベント
    • OOMKilled など Pod に関するイベント
    • Resource requests / Resource limits を見直す
  • Deployment のイベント
    • CrashLoopBackOffPullImageError など Deployment に関するイベント
    • 直近のデプロイが原因である可能性が高い
    • ローリングアップデートであれば影響は一部に留まるので Notice レベルでよい
  • コンテナ配置の偏り
    • Kubernetes のスケジューラは Pod の作成時にしかスケジューリングを行わない
    • ノードの Availability Zone (AZ) は Auto Scaling Group によって分散するが、Pod は特定のノードに偏っている可能性がある
    • Descheduler というコンポーネントもあるが、まだ Incubator プロジェクトの段階

通知レベル: Alert

通知レベルが Alert のメトリクスは、通知が届いたときには何かしらユーザーに影響が出始めている可能性があるものです。気付いた時点で即座に対応することが求められます。

Kubernetes の自律システムを安定稼働させられない状態や、どのコンポーネントかわからないけどユーザーに影響が出ている状態を通知します。調査するときには通知レベル None や Notice で集めたメトリクスが役に立つはずです。

クラスタ

  • kube-system にインストールされたコンポーネント
    • Kubernetes を稼働させるのに必要なコンポーネントが動いていることを監視する
    • 自分たちでインストールしたコンポーネントも含む
  • NTP (時刻ずれ)
    • freee のサービスにおいて時刻ずれはクリティカルな問題に繋がる

コンテナ

  • エンドポイント監視
    • エンドポイントの疎通監視やレスポンスタイムの悪化など
  • Deployment の Desired と Available
    • デプロイ時などを除き、常に一致することが期待される
    • 長時間(閾値が難しい)一致しないときは何か起きている可能性がある
    • Cluster Autoscaler が動いていない場合などもここで気付ける

まとめ

こうやって洗い出してみると、これまでの監視と根本的に違うことがわかりました。特に Kubernetes の自律システムが正しく動いているかどうかを監視するのが重要だと思います。

Mackerel はこのあたりの機能が弱いので、Datadog に乗り換えるつもりでいます。導入が完了したら、また書きたいと思います。