サードパーティ サービス向けのクラスタ通知を構成する

このチュートリアルでは、Google Kubernetes Engine(GKE)のクラスタ通知を受信するようにサードパーティのメッセージング サービスを構成する方法について説明します。

Slack などのサービスで提供される受信 Webhook を使用すると、アプリから Slack に簡単にメッセージを投稿できます。Cloud Run functions は軽量の Compute Engine ソリューションです。クラスタ通知など、Google Cloud イベントに応答する単一目的のスタンドアロン関数を作成できます。サーバーやランタイム環境を管理する必要はありません。GKE が Pub/Sub を使用してクラスタ通知を送信すると、トリガーが Slack 通知の送信などのアクションを実行して応答します。

アプリケーション間メッセージング機能を備えたサードパーティ サービスは、IFTTT をはじめとして数多く存在します。こうしたサービスを利用するために、このチュートリアルをテンプレートとして使用できます。

このチュートリアルでは、Cloud Run functions と Pub/Sub を使用して、GKE クラスタ イベントに関する通知を Slack に送信します。

Slack 通知

Slack 通知を設定するには、Slack アプリケーションを作成し、アプリケーションの着信 Webhook を有効にして、Slack ワークスペースにアプリケーションをインストールする必要があります。

Slack アプリケーションの作成

  1. メールアドレスで登録するか、またはワークスペース管理者から送信された招待状を利用して、Slack ワークスペースに参加します。

  2. ワークスペース名と Slack アカウントの認証情報を使用して、Slack にログインします

  3. 新しい Slack アプリを作成する

    1. [Create an app] ダイアログで [From scratch] をクリックします。
    2. アプリ名を指定し、Slack ワークスペースを選択します。
    3. [Create App] をクリックします。
    4. [Add Features and Features] で、[Incoming Webhooks] をクリックします。
    5. [Activate Incoming Webhooks] の切り替えボタンをクリックします。
    6. [Webhook URLs for Your Workspace] セクションで、[Add New Webhook to Workspace] をクリックします。
    7. 表示された認証ページで、通知を受け取るチャネルを選択します。
    8. [許可] をクリックします。
    9. [Webhook URLs for Your Workspace] セクションに Slack アプリケーションの Webhook が表示されます。後で使用できるように、URL を保存します。

Cloud Run 関数を作成する

GKE がクラスタ通知を Pub/Sub トピックに公開すると、イベントにより Cloud Run functions がトリガーされて Slack 通知が送信されます。

  1. gke_slack という名前の新しいディレクトリを作成し、そのディレクトリに移動します。

    mkdir ~/gke_slack && cd $_
    
  2. gke_slack ディレクトリに以下のファイルを作成します。

    index.js

    const functions = require('@google-cloud/functions-framework');
    const { IncomingWebhook } = require('@slack/webhook');
    
    const url = process.env.SLACK_WEBHOOK;
    
    const webhook = new IncomingWebhook(url);
    
    // Optionally filter what notification types to forward to Slack.
    // If empty, all types will be allowed.
    const allowedTypeURLs = [];
    
    // Register a CloudEvent callback with the Functions Framework that will
    // be executed when the Pub/Sub trigger topic receives a message.
    functions.cloudEvent('slackNotifier', pubSubEvent => {
        const data = decode(pubSubEvent.data.message.data);
    
        // Send message to Slack.
        if (isAllowedType(pubSubEvent.data.message.attributes)) {
            const message = createSlackMessage(data, pubSubEvent.data.message.attributes);
            webhook.send(message);
        }
    });
    
    // decode decodes a pubsub event message from base64.
    const decode = (data) => {
        return Buffer.from(data, 'base64').toString();
    }
    
    // isAllowedType can be used to filter out messages that don't match the
    // allowed type URLs. If allowedTypeURLs is empty, it allows all types.
    const isAllowedType = (attributes) => {
        if (allowedTypeURLs.length == 0) {
            return true;
        }
        for (var x in allowedTypeURLs) {
            if (attributes['type_url'] == allowedTypeURLs[x]) {
                return true;
            }
        }
        return false;
    }
    
    // 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;
    }
    

    SLACK_WEBHOOK は、Slack アプリケーション用に作成された webhook URL を指定する Cloud Run functions の環境変数です。関数のデプロイ時に、環境変数を定義します。

    Webhook は、Cloud Run functions からのメッセージをリッスンし、受信します。GKE がクラスタ通知を Pub/Sub(イベント)に送信すると、この関数は Webhook URL にメッセージ(トリガー)を送信します。その後、構成済みの Slack ワークスペースにメッセージが送信されます。

    createSlackMessage 関数でメッセージを拡張すると、テキストのフォーマット情報や画像など、多くの情報を含めることができます。isAllowedType 関数は、URL タイプでの通知の基本的なフィルタリングを有効にするために提供されます。allowedTypeURLs では、許可する URL タイプを指定できます。GKE または Pub/Sub サブスクリプションですでに通知をフィルタリング済みの場合、この関数は必要ありません。

    package.json

    {
      "name": "gke-slack",
      "version": "0.0.1",
      "description": "Slack integration for GKE, using Cloud Run functions",
      "main": "index.js",
      "dependencies": {
        "@slack/webhook": "6.1.0",
        "@google-cloud/functions-framework": "^3.0.0"
      }
    }
    

    package.json は、プログラムの以下の属性を記述します。

    • 名前、バージョン、説明
    • 主要ランタイム ファイル
    • 依存関係

    必要に応じて、依存関係、要件、その他の情報を追加できます。

