GKEのアップグレード実行をSlackへ通知させる


GKEのアップグレードをなぜslackへ通知させるのか

GKEのアップグレードってこちらで事前に実行することもできますが、気がついたらアップグレードされてると思います。

node-poolは意図的にオートアップグレードを無効化することもできるので無効にしている人もいると思います。

ただ、masterは利用者側ではオートアップグレードを無効化することはできないのでnodeだけ置いてけぼりになることがあります。

放置しているとGoogleのサポートバージョンではなくなることがあります。

その置いてけぼりを防ぐ、気がついたら上がってたということを防ぐために設定してみました。

必要なもの

  • Pub/Sub
  • Cloud Functions
  • Slack Incoming WebHooks
  • それなりに新しいgcloudコマンド
    • beta機能(2020/12時点)を利用するので古いgcloudコマンドだと入っていないです

手順

Pub/Subの作成

うちでは terraform で作成していますが、gcloudコマンドで作成する時は以下の通りになります

Pub/Sub topic の作成と Subscription の作成を以下のコマンドで作成します


$ gcloud pubsub topics create projects/[GCPのプロジェクト名]/topics/gke-upgrade-notify

$ gcloud pubsub subscriptions create gke-upgrade-notify --topic=gke-upgrade-notify

gke-upgrade-notify という文字列は適当に変えてもらって大丈夫です。変えた場合はこの先の指定するところも同様に修正が必要です。

Slack の Incoming WebHooks を作成する

  • 通知したいチャンネルの⚡マークをクリック

  • 検索窓が出てくるので app と入力すると 「Add apps to this channnel」が出てくるのでクリック

  • 検索窓に Incoming と入力すると Install ボタンがある Incoming WebHooks の項目があるので Install をクリック

    • View のボタンのものは他のチャンネルに通知を飛ばしているのに利用しているものなので利用しない
  • Add to Slack をクリック

  • Post to Channel のところで通知したいチャンネルを選択し Add Incoming WebHooks integration をクリックする
    • これでslack自体にwebhookの設定ができました
  • セットアップ画面になるので webhook url をコピーします

このURLは後ほど Cloud Functions の作成時に利用します。

Cloud Functionsの作成

事前にローカルPCで Cloud Functions に設定するコードを置いておきます

$ mkdir gke_slack
$ cd gke_slack

作成したディレクトリ配下で以下の2つのファイルを作成します

  • index.js
  • package.json

こちらは公式Docsのコードをそのまま利用しています

index.js
const { IncomingWebhook } = require('@slack/webhook');
const url = process.env.SLACK_WEBHOOK_URL;

const webhook = new IncomingWebhook(url);

// slackNotifier is the main function called by Cloud Functions
module.exports.slackNotifier = (pubSubEvent, context) => {
  const data = decode(pubSubEvent.data);

  // Send message to Slack.
  const message = createSlackMessage(data, pubSubEvent.attributes);
  webhook.send(message);
};

// decode decodes a pubsub event message from base64.
const decode = (data) => {
  return Buffer.from(data, 'base64').toString();
}

// createSlackMessage creates a message from a data object.
const createSlackMessage = (data, attributes) => {
  // Write the message data and attributes.
  text = `${data}`
  for (var key in attributes) {
    if (attributes.hasOwnProperty(key)) {
      text = text + `\n\t\`${key}: ${attributes[key]}\``
    }
  }
  const message = {
    text: text,
    mrkdwn: true,
  };
  return message;
}
package.json
{
  "name": "gke-slack",
  "version": "0.0.1",
  "description": "Slack integration for GKE, using Cloud Functions",
  "main": "index.js",
  "dependencies": {
    "@slack/webhook": "5.0.1"
  }
}

js,jsonを作成したディレクトリ配下で以下のコマンドで Cloud Functions を作成します

$ gcloud functions deploy gkeUpgradeNotify --trigger-topic gke-upgrade-notify --runtime nodejs10 --set-env-vars "SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYYY/zzzzzzzzzzzzzzzzzzzzzzzz" --ingress-settings internal-only --memory 128MB  --entry-point slackNotifier

SLACK_WEBHOOK_URL は事前にslackで作成したIncoming WebHooksのURLを利用してください。

エンドポイントは内部のみを許可するようにオプションを付けているのと entry point を明示的に指定しているのが公式Docsと異なるポイントです。

GKE の notification 設定

アップグレードの通知をしたいGKEクラスタを指定して以下のコマンドを実行する

$ gcloud beta container clusters update [クラスタ名] --notification-config=pubsub=ENABLED,pubsub-topic=projects/[プロジェクト名]/topics/gke-upgrade-notify --region asia-northeast1

複数のGKEクラスタの通知を同じSlackチャンネルに通知させたい場合は上記のコマンドのクラスタ名を変更して同じコマンドを実行したら通知されます。
別のSlackチャンネルに通知させたい場合は別名の Pub/Sub , Cloud Functions を作成して指定するpubsub-topicを変更したら分けて通知可能です。

通知例

この設定を行い、GKEのアップグレードを行うと以下のようにSlackに通知が来ます
Master,Node-poolそれぞれ別で通知が来ます。

参考文献