freeeの開発情報ポータルサイト

Elastic StackによるKubernetesモニタリングシステムの紹介

まえがき

SREの河村(at-k)です。freeeにjoinしたのは今年1月なので、そろそろ1年。前職は組み込み分野の研究屋だったのもあって、扱う技術も仕事の進め方もガラッと変わり、なかなか刺激的な1年でした。ひたすら詰め込みな日々ですが、最近はようやくこの分野における自分なりの目標がぼんやり見えてきた感じです。しかし、理想は高く、道は遠い。来年も頑張っていきます、よろしくお願いします。

さて自分語りはこのくらいにして。

年末ですね。

この時期になるとみな無駄に忙しく、つい周囲に目が行かなくなり、足元がおろそかになります。そんなときに事故はつきもの。そうならないためにも、日々冷静に自分を見つめ、絶えず変化を監視する必要があります。つまりモニタリングです。

この記事はfreee Developers Advent Calendar 2018の14日目です。

Elastic StackでKubernetesクラスタをモニタリングしてみた

タイトル通りです。freeeでのKubernetesクラスタのモニタリングシステムを紹介します。

構成です。

構成図

Kubernetesのモニタリング方法として、巷ではDatadogやPrometheus + Grafanaなどがありますが、ここではログの収集・分析基盤からデータストアまでをElastic Stackで統一しています。理由はいくつかありますが、

  • Elastic Stackで統一することで、豊富な連携・効率的な運用を期待
  • 様々なログ・メトリクスの収集をサポートする軽量ログシッパーなElastic Beatsが良さそう
  • 開発が活発で、頻繁にバージョンアップしている
  • もともと社内でElasticsearch + Kibanaを使っていたのでノウハウがある

などが挙げられます。

続いて、各コンポーネントについてざっくりと説明します。

まずFilebeat/Metricbeatですが、これはElastic社の開発するLightweight Data ShippersであるElastic Beatsのファミリーソフトウェアです。 Filebeatは各コンテナのログを収集します。以下は一例です。

f:id:atkmr:20181214024506p:plain

MetricbeatはCPU、Memory、StorageやNetwork等のメトリックを収集します。以下は一例です。

f:id:atkmr:20181214024525p:plain

各レコードにはKubernetes由来のメタデータ(kubernetes.*)が自動で付加されます。また、Filebeatのレコード例でmessage-jsonというフィールドがありますが、これはログフォーマットがjson形式の場合に、自動で検出 & パースする機能を使っています。デフォルトでは有効で無いので、例えば以下のように設定します、詳しくは公式のマニュアルをあたってください。

config:
  filebeat.prospectors:
  <snip>
  - containers.ids:
    - '*'
    processors:
    - add_kubernetes_metadata:
        in_cluster: true
    - decode_json_fields:
         fields: ["message"]
         process_array: false
         max_depth: 5
         target: "message-json"
         overwrite_keys: true
    - drop_fields:
        when:
          has_fields: ["message-json"]
        fields: ["message"]
    type: docker

Filebeat/Metricbeatともにhelm chartが用意されているので、環境に合わせてvalue.yamlを書いてhelm installすれば大体OKです。

また、Filebeat/MetricbeatにはKibanaのセットアップコマンドが用意されており、例えばMetricbeatを使ってKibanaをセットアップすると、インデックスマップやダッシュボードをいい感じに作成してくれます。弊社における作例を貼ろうと思いましたが、黒塗りだらけで絵面が大変よろしくなかったので、どんな感じかは公式を参照ください。

ログは一度Kinesisに集めて、ここからS3とElasticsearchに同報しています。これにより、ログ送付の安定化を実現し、今後の発展的活用(ログ加工・転送先追加等)の余地を残しています。なおBeatsはデフォルトではKinesisを送付先に指定できないので、OSSのプラグインであるawsbeatsを使用しています。

ElasticsearchはAWS Elasticsearch Serviceを使っています。自前運用に比べてかなり楽ですが、Elasticsearchの最新バージョンにすぐに追従できなかったり、Kibanaに自前でpluginを入れられなかったりと、ある程度の制約が課せられます。

