Help us understand the problem. What is going on with this article?

SensuのhandlerとしてAnsibleを使う

More than 5 years have passed since last update.

うどん大学 情報系 院1年の堀内です.
勢いで Sensu Advent Calendar を立てましたが,無事埋まっていてホッとしています.

SensuはAnsibleと同時期に使い始めました.
現在は,研究室のサーバ監視に使っています.

もくじ

  1. Sensuとの出会い
  2. 研究室のサーバ監視で
  3. handlerとしてのAnsible

Sensuとの出会い

研究室でAnsible使ってる話」でも書きましたが,8月末にヤフーのインターンシップに参加しました.
そこでSensuが使われているのを見せて頂き,興味を持ったのがキッカケです.
ホテルに戻ってから,試してみようと作業していたのを覚えています.
(Ansibleを使ってsensu-clientを流し込もうと四苦八苦.)

ヤフーでの取組みはAdvent Calendarに書かれています.

研究室のサーバ監視で

研究室にはVMを含めて20台以上のサーバがあります.
そこにAnsibleを使ってsensu-cluentを流し込み,監視しています.

監視項目はCPUやメモリ,HTTPなど,基本的なものだけです.
community-plugins もしくは,その機能を削って使っています.

sensu_metrics.png

metricsはElasticsearchに投げて,Kibanaで可視化しています.
(fluentdなどを介さず,handlerから直接投げています.)
また,研究室で Typetalk を使っているので,Hubotを使ってアラートを投げたりもしています.

handlerとしてのAnsible

ここからが本題です.

例えば,SensuのHTTPチェックでCRITICALが発生したとします.
そこで,handlerからWebサーバを再起動するためにAnsibleを使ってみます.
(ついでに,Typetalkに再起動の通知も出します.)

発生したアラートはこんな感じ.

{
  "client":{
    "name": "web-server-01",
    "address": "192.168.11.10",
    "subscriptions": ["webservers"],
    "timestamp": 1326390159
  },
  "check":{
    "name": "check-http",
    "issued": 1326390169,
    "output": "HTTP CRITICAL: HTTP/1.1 503 Service Temporarily Unavailable",
    "status": 2,
    "command": "etc/sensu/community-plugins/plugins/http/check-http.rb -r -u http://localhost/",
    "subscribers":["webservers"],
    "interval": 60,
    "handler": "ansible",
    "history": [],
    "flapping": false
  },
  "occurrences": 1,
  "action": "create"
}

まず,このアラートを受ける/etc/sensu/plugins/ansible_handler.rbを作ります.

#!/usr/bin/env ruby
# Sensu Ansible Handler

require 'sensu-handler'

class AnsibleHandler < Sensu::Handler
  def playbooks
    settings['ansible']['playbooks'] || '/etc/sensu/playbooks'
  end

  def typetalk_vars
    {
      client_id: settings['ansible']['typetalk_client_id'],
      client_secret: settings['ansible']['typetalk_client_secret'],
      topic: settings['ansible']['typetalk_topic']
    }
  end

  def generate_hostfile(event)
    client = event['client']['name']
    address = event['client']['address']
    check = event['check']['name']

    hostfile = "/tmp/#{Time.now.strftime '%y%m%d%H%M%S'}.hosts"
    typetalk = typetalk_vars

    File.open(hostfile, 'w') do |f|
      f.puts "[#{check}]"
      f.puts "#{client} ansible_ssh_host=#{address}"
      f.puts "[#{check}:vars]"
      f.puts "typetalk_client_id=#{typetalk[:client_id]}"
      f.puts "typetalk_client_secret=#{typetalk[:client_secret]}"
      f.puts "typetalk_topic=#{typetalk[:topic]}"
    end

    hostfile
  end

  def handle
    status = @event['check']['status']
    occurrences = @event['occurrences']
    return if status < 2 || occurrences > 1

    hostfile = generate_hostfile @event
    check = @event['check']['name']
    result = `ansible-playbook -i #{hostfile} #{playbooks}/#{check}.yml`
    unless $?.to_i == 0
      puts result
    end

    File.delete hostfile
  end
end

handlerの設定ファイル/etc/sensu/conf.d/handler_ansible.jsonは下記の通り.

{
  "ansible": {
    "playbooks": "/etc/sensu/playbooks",
    "typetalk_client_id": "abcdefghijklmnopqrstuvwxyz123456",
    "typetalk_client_secret": "abcdefghijklmnopqrstuvwxyz123456789abcdefghijklmnopqrstuvwxyz123",
    "typetalk_topic": 1234
  },
  "handlers": {
    "ansible": {
      "type": "pipe",
      "command": "/etc/sensu/handlers/ansible_handler.rb"
    }
  }
}

ansibleで実行する/etc/sensu/playbooks/check-http.yml
Nginxの再起動と,Typetalkの通知のみでシンプルにします.

---
- hosts: check-http
  sudo: yes
  tasks:
    - name: restart nginx
      service:
        name=nginx
        enabled=yes
        state=restarted

    - name: notify to typetalk
      typetalk:
        client_id={{ typetalk_client_id }}
        client_secret={{ typetalk_client_secret }}
        topic={{ typetalk_topic }}
        msg='[sensu] restart nginx on {{ ansible_hostname }}'

後は,実際に対象サーバのNginxを止めると,Ansibleが実行されるはずです.
こんな感じで Huboco ちゃんが通知してくれます.

huboco.png

まとめ

今ハマっているSensuとAnsibleを組合せる方法を紹介しました.
今回はNginxでしたが,AnsibleでRailsをデプロイ しているので,こちらも対応させたいなと思います.

また,この記事のhandlerはGitHubで公開しています.
コメント・プルリクお願いします!

hiconyan
大手町でクラウドエンジニアしてます。うどん大学院 情報系出身。趣味は料理と映画、カメラ。
https://hiconyan.page/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした