search
LoginSignup
5
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

グレンジ Advent Calendar 2018 Day 7

posted at

updated at

Organization

カンシを止めるな! 【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

最後に

これを実装してからホストエラーは激減しました。(が、たまに自動投稿されるので、個人的に重宝してます。)
あるあるですね。
カメラもカンシも止めずにがんばっていきましょう!

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

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
What you can do with signing up
5
Help us understand the problem. What are the problem?