🎉

Google Cloud で Synthetic Monitoring が Preview になりました

2023/08/09に公開

はじめに

こんにちは。クラウドエース株式会社で SRE をしている間瀬です。

今回は 2023 年 7 月 17 日に Preview となった Synthetic Monitoring について紹介したいと思います。

Synthetic Monitoring とは

合成モニタリングはサービスを利用するユーザの一連の操作によって発生するリクエストを擬似することでサービスの正常性をモニタリングするものです。
従来より Google Cloud より提供されていた稼働時間チェックによるモニタリングでは、特定のプロトコル、エンドポイント、URI に対してリクエストしたり、チェック用のエンドポイントをアプリケーション等で実装してこれに対してリクエストすることでサービスの正常性を確認するものになります。

これらの違いとしては、稼働時間チェックはプロセスレベルの正常性のモニタリングを行う一方で、Synthetic Monitoring ではアプリケーションのビジネスロジックレベルでのモニタリングが可能となる点かと思います。ユーザが利用する機能を監視することでビジネスロジックレベルでのモニタリングを行い、機能や非機能面での不具合を能動的に検出することが可能になります。

尚、導入負担における傾向としては稼働時間チェックは導入が容易であることに対して、Synthetic Monitoring はユーザの一連の操作を再現させる必要があるため、比較的導入に手間がかかると言えるでしょう。

Google Cloud における Synthetic Monitoring

今回 Preview された機能はモニタリングを行うための Cloud Functions を実装して、これを Google Cloud が一定間隔で実行し結果をモニタリングしてくれて、異常発生時には通知チャンネルより通知するものになっています。現在のところ実行間隔は最短1分ごとでタイムアウトの最小値は30秒となっています。

architecture

Cloud Functions では Synthetics SDK を利用しなければいけないことから、以下のように Node.js によってコードを記述する必要があります。

const functions = require('@google-cloud/functions-framework');
const fetch = require('node-fetch');
const { runSyntheticHandler } = require('@google-cloud/synthetics-sdk-api');
const assert = require('node:assert');

/*
 * This is the server template that is required to run a synthetic monitor in
 * Google Cloud Functions. It is unlikely that you should need to change the
 * contents of this function.
 */
functions.http('SyntheticFunction', runSyntheticHandler(async () => {
  /*
   * This is the function that should run your code synthetic code. This should
   * either exit without issue, in which case the synthetic is considered a
   * success, or it should throw an Error, in which case the synthetic is
   * considered a failure.
   */
  const url = 'http://xxx.xxx.xx.xxx/'; // URL to send the request to
  return await assert.doesNotReject(fetch(url));
}));

Synthetic Monitoring において参照できる情報はステータス、成功率、平均レイテンシ、監視実行毎の成否といった情報になります。

cloud-run

個人的には Identity-Aware Proxy(以下、IAP) による認証が自動化されたり、Cloud Functions を1から実装するよりも効率的に実現できるような機能もあれば良かったのですが、現時点ではそのような機能はないようです。勝手に今後のアップデートに期待しています。

本機能が解決する課題、メリット

Cloud Functions によって実装する必要はありますが、上記で説明したようなビジネスロジックレベルでの正常性確認に加えて、稼働時間チェックでは実現することが難しかった認証/認可が必要なエンドポイントに対してもモニタリングを行うことができる点が大きなメリットかと思います。
他には、監視結果に応じて通知チャンネルへ容易に連携できる点は個別に Cloud Functions を実装して監視を実現するよりも効率的でメリットになるかと思います。

利用にかかるコスト

モニタリングの実行回数に対して課金され、1000回実行あたり $1.2 となります。請求先アカウント毎に100回まで無料とのことです。
コストについての詳細は公式docを参照ください。

利用方法の紹介

今回は Synthetic Monitoring を使ってIAPによる認証が必要なエンドポイント、OpenID Connect (以下、OIDC)による認証が必要なエンドポイントをそれぞれ、モニタリングしてみようと思います。

IAP による認証が必要なエンドポイント

本検証では、IAPによる認証を必須とした Cloud Run 上の Nginx へアクセスするものとしています。

Cloud Run のデプロイ

公式docを参考に Nginx をデプロイします。
Nginx をデプロイするときは [既存のコンテナ イメージから 1 つのリビジョンをデプロイする] を選択してコンテナイメージ URL にて docker.io/library/nginx:latest を指定します。
また、Nginx は 80 ポートでリクエストを受け付けるので、コンテナポートは 80 にしてください。

IAP のセットアップ

