Edited at

カンシを止めるな! 【GCP】Stackdriver Logging と Cloud Functions で hostError を自動投稿

グレンジ Advent Calendar 2018 7日目担当のs.1na9ak1です。


概要


概要が長いので、3行で

概要が長くなってしまったので、まとめました。


  • たまにホストエラーが起きる

  • 調査が億劫

  • 自動投稿

以下、概要が長いので、内容まで読み飛ばしても大丈夫です。


インスタンスが再起動!原因はなに?

弊社サービス「ポコロンダンジョンズ」をGCPに移設した当初、インスタンスの再起動がごく稀にあり、調査を行うと原因はホストエラーとわかりました。


ホストエラーってなに?

「Google Compute Engine のよくある質問」に記載がありました。

仮想マシンでホストエラーが発生して再起動しました。何が起こったのですか?


ホストエラーは、仮想マシンをホストしている物理マシンで、仮想マシンがクラッシュするようなハードウェアまたはソフトウェアの問題が発生したことを意味します。Compute Engine でこのようなイベントが検出されると、オペレーション ログに compute.instances.hostError というエントリが追加されます。仮想マシンが自動的に再起動するように設定されている場合は(デフォルト設定)、別の物理マシンで仮想マシンが再起動します。



ホストエラーは起きたのか?

ホストエラーを調査する場合、

gcloud compute operations list --filter "hostError" --project [プロジェクト名]

compute.instances.hostError のエントリから検索

の2つがありました。


自動投稿しよう

上記の調査方法の場合、過去(1か月程度は参照できる)に遡って調査を行うことができないということと、

なにより、たまに起きたときに調査する手間がかかります。

ですので、ホストエラーが起きたら、ChatworkDatadogに自動投稿するようにしました。


内容

素晴らしいことに、ホストエラーのエントリがStackdriver Loggingに出力されている!なら、エクスポートして、Cloud Functions で自動投稿できる!って内容です。


Stackdriver Loggingのエクスポート作成

Google Cloud Platfrom のコンソールから

Logging > エクスポート > エクスポートの作成 に移動します。


  • フィルタの設定

jsonPayload.event_subtypecompute.instances.automaticRestart または、compute.instances.hostError のフィルタを設定します。

hostErrorの場合は、compute.instances.hostError

自動再起動の場合は、compute.instances.automaticRestart

以下のフィルタを設定します。

resource.type="gce_instance"

jsonPayload.event_subtype=("compute.instances.automaticRestart" OR "compute.instances.hostError")


  • シンクサービスの設定

エクスポート先に Cloud Pub/Sub を設定します。


  • シンクのエクスポート先の作成

Cloud Pub/Sub のトピックを新規作成します。

qiita001.PNG


Cloud Functions の作成

Chatwork 投稿と、Datadogにメトリックを送信します。

以下のコードを用意します。Node.jsで書いています。

Chatwork投稿は、Chatwork API

Datadogのメトリック送信に dogapi を利用しています。

index.js

var async = require('async');

var dogapi = require('dogapi');
var postChatworkMessage = require('post-chatwork-message');
var _ = require('underscore');
var dateformat = require('dateformat');
var moment = require('moment-timezone');

// https://app.datadoghq.com/account/settings#api
var options = {
api_key: '*****************************',
};

dogapi.initialize(options);

// ID:******************@grenge.co.jp
const CHATWORK_API_KEY = '*****************************';
// chat work room id
const RID = '*********';

const POST_TITLE_PREFIX = '[GCE_OPERATION]';

/**
* Background Cloud Function to be triggered by Pub/Sub.
*
* @param {object} event The Cloud Functions event.
* @param {function} callback The callback function.
*/

exports.triggerTopicComputeOperationsHostError = (event, callback) => {
var pubsubMessage = event.data;
var data = pubsubMessage.data ? Buffer.from(pubsubMessage.data, 'base64').toString() : null;

if (!data) {
console.log('ERROR: data is null.')
callback();
return;
}

var obj = JSON.parse(data);
var chatwork_post_message = '[info][title]' + POST_TITLE_PREFIX + ' ' + obj.jsonPayload.event_subtype + '[/title]';
chatwork_post_message += moment(Number(obj.jsonPayload.event_timestamp_us/1000)).tz("Asia/Tokyo").format("YYYY-MM-DD HH:mm:ssZ") + ' ' + obj.resource.labels.project_id + ' ' + obj.resource.labels.zone + ' ' + obj.jsonPayload.resource.name;
chatwork_post_message += '[/info]';
chatwork_post_message += 'https://console.cloud.google.com/logs/viewer?project=' + obj.resource.labels.project_id + '&resource=gce_instance%2Finstance_id%2F' + obj.resource.labels.instance_id;

// post
postChatworkMessage(CHATWORK_API_KEY, RID, chatwork_post_message);

// Datadog post event
dogapi.event.create(POST_TITLE_PREFIX, data, {
host: obj.jsonPayload.resource.name,
alert_type: 'error',
tags: ['project:' + obj.resource.labels.project_id, 'event_subtype:' + obj.jsonPayload.event_subtype, 'env:' + obj.resource.labels.project_id.replace('popolo-', '')]
}, callback);
};


Cloud Functions のデプロイ

gcloud functions deploy コマンドでデプロイを行います。

以下がデプロイコマンドです。

特に重要なのは、2点です。


  • --trigger-resource

Stackdriver Logging で作成したエクスポート先のトピックを指定します。


  • --trigger-event

Cloud Pub/Sub を利用するので、google.pubsub.topic.publish を指定します。

gcloud beta functions deploy triggerTopicComputeOperationsHostError --trigger-resource topic-compute_operations_host_error --trigger-event google.pubsub.topic.publish --project [プロジェクト名]

デプロイが完了で、ホストエラーの自動投稿は完了です。


こんな感じです。


  • Chatwork

    qiita002.png


  • Datadog

    qiita003.png



最後に

これを実装してからホストエラーは激減しました。(が、たまに自動投稿されるので、個人的に重宝してます。)

あるあるですね。

カメラもカンシも止めずにがんばっていきましょう!

ありがとうございました。