⚠️ このエントリーは1年以上前に作成されたものです。情報の賞味期限切れにご注意ください。

先日、SpotFleetからASGに移行した。
ECS managed ASGが使えるので、ECSクラスターのスポットインスタンスが足りなくなったときに、勝手に足してくれるようになった。
ところで、ASGが知らない間に裏で上限までスケールアウトして請求が3倍くらいになるのは避けたい。
普段のサーバーの通知はDiscordに纏めているので、ASGの通知もDiscordにほしい。
SlackにはAWS Chatbotを使えばいいけど、Discordには対応していないのでLambdaを書く必要がある。
今回はそのお話。
Lambda関数を用意する
外部ライブラリーに頼るとパッケージを作らなきゃいけないし怠い。
1つしかない環境のために、わざわざSAMの用意をして~とかやるのは時間の無駄でバカがやることなので、標準ライブラリーだけでDiscordのIncoming Webhookを叩く。
ランタイムをNode.js 12.x
にしたLambda関数を作って、エディターに以下のソースコードをべた貼りする。
const https = require('https');
exports.handler = (event, context) => {
if (!process.env.WEBHOOK_URL) {
console.log("invalid 'WEBHOOK_URL'");
}
const url = process.env.WEBHOOK_URL;
console.log('event:', JSON.stringify(event));
const message = JSON.parse(event.Records[0].Sns.Message);
const postData = {
content: `**${event.Records[0].Sns.Subject}**\n${message.Description}\n> ${message.Cause}`,
embeds: [
{
fields: ['AccountId', 'AutoScalingGroupName', 'StatusCode', 'EC2InstanceId'].map((key) => ({
name: key,
value: message[key],
inline: true,
})),
},
],
};
const postBody = JSON.stringify(postData);
console.log('generated:', postBody);
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
};
const req = https.request(url, options, (res) => {
res.setEncoding('utf-8');
res.on('data', (chunk) => {
console.log(chunk);
});
res.on('end', (end) => {
context.done(null);
});
});
req.on('error', (e) => {
console.log('request error:' + e.message);
});
req.write(postBody);
req.end();
}
JavaScript環境変数WEBHOOK_URL
にDiscordのIncoming Webhook URLを設定する。
このLambdaではSlack形式ではなくてDiscordネイティブ形式で送信するので、末尾の/slack
は不要。
こんな感じ。

SNSトピックを用意する
スタンダードタイプのSNSトピックを作る。
他の項目は適当。

作ったSNSトピックのサブスクリプションにさっきのLambdaを指定する。

ASGのアクティビティ通知を設定する
ASGのアクティビティに用意したSNSトピックを紐付ける。


これで冒頭のような通知がDiscordに流れてくる。