ログの監視としてはelastalertというツールを用いています。Elasticsearchのログを監視し、指定のログパタンにマッチしてSlackなどにメッセージを飛ばす仕組みです。またルールを管理しやすいように、Kubernetesに自前のOperatorを入れています。この辺は別記事で詳細を書くかもしれません。

トラブル集

モニタリングシステムにおいて重要なのは、途切れなくログを収集・格納することです。しかし、この世に絶対というものはなく、本システムもちらほらトラブルに見舞われました。厄払いも兼ねて、いくつか紹介します。

大きなサイズのログが壊れる

Filebeatはログファイルをtailして送付します。何のファイルを監視しているかは$ROOT_DIR/data/registryで管理されており、例えば以下のような形式です。

kubectl exec  filebeat-xyz cat data/registry |  jq . 
[
  {
    "source": "/var/lib/docker/containers/xxxxx.log",
    "offset": xxx,
    "timestamp": "2018-12-13T03:51:12.090061457Z",
    "ttl": -1,
    "type": "docker",
    "meta": null,
    "FileStateOS": {
      "inode": 1044114,
      "device": 51721
    }
  },

sourceが対象ファイルです。一定のサイズになったら別ファイルに切り替わってローテートするのですが、ログのレコード(改行区切り)がファイルをまたがった場合、別々のログとして分割されて送付され、結果、予期しない形式のログになってKibana上で見つからない、という問題がありました。 この問題については以下のissueで議論され、現在は対策済みで、ファイルをまたがってもうまいこと連結してくれます。

バージョンを上げたらログ採取エラー

ログ分割の問題解決、と思いきや、バージョンを上げるとログが送付されなくなりました。Filebeatのログを調べたところ、以下のようなエラー。

Read line error: invalid CRI log

こちらも公式で解決済み参考ですが、先のissueの対策と既存の制御方式のアンマッチで、ファイルの読み出し位置(offset)の不整合が置きたことが原因だった模様です。

ログサイズが大きすぎてKinesisで詰まる

先に書いたとおり、Kinesisを中継する仕組みになっていますが、Kinesisの制限でログのサイズは最大1MB/レコード(参考)です。巨大なログがこの制限に引っかかり、無限リトライして他のログが一切届かないという問題がおきました。filebeat側の設定で最大ログサイズを1MBに制限し、また、極端に大きいログは分割するように周知しました。

Elasticsearchに投入されたログがマッピング不一致でdropされる

Elasticsearchの仕様ですが、登録されているdata typeと異なるfieldを持つログを渡すとdropされます。それは良いのですが、各コンテナが思い思いにログを出力して、それが一律message-json.xxにパースされると、型の衝突が容易に発生します。つまり、message-json.idが、数値だったり文字列だったりして、エラーになる、という感じですね。dynamic templateでdata typeを文字列に寄せておくといったやり方で対応しますが、やや面倒なので、よいベストプラクティスを模索中。

こんな感じで時々地雷を踏みながら運用を続けています。ただBeatsに関しては未報告のバグは踏んだことがなく、また割とすぐに公式による修正が入る印象です。活発なコミュニティの恩恵ですね。

今後

健全なシステムを維持するためにもモニタリングは非常に重要ですので、より堅牢なモニタリングシステムを目指し、例えばモニタリングシステムの監視強化や冗長化を検討していきます。さらに、今回紹介した内容以外にも、Heartbeatで死活監視、Elastic apmで分散トレーシング、などがElastic社から提供されており、適宜組み込むことでモニタリング対象のさらなる充実に取り組んでいきます。また、他の監視システム、例えば最近AWS reInventで紹介されたCloudwatch Insightsなども、今のシステムの代替になりうるか試してみたいですね。

まとめ

以上、freeeにおけるKubernetesクラスタの監視システムを一部ご紹介しました。監視なきシステム運用は夜道を明かり無しで進むようなもの。安心して年の瀬を過ごせるよう、この機会にご自身のモニタリングシステムを見直してみてはいかがでしょうか。

それでは皆さん、ご安全に。

明日は、プロダクトを陰から守る、freeeセキュリティの要、CSIRT杉浦さんによる記事です!