グレンジ 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か月程度は参照できる)に遡って調査を行うことができないということと、
なにより、たまに起きたときに調査する手間がかかります。
ですので、ホストエラーが起きたら、__ChatworkとDatadog__に自動投稿するようにしました。
内容
素晴らしいことに、ホストエラーのエントリが__Stackdriver Logging__に出力されている!なら、エクスポートして、Cloud Functions で自動投稿できる!って内容です。
Stackdriver Loggingのエクスポート作成
Google Cloud Platfrom のコンソールから
Logging > エクスポート > エクスポートの作成 に移動します。
- フィルタの設定
jsonPayload.event_subtype
に compute.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 のトピックを新規作成します。
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 [プロジェクト名]
デプロイが完了で、ホストエラーの自動投稿は完了です。
こんな感じです。
最後に
これを実装してからホストエラーは激減しました。(が、たまに自動投稿されるので、個人的に重宝してます。)
あるあるですね。
カメラもカンシも止めずにがんばっていきましょう!
ありがとうございました。