VMware-vSphereで仮想マシンのvMotionをSlackに通知する

Adways Advent Calendar 2017 8日目の記事です。

http://blog.engineer.adways.net/entry/advent_calendar_2017


こんにちは、アドウェイズの天津です。商用インフラ全般を担当しています。

今回はオンプレ基盤で使用しているVMware vSphere でのvMotionをSlackに通知させた事例を書きます。

なぜSlack通知が必要だったか

弊社ではvSphereでESXi複数台でクラスタを組んでおり、DRSによる負荷平準化を設定しています。
DRSによるvMotionは自動で実施されるのですが、大きめの仮想マシンの場合、vMotion時に静止時間が長く、アプリケーションに影響が出ることがあります。
アプリケーションでエラーが発生し、原因切り分けを行う際に毎回vMotion履歴をvCenterにログインして確認としていましたが社外にいる場合もあるためリアルタイムSlack通知を実装しました。

構成

f:id:AdwaysEngineerBlog:20171212152642p:plain

VMware vCenter Server からvMotionをSNMPトラップで流し、受信サーバで整形してSlackに通知する構成です。

Slack通知のために必要なこと

  • SNMPトラップ受信サーバの設定
  • vCenter ServerでのSNMPトラップ送信設定
  • vCenter ServerでのvMotionイベントの通知設定
  • SNMPトラップのSlack通知スクリプトの作成

それでは説明していきますね。vSphere 5.5での設定となります。

SNMPトラップ受信サーバの設定

まずはvCenterServerと通信できるネットワーク内にSNMPトラップを受信するサーバを建てましょう。
詳しい説明は割愛しますが、net-snmpのインストールと設定で動作すると思います。
vSphereのMIBファイル(こちらから ダウンロード できます)も忘れずに設置してください。

https://code.vmware.com/web/sdk/55/vsphere-management

vCenter ServerでのSNMPトラップ送信設定

vCenterの「管理」 - 「設定」 - 「全般」 - 「SNMPレシーバー」にIPアドレス、ポート番号、コミュニティストリングを設定します。

f:id:AdwaysEngineerBlog:20171212152708p:plain

イベントが発生した場合、SNMPトラップ受信サーバに送信されるようになりますので、ログを確認してみて下さい。

vCenter ServerでのvMotionイベントの通知設定

ここが今回のポイントです。

vCenter ServerにてvMotionイベントを通知するようにアラーム定義を設定していきます。
アラーム定義は「状態変化」に対して通知が可能となっているため、状態変化を定義する必要があります。
今回は全仮想マシンの通知とするためvCenter Server のアラーム定義を設定します。
vMotionイベントにはDRSによるものと手動によるものがありますので2つとも設定します。

DRSの通知

「管理」-> 「アラーム定義」より新規作成します。(緑の+ボタンで作成)

  • 1 全般
    • アラーム名:任意
    • 説明:任意
    • 監視対象:仮想マシン
    • 監視内容:「仮想マシンのパワーオンなど、このオブジェクトで起きる特定のイベント」を選択
    • このアラームを有効にする:オン

f:id:AdwaysEngineerBlog:20171212152741p:plain

  • 2 トリガー

トリガーとなるイベントと条件を下記のとおり設定しましよう。

状態変化を定義するのはこの項目です。 「開始」を警告として設定し、「完了」を正常とするのがポイントです。

f:id:AdwaysEngineerBlog:20171212152751p:plain

DRSを検知するためユーザ作業を除く条件もつけておきます。

  • 3 アクション

アクションで「警告」から「正常」に状態変化したタイミングに対してsnmptrap通知を設定します。

f:id:AdwaysEngineerBlog:20171212152758p:plain

手動vMotionの通知

DRSのものとトリガーのみ異なります。

f:id:AdwaysEngineerBlog:20171212152808p:plain

確認

