ENGINEER BLOG

ENGINEER BLOG

Google Calendar APIとZabbix APIを組み合わせ、カレンダーに合わせて監視設定を切り替える

ITサービス本部 遠藤です。
運用設計書や手順書を作ったり、バックアップの処理を作ったり、監視の設定をしたりしています。
最近はもっぱらCloudWatchをいじってます。

今回はNCTの監視環境の紹介、悩み、解決に向けての検証結果報告です。

1.NCTの監視は、ほぼZabbix

NCTでは約60のサービスと、200台のサーバーやネットワーク機器を監視しています。
環境もオンプレ、クラウドさまざま。
OSもwindows、Linux両方があります。
これらほぼすべての監視に、Zabbixを利用しています。

Zabbixは有名なので、詳細は割愛しますが、なんでもできます。

2.Zabbix唯一の欠点

なんでもできるので、不満なんてないんじゃないか? と思われますがそんなことはありません。
その中でも特に大きいのが「祝日や祭日、メンテナンスの監視ステータス切り替え」です。

60近くのサービスがあるので、中には土日祝は監視しなくてよい(というかしてはいけない)ものもあります。
メンテナンス時も止めなくてはいけません。

しかしZabbixの監視停止は

No000

これしかありません

祝日にサービスが止まっているのに、監視を止めわすれた、三が日とめ忘れた、
結果パトランプが鳴ってオペレーターが余計な対応を…なんてことがたびたびありました。

これらを防止するために、今回は祝日や停止したい日に合わせて自動で停止する環境を構築することにしました。
Google CalendarとZabbixを組み合わせて、事前に停止する予約をします。

3.Google Calendar APIを導入する

ZabbixサーバーからGoogleカレンダーの日にちを取得するように、Google Calendar APIを導入します。
Google Calender APIのQuickstartサイトに沿って環境準備。
Google APIは様々な言語が用意されていますが、今回はpythonを使用します。

Quickstart

導入において、1点気になった動作があったので記載します。
quickstart.pyをLinuxサーバーで実行した後、認証画面が自動で表示されるのを待ったのですが、表示されませんでした。

■実行途中のメッセージ

% python quickstart.py
XXXX/lib/python2.7/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access XXXXX/.credentials/calendar-python-quickstart.json: No such file or directory
warnings.warn(_MISSING_FILE_MESSAGE.format(filename))

Your browser has been opened to visit:

https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleAPIs.com%2Fauth%2Fcalendar.readonly&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=NNNNNNNN-XXXXXX.apps.googleusercontent.com&access_type=offline

If your browser is on a different machine then exit and re-run this
application with the command-line parameter

--noauth_local_webserver

この場合、実行表示されているURLをコピーして、ブラウザでアクセスすると認証画面が表示されます。
認証ボタンを押すと、アクセスキーだけ表示されるサイトに移るので、
そのキーをコピーし、サーバー実行画面に貼り付けて Enterを押せば再開されます。

4.Google Calender APIとZabbix APIを組み合わせる

今回は、トリガー単位で監視を停止させます。
テスト用に適当なZabbix監視環境を作りました。

No001

ホスト名はローマ字、監視は死活監視を2個ずつ設定。
テンプレートを使う方が早いのですが、Zabbix上の変更結果を確認しやすくしたいので直接入力します。

No002
Googleカレンダーにホスト名を、日にち単位で登録します。

No003

■カレンダー情報取得

starttime、endtimeに時間を指定すれば、その時間内に登録されたスケジュール情報だけ持ってきます。
今回は、starttimeに現在時間を、endtimeに1日後を指定します。

認証情報の取得は、quickstart.pyをそのまま流用。

def get_googleclender():  
    credentials = get_googlecredentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('calendar', 'v3', http=http)

    starttime = datetime.datetime.utcnow()
    endtime = datetime.datetime.utcnow()+datetime.timedelta(days=1)
    starttimeutc = starttime.isoformat() + 'Z'
    endtimeutc = endtime.isoformat() + 'Z'

    eventstmp = service.events().list(
            calendarId='primary', timeMin=starttimeutc, timeMax=endtimeutc, singleEvents=True,
            orderBy='startTime').execute()
    eventsdata = eventstmp.get('items', [])

eventsdataから開始日時、終了日時、カレンダー情報を表示させてみます。

for eventsresult in eventsdata:
  start = eventsresult['start'].get('dateTime'eventsresult['start'].get('date'))
    end = eventsresult['end'].get('dateTime', eventsresult['end'].get('date'))      
    print(start,end, eventsresult['summary'])

表示結果はこんな感じです。

2017-10-10 2017-10-11 chiba
2017-10-10 2017-10-11 tokyo

なお、calendarId=’primary’の部分に日本の祝日カレンダーID(japanese__ja@holiday.calendar.google.com)
を指定すれば祝日を取得できます。

■Zabbix トリガー停止

登録したホスト名の、トリガーをすべて無効にさせます。
トリガーが有効の場合、statusが0ですので、trigger.updateで1に変更するようにします。

def change_zabbixstatus():
    zabbixurl = "http://localhost/zabbix/api_jsonrpc.php"
    headers = {"Content-Type":"application/json-rpc"}
    zabbixusr = "*****"
    zabbixupw = "*****"
    auth_post = json.dumps({'jsonrpc':'2.0', 'method':'user.login', 'params':{'user':zabbixusr, 'password':zabbixupw}, 'auth':None, 'id': 1})
    request = urllib2.Request(zabbixurl, auth_post, headers)
    contents = urllib2.urlopen(request)
    contents_str = contents.read()
    contens_dict = json.loads(contents_str)
    zabbixkey = contens_dict["result"]

    changedata = get_googleclender()
    trigerstatus = "1"

    for gethostdata in changedata:
            targethost = (gethostdata['summary'])
            auth_post = json.dumps({'jsonrpc':'2.0', "method": "trigger.get", "params":{"filter":{"host":targethost}}, 'auth':zabbixkey, 'id':1})
            request = urllib2.Request(zabbixurl, auth_post, headers)
            contents = urllib2.urlopen(request)
            contents_str = contents.read()
            contens_dict = json.loads(contents_str)

            for stoptriger in contens_dict["result"]:
                    stoptriggerid = stoptriger["triggerid"]
                    auth_post = json.dumps({'jsonrpc':'2.0', "method": "trigger.update", "params":{"triggerid":stoptriggerid ,"status":trigerstatus }, 'auth':zabbixkey, 'id':1})
                    request = urllib2.Request(zabbixurl, auth_post, headers)

実行してみます。

date;python zabbix_stop.py;date
2017年 10月 10日 火曜日 00:00:06 JST
2017年 10月 10日 火曜日 00:00:06 JST

無事、切り替わりました。

No004

5.まとめ

Google Calender とZabbixは連携できることがわかりました。
処理をZabbixサーバーのcronに登録し、自動起動を設定することで、祝日の監視停止は手動で行う必要がなくなります。
また、停止したい日にちを事前にカレンダー登録するだけですので、簡単に、誰でも監視を停止できます。
かつ登録しているホストが多い環境では、複数の監視を手動より短い時間で切り替えられます。

現在、Zabbix APIを用いた監視設定の更新は、アイテム、トリガー共に有効化・無効化しかできません。
メンテナンス等の作業を、時間単位でカレンダーを登録し、その内容をZabbix APIに引き渡して、
時間単位でアイテムの除外時間を更新する、
といったことができればより正確な監視切り替えができる!と期待が膨らみます。

Zabbixさん、APIのアップデートお待ちしております。