Cloud Run にて IAP による認証を行う際はサーバーレス NEG とロードバランサが必要になります。公式docを参考にサーバーレス NEG とロードバランサを構築します。
その後、こちらの公式docを参考に IAP をセットアップします。

Synthetic Monitoring のセットアップ

事前にCloud Functions が利用するサービスアカウントを用意して IAP による認証をパスできるように「IAP で保護されたウェブアプリ ユーザー(roles/iap.httpsResourceAccessor)」ロールを付与するようにしてください。
その後、公式docを参考にセットアップを行いますが、Cloud Functions のサービスアカウントは上記ロールを付与したものを利用するようにします。監視頻度や通知チャンネルは自由に設定してください。
Cloud Functions のコードは以下のようにしてください。本コードではエンドポイントから 200 が応答されれば正常と判定しています。

const functions = require('@google-cloud/functions-framework');
const fetch = require('node-fetch');
const { runSyntheticHandler } = require('@google-cloud/synthetics-sdk-api');
const assert = require('node:assert');
const {GoogleAuth} = require('google-auth-library');
const url = 'https://xxxxxxxx/'; //LBのエンドポイント
const targetAudience = 'xxxxxxxxx'; // IAP で作成した認証情報のクライアントID
const auth = new GoogleAuth();

functions.http('SyntheticFunction', runSyntheticHandler(async () => {

  const client = await auth.getIdTokenClient(targetAudience);
  const res = await client.request({url})
  return assert.strictEqual(res.status, 200, `Expected status code 200, but received ${res.statusCode}`);
}));

セットアップが完了すると、実行間隔に基づいて監視が行われるようになり上記で紹介したようにコンソールから状況が確認できるようになります。

OIDC による認証が必要なエンドポイント

本検証では、OIDCによる認証を必須としたエンドポイントへアクセスするものとしています。
検証の際は Keycloak を IDP として、Cloud Run 上の Envoy の JWT Authentication を利用して検証を行なっていますが、本実装の説明は割愛させていただきます。
実装内容に興味がある方は以前に私が公開している記事にて説明していますので参照してください。

Synthetic Monitoring のセットアップ

上記で説明している内容と同様に公式docを参照してセットアップします。
Cloud Function のコードは以下のようにしてください。Keycloak に対してアクセストークンを要求して、これを使ってアプリケーションの API エンドポイントへリクエストを送信しています。
アクセストークンを要求する上では、Keycloak 上に専用のユーザを作成して使用するようにしています。

const functions = require('@google-cloud/functions-framework');
const fetch = require('node-fetch');
const { runSyntheticHandler } = require('@google-cloud/synthetics-sdk-api');
const assert = require('node:assert');

const authUrl = 'https://xxxxxxxxxxxxxxx/auth/realms/consumer/protocol/openid-connect/token'; // KeycloakのTokenAPIエンドポイント
const authParams = new URLSearchParams();
authParams.append('client_id', 'xxx');        //Client ID
authParams.append('username', 'xxxxxxxxxx');  //ユーザID
authParams.append('password', 'xxxxxxxxxx');  //ユーザパスワード
authParams.append('grant_type', 'password');

const authOptions = {
  method: 'POST',
  headers:{
    'Content-Type':"application/x-www-form-urlencoded"
  },
  body: authParams.toString(),
};

const appUrl = 'https://xxxxxxxxxxx/' // アプリケーションAPIエンドポイント

functions.http('SyntheticFunction', runSyntheticHandler(async () => {
    requestApp().then((result) => {
       return assert.strictEqual(result, 200, `Expected status code 200, but received ${result}`);
    });
}));

async function requestApp() {
  return fetch(authUrl, authOptions)
    .then((response) => response.json())
    .then((data) => {
      return fetch(appUrl,{
        headers:{
          "Authorization": "Bearer "+ data.access_token
        }
      }).then((response) => {
        return response.status    
      })    
      .catch((error) => {
         console.error('Error occurred:', error);
      });
    })
    .catch((error) => {
      console.error('Error occurred:', error);
    });  
}

セットアップが完了すると、実行間隔に基づいて監視が行われるようになり上記で紹介したようにコンソールから状況が確認できるようになります。

まとめ

サービスを利用する上で Cloud Functions を実装しなければいけない点はありますが、個人的にはリクエスト成功率、レイテンシを集計してくれる点や通知チャンネルとの連携容易性はとても魅力を感じました。
今後のアップデートへの期待としては Google Cloud が提供している IAP との統合が少しでも楽になるような機能が追加されると嬉しいなというところです。
冒頭にも記載しておりますが、本機能は記事執筆時点では Preview であることに注意してください。
興味ある方は触ってみてください。記事を閲覧いただきありがとうございました。

Discussion