手動でvMotionを実行してみましょう。 うまく設定されていれば SNMPトラップ受信サーバの ログに下記のようなメッセージが書き込まれます。
(下記はrsyslogdによるログ書き込みのため、改行コードが8進数(#011、#012)に変換されています

Dec  4 18:46:47 snmptrapd-001 snmptrapd[53668]: 2017-12-04 18:46:47 192.168.200.8(via UDP: [192.168.0.1]:52727->[192.168.0.2]) TRAP, SNMP v1, community public#012#011VMWARE-PRODUCTS-MIB::vmwVC Enterprise Specific Trap (VMWARE-VC-EVENT-MIB::vpxdAlarmInfo) Uptime: 11 days, 23:38:59.22#012#011VMWARE-VC-EVENT-MIB::vmwVpxdTargetObjType.0 = INTEGER: vm(3)#011VMWARE-VC-EVENT-MIB::vmwVpxdOldStatus.0 = STRING: 赤#011VMWARE-VC-EVENT-MIB::vmwVpxdNewStatus.0 = STRING: 緑#011VMWARE-VC-EVENT-MIB::vmwVpxdObjValue.0 = STRING: vMotion_Notif - イベント: 仮想マシンが移行されました (7260303)#012サマリ: 仮想マシン amatsu-test-001 が ESXi-A、Storage-A から ESXi-B、Storage-A に移行されました#012日付: 2017/12/04 9:46:46#012ユーザー名: ADWAYS.NET\amatsu_satoshi#012仮想マシン: amatsu-test-001#012ホスト: ESXi-A#012リソース プール: Test-Cluster#012データストア: Storage-A#012データセンター: Test-Datacenter#012引数:#012    sourceDatacenter.name = Test-Datacenter#012    sourceDatastore.name = Storage-A#012    sourceHost.name = ESXi-B#012#011VMWARE-VC-EVENT-MIB::vmwVpxdTargetObj.0 = STRING: amatsu-test-001

改行変換処理したものが下記です。(#011をタブに、#012を改行に置き換えています)

Dec  4 18:46:47 snmptrapd-001 snmptrapd[53668]: 2017-12-04 18:46:47 192.168.200.8(via UDP: [192.168.0.1]:52727->[192.168.0.2]) TRAP, SNMP v1, community public
    VMWARE-PRODUCTS-MIB::vmwVC Enterprise Specific Trap (VMWARE-VC-EVENT-MIB::vpxdAlarmInfo) Uptime: 11 days, 23:38:59.22
    VMWARE-VC-EVENT-MIB::vmwVpxdTargetObjType.0 = INTEGER: vm(3)    VMWARE-VC-EVENT-MIB::vmwVpxdOldStatus.0 = STRING: 赤   VMWARE-VC-EVENT-MIB::vmwVpxdNewStatus.0 = STRING: 緑   VMWARE-VC-EVENT-MIB::vmwVpxdObjValue.0 = STRING: vMotion_Notif - イベント: 仮想マシンが移行されました (7260303)
サマリ: 仮想マシン amatsu-test-001 が ESXi-A、Storage-A から ESXi-B、Storage-A に移行されました
日付: 2017/12/04 9:46:46
ユーザー名: ADWAYS.NET\amatsu_satoshi
仮想マシン: amatsu-test-001
ホスト: ESXi-A
リソース プール: Test-Cluster
データストア: Storage-A
データセンター: Test-Datacenter
引数:
    sourceDatacenter.name = Test-Datacenter
    sourceDatastore.name = Storage-A
    sourceHost.name = ESXi-B
    VMWARE-VC-EVENT-MIB::vmwVpxdTargetObj.0 = STRING: amatsu-test-001

SNMPトラップのSlack通知スクリプトの作成

上記の通知内容を整形して通知します。今回はbashで書きました。「OID」と「サマリ」が含まれる行を処理しています。
弊社ではSlack通知に cubicdaiya さんのslackboard https://github.com/cubicdaiya/slackboard を使用して送信していますが、curlで直接Slackに送信してもいいと思います。

#!/bin/bash

Temp_trap="/tmp/temp_trap.log"
CHANNEL="amatsu-vminfo"
SLACKBOARD="192.168.0.101:29800"

echo -n > $Temp_trap

while read LINE; do
  echo $LINE >> $Temp_trap
done

# OIDの取得
OID=`head -4 $Temp_trap | tail -1 | cut -f2 -d " "`

##### VMware vCenter Event MIB Trap #####
case $OID in
  *VMWARE-VC-EVENT-MIB* | *VMWARE-PRODUCTS-MIB* ) 
     if grep "DRSvMotion_Notif"  $Temp_trap > /dev/null ; then
       # DRS
       Message=`grep サマリ $Temp_trap | sed 's/、/ /g' |awk '{printf("vMotion(DRS): \`%s\` : %s -> %s (%s)", $4, $6, $12, $10)}'`
     elif grep "vMotion_Notif"  $Temp_trap > /dev/null ; then
       # operation
       Message=`grep サマリ $Temp_trap | sed 's/、/ /g' |awk '{printf("vMotion(ope): \`%s\` : %s -> %s ( %s -> %s)", $3,  $5, $8, $6, $9)}'`
     fi

     if [[ ! -z ${Message} ]]; then
       # send Slack
       echo -e "${Message}" | /usr/local/bin/slackboard-cli -s ${SLACKBOARD} -c ${CHANNEL} > /dev/null &
     fi
     ;;
esac

exit 0

通知スクリプトの設定

作成したスクリプトをSNMPトラップ受信時のハンドルとして登録します。

動作確認

手動でvMotionしてみましょう。 下記のようにSlackに通知が実行されるはずです。

f:id:AdwaysEngineerBlog:20171212152825p:plain

これでいつでもどこにいてもvMotionがリアルタイムで把握できますね。

終わりに

今回、SNMPトラップをトリガーにしてSlackにvMotionを通知しましたが、任意のスクリプトを動かすことができるため、vMotionの前後に動かしたいスクリプトがあれば仕込むことができます。
vMotionに影響を受けるアプリケーションやミドルウェアがある場合、事前作業の自動化や回復処理の自動化ができそうですね。

最後までお読みいただきありがとうございました。