10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Docker2Advent Calendar 2016

Day 3

Docker Events APIとSensu Proxy Clientsでコンテナ監視

Posted at

こんにちは、@hico_horiuchiです。
この記事はDocker2 Advent Calendar 2016の3日目です。

先日、社内でコンテナやクラウドネイティブの勉強会があり、そこでLTした内容をブラッシュアップしました。
Dockerは仕事で使っている訳ではなく、紹介するツールに新規性も実用性も無いですが、参考までに。

Sensuとは?

Sensuは、2011年から開発されているRuby製のOSS監視ツールです。
監視ホストの自動登録など、Nagiosの問題点を解消し、クラウド環境に適した監視ツールとして作られました。
下の図のように、sensu-serverとsensu-client間の通信にRabbitMQ、設定や監視結果の保存にRedisを使っています。
(sensu-serverやミドルウェアは簡単にスケールアウトすることができます。)
また、JSON形式の簡素な設定ファイルなど、ChefやAnsibleなどの構成管理ツールとの相性も良いです。

sensu-diagram.png

SensuによるDockerの監視

Sensuでは、Docker監視用の公式プラグインが提供されています。
ただ、少し触ってみて、機能不足を感じる部分がありました。

上のプラグインでは、sensu-clientを導入したDockerホストが1つの監視対象として登録されます。
しかし、今回は各コンテナを、それぞれsensu-clientとして監視したいと考えました。
ただ、一々Dockerfileを編集してsensu-clientを導入するのは面倒です。

そこで、SensuのProxy Clientsという機能を使うことにしました。
Proxy Clientsは、sensu-apiに対して監視ホストや監視結果のJSONを投げると、登録してくれる物です。
(sensu-clientを導入していないホストも、sensu-clientとして登録できる、など。)
これで、コンテナ単位で監視でき、監視結果のハンドリング(通知など)もsensu-serverで行えるようになります。

Dockerのイベントについて

Dockerでは、イメージをビルドする、コンテナを起動するなどのイベントが発火・記録されます。
今回は create で監視ホスト登録、 kill で監視結果登録するように実装しています。
(本当は終了ステータス等も考慮する必要があるのですが、まだその段階まで行っていないので…。)

event_state.png

サンプルとして、rabbitmqコンテナを run , kill , rm したときのイベントを取ってみました。
ネットワークの接続や、ボリュームのマウントが実施されていることが分かりますね。
(RubyからDocker Remote APIを呼ぶのにswipely/docker-apiを使いました、便利ですね。)