これで、gke_slack ディレクトリに index.js ファイルと package.json ファイルが追加されました。

Cloud Run functions 関数をデプロイする

Cloud Run functions 関数は、Google Cloud CLI または Google Cloud コンソールでデプロイできます。

gcloud

関数をデプロイするには、gke_slack ディレクトリで次のコマンドを実行します。

gcloud functions deploy slackNotifier \
  --gen2 \
  --trigger-topic=TOPIC_NAME \
  --runtime=nodejs14 \
  --entry-point=slackNotifier \
  --region=REGION \
  --source=. \
  --set-env-vars="SLACK_WEBHOOK=WEBHOOK_URL"

次のように置き換えます。

出力は次のようになります。

Deploying function…
availableMemoryMb: 256
entryPoint: slackNotifier
environmentVariables:
  SLACK_WEBHOOK: https://hooks.slack.com/services/…
eventTrigger:
  eventType: google.pubsub.topic.publish
  failurePolicy: {}
  resource: projects/PROJECT_ID/topics/TOPIC_NAME
  service: pubsub.googleapis.com
labels:
  deployment-tool: cli-gcloud
name: projects/PROJECT_ID/locations/us-central1/functions/slackNotifier
runtime: nodejs10
serviceAccountEmail: PROJECT_ID@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/…
status: ACTIVE
timeout: 60s
updateTime: 'YYYY-MM-DDThh:mm:ssZ'
versionId: '1'

コンソール

  1. Google Cloud コンソールの [Cloud Run functions] ページに移動します。

    Cloud Functions に移動

  2. [関数の作成] をクリックします。

  3. [構成] ページで、次の手順を行います。

    1. [環境] プルダウン リストから [第 2 世代] を選択します。
    2. [関数名] で slackNotifier を指定します。
    3. [リージョン] で Compute Engine リージョンを指定します。
    4. [トリガー] セクションで [Eventarc トリガーを追加] をクリックします。
    5. 表示されたウィンドウで、[イベント プロバイダ] プルダウン リストから [Cloud Pub/Sub] を選択します。
    6. クラスタ通知を有効にするときに作成した Pub/Sub トピックを選択します。
    7. [リージョン] に、関数と同じ Compute Engine リージョンを指定します。
    8. [トリガーを保存] をクリックします。
    9. [ランタイム、ビルド、接続、セキュリティの設定] セクションを開きます。
    10. [ランタイム環境変数] で、[変数を追加] をクリックします。
    11. [名前] で SLACK_WEBHOOK を指定します。
    12. [] で、Slack アプリケーションの作成で作成した内部 Webhook の URL を指定します。
    13. [次へ] をクリックします。
  4. [コード] ページで、次の手順を行います。

    1. [ランタイム] プルダウン リストから [Node.js 14] を選択します。
    2. [エントリ ポイント] で slackNotifier を指定します。
    3. ナビゲーション パネルで [index.js] を選択し、コードを Cloud Functions の関数の作成にあるサンプルコードで置き換えます。
    4. ナビゲーション パネルで [package.json] を選択し、コードを Cloud Functions の関数の作成にあるサンプルコードで置き換えます。
    5. [デプロイ] をクリックします。

Cloud Run 関数のデプロイ完了後、GKE がクラスタ通知を送信するたびに Slack 通知が届きます。

Slack 通知の確認

Autopilot クラスタを使用した場合は、次のように通知を確認します。

  1. コントロール プレーンのアップグレードを開始します。
  2. GKE がノードを新しいバージョンに自動的にアップグレードするまで待ちます。所要時間は、構成したメンテナンスの時間枠とメンテナンスの除外によって変動する場合があります。
  3. GKE がノードをアップグレードしたら、Slack でメッセージを確認します。

Standard クラスタを使用した場合は、次のように通知を確認します。

  1. 特定のノードプールを新しいバージョンにアップグレードします。ノード上の GKE バージョンを変更しない場合は、ノード上で現在インストールされている同じバージョンにアップグレードできます。

  2. GKE がノードをアップグレードしたら、Slack でメッセージを確認します。

Slack の通知は次のようになります。

Master is upgrading to version 1.20.10-gke.301.
    cluster_location: us-central1
    cluster_name: pubsub-cluster
    payload: {"resourceType":"MASTER", "operation":"operation-1632775054313-45128f4f", "operationStartTime":"2021-09-27T20:37:34.313742491Z", "currentVersion":"1.20.9-gke.1001", "targetVersion":"1.20.10-gke.301"}
    project_id: 729788050015
    type_url: type.googleapis.com/google.container.v1beta1.UpgradeEvent