ぐるなびは食に関する数多くのサイトを展開しており、私たちインフラ担当はこれらのサイトインフラの構築と運用を行なっております。
システム運用において「監視」というキーワードは、担当者にとってはとても重要な要素になるかと思います。
以前の監視システムでは、サーバが増えるたびに監視担当者に依頼を行い、監視登録を手動で行う運用がされていましたが、ぐるなびサイトの成長とともにリリーススピードも早くなり、対応できなくなってきました。
そのため、新しい監視システムを自分たちで作りました。今回はその設計から実装、運用までの取り組みについて紹介させていただきます。
設計フェーズ
システム監視というと世の中にはさまざまなツールが存在します。ZabbixやNagiosといったツール類が有名ですね。
真っ先にどのツールを使うかといったツール選定に目が向きがちですが、実際の運用においては現状の課題の把握と、あるべき姿に向けたコンセプトを決めておくことが重要だと思います。
保持サーバ情報を洗い出してグルーピング:サーバリストの活用
まずは、サーバの構成や役割を明らかにするため、管理したい属性をあらかじめ網羅的に把握したサーバリストを準備しました。
以前、弊社では「どういった監視を行うか」という、監視のために必要な情報をエクセルファイルで保持していました。しかし、自前で管理しているサーバが多かったこともあり、エクセルだとどうしてもシステムの自動化が困難でした。
そこでまず、この情報をDB化し、API経由で参照できるようにしました。
DB化に伴って、新たな属性を追加することに。
まずは、このサーバがどういう役割(WEBサーバかDBサーバ等)で、かつ、どんな構成(ミドルウェアのバージョンや構成等)かを定義した「サーバタイプ」という属性を用意しました。
この「サーバタイプ」によって同じ構成のサーバ群はグルーピングされることになります。
加えて、同一サービスというカテゴリでのグルーピングも行い、同じサービスを提供するサーバ群に対して「ロール」という属性を持たせました。
この標準化の工程がもっとも重要で難しい部分かもしれません。
サーバリストはとても便利で、一連の作業を自動化するのにとても重宝します。
- サーバの増強などを自動化するにあたり、クローニングしたサーバ情報をサーバリストにAPI経由で登録する
- サーバタイプに対応したテストコードを使ってServerspecでテストする
などといったさまざまな作業が自動化できるようになりました。
重大度に応じて監視の検知レベルを設計
監視を考える上でもう1つの重要な要素が検知のレベル設定です。
例えばSLA(サービスレベルアグリーメント)を99.99%と設定すると、1年間のうちに許容されるサービスのダウンタイムは 52.6分となります。
仮に監視でサービスの異常検知に1時間かかってしまうとすると、このSLAを満たすことはできません。かといってリアルタイムに異常検知を行おうとすると、監視サーバの負荷が増大するとともに誤検知が多くなります。
監視設計は、「異常を何分以内に検知したい」という要求に応じて行うと良いと思います。
監視項目によって、Critical, Warning, Informationなどの直接障害に関わるものやそうでないもの等がそれぞれ分類されるため、重大度に応じてアラート種別を分ける形が考えられます。
弊社では重大度が大きいものの方がより短い時間で検知できるように設計しています。こうすることでインシデント発生時のアラートを後々減らせるようにもなります。
実装フェーズ
弊社では主にサーバの死活監視にはZabbixを利用しています。Zabbix監視の実装例を簡単に紹介します。
自作監視テンプレートを使用
Zabbixでは監視アイテムをあらかじめテンプレートとして用意しておくことで、監視項目一元管理ができるようになります。
弊社ではサーバの監視については、Zabbix標準のテンプレートは使わず、自分たちで取りたい情報を自作テンプレートとして作成し運用しています。
この監視テンプレートは、サーバリスト上のサーバタイプに対応したものをあらかじめ作成しておくのがおすすめです。また、監視する対象のレイヤー(OS/ミドルウェア)ごとにテンプレートを分けておくことで、多様な組み合わせでも柔軟に対応できるようにしています。
Zabbixのトリガーでは依存関係を設定できるため、重複するアラートに対しては依存関係を設定しておきます。こうすることで、例えばサーバがハングアップしてしまった場合にも、必要な情報だけを通知できるようにしています。
一方でストレージ製品やネットワーク機器などについては、テンプレートの共有サイトZabbix Shareで公開されているものをベースに、カスタマイズを施しています。
Zabbix APIの利用
サーバ台数が多ければ多いほど 監視の登録作業も比例して増えていくため、こちらも自動化しました。
Zabbix APIを利用すると、WebUIなど管理画面を操作せずにデータ取得や各種設定が行えます。弊社では基本的な運用に関わる操作(登録、削除やメンテナンス、情報取得等)は全てコード化し、WebUIでの操作はあまり行っていません。
監視ノードの登録も、Jenkinsが定期的にサーバリストを監視し、サーバリストにサーバが追加されたことを検知すると、自動的にZabbixにも「サーバタイプに対応した監視」として登録されるようになっています。
監視情報の可視化
Zabbixのグラフ機能では、監視アイテムで取得した情報を可視化することが可能ですが、もっと簡単に、かつ、かっこよく可視化するにはGrafanaを使うのがおすすめです。
Grafana Labsで公開されているZabbixプラグインを追加するだけで非常に簡単に可視化が可能です。
サーバタイプごとにダッシュボードを作成しておき、サーバロール(同じサービスを提供するサーバ群)毎の情報を閲覧できるようにしています。
ZabbixトリガーのトリガーURL欄にGrafanaのダッシュボードURLとサーバロール(可変値)を設定しておくことで、アラート本文に適切なGrafanaのURLリンクが貼られるようにしています。
http://{$GRAPH_IP}/dashboard/db/pagename?var-group={TRIGGER.HOSTGROUP.NAME}
{$GRAPH_IP} はZabbixのユーザーマクロでグローバルに予め登録したもので、{TRIGGER.HOSTGROUP.NAME} は対象ノードが属するホストグループを示します。
注意点として、対象ノードが属するホストグループが1つだけならこれだけで問題ありませんが、複数のホストグループに属する場合は少しテクニックが必要です。
弊社では、アクション実行時にZabbix標準のメール通知は使用せず、スクリプトを介してトリガーURLの文字列をサーバリストのロール名に加工した上で、メール通知しています。
運用フェーズ
監視システムの刷新後、どのように変化したのでしょうか。
実際の運用における利点
大量にアラーティングされると何が本当の問題なのか気づくのに時間がかかってしまいますが、アラートが適切にされることで事象の把握が早くなります。
Zabbixトリガーの依存関係設定によって、インシデント発生時のアラート通知の数が大幅に減りました。
またアラート本文にGrafanaのURLリンクを貼るよう設定することで、サーバの状態が適切に可視化されたダッシュボードをワンクリックで参照でき、次のアクションへの判断が早くなりました。
他のオペレーションも自動化されているため、日々の運用での人的ミスや漏れも防止できています。
閾値の変更
システムを標準化し監視のテンプレート化を行っても、実際のサーバは様々な利用のされ方をするため、トリガーの閾値を変更するケースも多々出てきます。
弊社ではこういったケースも踏まえて、トリガーの閾値にマクロを使用するようにしています。ホスト単位にマクロ値を設定することで、監視テンプレート本体に手を加えずに対応できるようにしています。
トリガー例
{system.cpu.load[percpu,avg1].count(#4, {$LA_WARN}, "gt")}>3
マクロ例
{$LA_WARN} = 1
また、ローレベルディスカバリで作成したトリガーについては、単純なマクロ値によるトリガー閾値の変更ができないため、マクロコンテキスト機能を使うのがちょっとしたテクニックになります。
トリガー例
{vfs.fs.size[{#FSNAME},pused].last()}>{$DISK_USED_WARN:"{#FSNAME}"}
マクロ例
{$DISK_USED_WARN:"/usr"} = 85
最近のTopic
昨今、年々インフラを取り巻くシステムは複雑になりつつあるなか、弊社では自作のWrapper APIを活用しています。
Wrapper APIの役割
Kubernetes上のコンテナやパブリッククラウドの監視、監視対象もアプリケーションパフォーマンスや蓄積データによる機械学習による予兆検知など、さまざまなレイヤーを取り扱うようになってきています。
Wrapper APIに制御やエラーハンドリングを実装することで、監視ツール側のスクリプトをシンプルに構成できるようにしています。同時に、Zabbix以外のどんな監視ツールでも、Webhookにさえ対応していれば統合的に簡単に監視システムに組み込むことができるようになっています。
Twilioの導入
システム監視のアラート通知、皆さんどうされていますか。メールやSlackなどのチャットツール、または24時間365日アラートに気付く必要があるため架電などもよく使われるかと思います。
弊社でもこのように架電で夜間でも気付ける体制をとり、この仕組みをクラウドAPIサービスのTwilioで構築しました。
Zabbixではトリガー発生時のイベント通知方法としてスクリプトを使用できます。このスクリプトでTwilio APIを叩くようにするだけで、Twilioから簡単に架電させることが可能です。
実際にはZabbixから直接Twilio APIを呼び出すのではなく、Twilio APIをラップしたWrapper APIを用意しています。
Wrapper APIでは、例えば平日日中帯や、平日夜間帯、土日祝日など、日時や時間帯によって架電する番号(会社なのか携帯なのか)を切り替えたり、電話が繋がらない場合などに、次の電話番号にかけ直すなどのエラーハンドリングを行います。
この他にも
- 対象サーバによってかける担当者を判定する
- 同一のサーバロールで複数回アラートが上がったとき、1つのインシデントとみなして一定期間は架電しない
というような、これまで人が行なっていた処理を全て実装しました。
Twilioはメッセージの読み上げにも対応しています。
日本語や英語の言語選択が可能ですが、Zabbixトリガー自体は英語で設定することが多いので、メッセージの読み上げも英語を選択しています。聞き取れなかったり、ホスト名を正確に読み上げられなかったりすることも多いので、Twilioで架電した内容をSlackなどに文字で起こす補完も行っています。
インシデント管理
インシデント管理にRedmineを使っています。
こちらもRedmine APIを経由して自動的にインシデントを起票していますが、Twilioと同じようにZabbixから直接Redmine APIを叩かずラップした Wrapper APIを構築しています。
電話で呼び出されないようなインシデントも網羅的に管理することで、システムの健全性を維持するようにしています。
最後に
ぐるなびの監視システムは常に進歩し続けています。これまで人が行なっていたような作業をほとんど自動化させてきましたが、実際に監視アラートが上がるのはインシデントが発生した時です。いざという時にちゃんと監視システムが機能することを保証する必要があります。
障害が発生した際に、予期した動作としてちゃんとシステムが機能するか、現在カオスエンジニアリング*1の手法を取り入れながら進めています。こちらの内容も機会があればご紹介したいと思います!
最後まで読んでいただきありがとうございました。
お知らせ
今年はぐるなびアドベントカレンダー2018も実施しました!
*1:本番環境で意図的に障害を起こし、障害発生時のシステム挙動を把握する