[1] pry(main)> Docker::Event.stream { |event| p event }                                                                                                                             
#<Docker::Event:0x007fed16026c40 @Type="container", @Action="create", @Actor=#<Docker::Event::Actor:0x007fed16026a38 @ID="a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", @Attributes={"image"=>"rabbitmq", "name"=>"rabbitmq"}>, @time=1480730174, @timeNano=1480730174259097295, @status="create", @from="rabbitmq">
#<Docker::Event:0x007fed16025138 @Type="network", @Action="connect", @Actor=#<Docker::Event::Actor:0x007fed16024f80 @ID="4d01638e5b1c4b44257d45dddab0958ef01b0cd9ffb9fda7bfa6af2eb1d77aed", @Attributes={"container"=>"a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", "name"=>"bridge", "type"=>"bridge"}>, @time=1480730174, @timeNano=1480730174418394592, @status=nil, @from=nil>
#<Docker::Event:0x007fed1601f9e0 @Type="volume", @Action="mount", @Actor=#<Docker::Event::Actor:0x007fed1601f760 @ID="e663057569416c62641ea9e9ded1c449f9a69b84a4858903636103e610e2d833", @Attributes={"container"=>"a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", "destination"=>"/var/lib/rabbitmq", "driver"=>"local", "propagation"=>"", "read/write"=>"true"}>, @time=1480730174, @timeNano=1480730174447237658, @status=nil, @from=nil>
#<Docker::Event:0x007fed16017128 @Type="container", @Action="start", @Actor=#<Docker::Event::Actor:0x007fed16016d68 @ID="a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", @Attributes={"image"=>"rabbitmq", "name"=>"rabbitmq"}>, @time=1480730174, @timeNano=1480730174677730843, @status="start", @from="rabbitmq">
#<Docker::Event:0x007fed1600c2f0 @Type="container", @Action="kill", @Actor=#<Docker::Event::Actor:0x007fed16003ba0 @ID="a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", @Attributes={"image"=>"rabbitmq", "name"=>"rabbitmq", "signal"=>"9"}>, @time=1480730187, @timeNano=1480730187279469309, @status="kill", @from="rabbitmq">
#<Docker::Event:0x007fed1523c6c0 @Type="container", @Action="die", @Actor=#<Docker::Event::Actor:0x007fed1523c2d8 @ID="a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", @Attributes={"exitCode"=>"137", "image"=>"rabbitmq", "name"=>"rabbitmq"}>, @time=1480730187, @timeNano=1480730187282653393, @status="die", @from="rabbitmq">
#<Docker::Event:0x007fed15235820 @Type="network", @Action="disconnect", @Actor=#<Docker::Event::Actor:0x007fed15235320 @ID="4d01638e5b1c4b44257d45dddab0958ef01b0cd9ffb9fda7bfa6af2eb1d77aed", @Attributes={"container"=>"a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", "name"=>"bridge", "type"=>"bridge"}>, @time=1480730187, @timeNano=1480730187497574672, @status=nil, @from=nil>
#<Docker::Event:0x007fed1522e368 @Type="volume", @Action="unmount", @Actor=#<Docker::Event::Actor:0x007fed1522dd78 @ID="e663057569416c62641ea9e9ded1c449f9a69b84a4858903636103e610e2d833", @Attributes={"container"=>"a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", "driver"=>"local"}>, @time=1480730187, @timeNano=1480730187530913425, @status=nil, @from=nil>
#<Docker::Event:0x007fed152274a0 @Type="container", @Action="destroy", @Actor=#<Docker::Event::Actor:0x007fed152272c0 @ID="a34b0b00cfe6201a9d597e01cf3bff34743b5165c73b8a3ba560258cb12cea11", @Attributes={"image"=>"rabbitmq", "name"=>"rabbitmq"}>, @time=1480730195, @timeNano=1480730195313928081, @status="destroy", @from="rabbitmq">

Sunameriの紹介

では、Docker Events APIを監視してSensu Proxy Clientsを登録するツールを作ったので紹介します。
(クジラの仲間で、漢字2文字で良さそうな名前…ということで、砂滑にしました。)

sensu-server, sensu-api, uchiwa(Sensuのダッシュボード)などの一式が入ったDockerfileを同梱しています。
Git、Ruby、Dockerが使える環境であれば、コマンドを幾つか打つだけで使い始められる筈です。

$ git clone git://github.com/hico-horiuchi/sunameri.git
$ cd sunameri
$ docker build -t hico/sunameri .
$ docker run -d -p 3000:3000 -p 4567:4567 --name sunameri hico/sunameri
$ bundle install --jobs=4 --path=vendor/bundler --binstubs=vendor/bin --without doc production
$ SENSU_API_HOST=localhost SENSU_API_PORT=4567 bundle exec ruby bin/sunameri

http://localhost:3000/ でuchiwaにアクセスできます。
試しにrabbitmqコンテナを起動すると、クライアント一覧に登録されていることが分かりますね。

clients.png

次に、rabbitmqコンテナを kill すると、アラートが上がってきました。
勉強会で「死亡時のログも見れると嬉しい」と言われたので、一緒に見られるようにしてみました。
(行頭に何か文字が入っているようです…除去方法知ってる方居たら教えて下さい…。)

events.png

まとめ・これから

今回、とりあえずコンテナの登録とアラートの発火まではできるようになりました。
Docker Remote APIを触るのはほぼ始めてでしたし、イベントサイクルの勉強にもなって良かったです。
今はVPS上のDockerホストの監視にMackerelを使っていますが、いつかは大好きなSensuを使えるようにしたいですね。

まだまだ不足している機能や課題がありますが、引き続き細々と開発を続けて行こうと思っています。
以上、ありがとうございました。これからAdvent Calendarを書かれる方、楽しみにしてます&応援してます!

10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?