PubSubの通知をEventarcでGKEに安全に送信する

ogp

はじめに

こんにちは、enechain に今年の 1 月から入社したエンジニアの櫻井 (@saku2saku) です。

enechain はあらゆるエネルギーの価値を自由に取引できるプラットフォームを運営しています。

事業領域が ”エネルギー” という非常に重要な社会インフラに関わるものであるため、高度なセキュリティ要件やガバナンスの容易さを維持できるよう、全社横断的な開発基盤を構築し、その上でアプリケーションの開発・運用をしています。(全社横断的な開発基盤については後日 SRE チームより記事が出る予定です)

私が所属するチームで開発している電力取引プラットフォーム eSquare もこの開発基盤で開発をしています。本記事では、開発の中で得られた「Pub/Sub の通知を Eventarc + Cloud Run で Cross Project の GKE へ安全に送信する TIPS」を共有できればと思います

背景と課題

enechain では、管理のしやすさやセキュリティ要件を満たすため、用途に応じた形で GCP プロジェクト(以下、 GCP PJ と記載)を分けて運用する Cross Project の形をとっています。アプリケーションを動作させる GKE のある GCP PJアプリケーションに紐づくマネージドサービスを置く GCP PJとで分けて管理をしています。

また、アプリケーションを動作させる GKE のある GCP PJは外部に公開する必要がないため Private Network からのアクセスのみを許可するべく Cloud Armor を置いて IP 制限をかける形にしています。

image1

こうした構成において、PubSub の通知を push 型で GKE 上のアプリケーションに対して送信するというニーズが発生したのですが、単純に PubSub Subscription の Push endpoint を指定する方法では固定 IP によるリクエストができないため Cloud Armor の IP 制限ポリシーに引っかかってしまい通信ができないという問題が発生しました(図の赤色の矢印の通信)。

image2

そこで今回は PubSub の通知を何かしらのサービスを経由して Cloud Run に渡して、Cloud Run からアプリケーションへのリクエストをサーバレス VPC アクセスのコネクタを通して行う方針としました。これにより Cloud Run からのリクエストを固定 IP で行えるため、CloudArmor に許可 IP を 1 つ追加すれば GKE に安全に通信できるようになります。

image3

PubSub と Cloud Run のつなぎに関してはEventarc を使う方法PubSub Subscriptionpush endpoint を指定する方法が候補としてあがりましたが、マネージドサービスの構築を Config Connector で行っていることもあり Subscription の push endpoint を指定するにはひと手間かかることになってしまうため今回はEventarc を使う方法を採用して実現することとなりました。

Eventarc の概要と課題の解決方法

Eventarc は GCP のイベント駆動型のサービスで、イベントを検知しそれを Cloud Run や Cloud Functions などの処理先に簡単にルーティングすることができます。 2021 年 1 月に GA リリースされた後も機能追加が継続的に行われておりイベントソースの種類がどんどん増えてきているため、色々なニーズに合わせて自動処理を行うことができる便利なサービスです。

cloud.google.com

2022 年 5 月には GKE をイベントの宛先として指定できる機能もリリースされました。 本当ならばこの機能を活用して下図のような構成を組めると Cloud Armor の IP 制限の変更も必要無くなってより安全に通信できて良かったのですが、Cross Project の GKE の指定はまだできないのと 2023 年 3 月時点においてはまだ Preview 版であったため、Eventarc から GKE を直接呼び出す方法については断念しました。

image4

その代わりに Eventarc から Cloud Run をキックして、Cloud Run からのリクエストをサーバレス VPC アクセスのコネクタを通して行うことで Cloud NAT の IP に固定する方法を取りました。 次の章では、仕組みのコアとなる下図の四角部分にフォーカスして構築方法を説明します。

image5

Pub/Sub の通知を Eventarc + Cloud Run で Cross Project の GKE へ安全に送信する

本章では Eventarc と Cloud Run を組み合わせて Pub/Sub の通知を Cross Project の GKE に安全に送信する方法について説明します。必要なリソースは以下となります。

  • PubSub Topic
    イベントメッセージを受けるための Topic
  • Eventarc
    PubSub Topic に届いたメッセージを指定のサービスに届ける
    イベントソース元となる Topic を指定すると自動で Subscription を作ってくれるため、自身で Subscription を作成する必要はありません
  • Cloud Run
    メッセージを受け取り、それをアプリケーションに Proxy するために用意するリソース リクエストを Proxy する際にサーバレス VPC アクセスのコネクタを通して Cloud NAT の IP に固定する
  • リクエストを受け付けるアプリケーション
    固定 IP からのリクエストが Cloud Run から届くことが検証できればよいので、ローカルで建てた python サーバを ngrok で公開したエンドポイントで受け付けて検証を行います
    サンプルコードおよび起動方法はこちら

上記以外にも厳密には Cloud NAT やそれに関連する VPC Connector などのリソースもありますが、本筋から少し逸れてしまうため割愛させていただきます。 (構築手順が気になる方は以下のドキュメントをご参照ください)

cloud.google.com

cloud.google.com

PubSub Topic の作成

任意の名前で Topic を作成しましょう。 Subscription は Eventarc の構築時に自動で作成されるため「デフォルトのサブスクリプションを追加する」のチェックは外して OK です。

image6

Cloud Run の作成

Cloud Run は特定のサーバに対して proxy するだけの役割のため、Nginx をベースに起動時に環境変数によって任意の宛先にリクエストをリダイレクトできるようなイメージを作成します。

下記の手順で作成した Docker イメージを Cloud Run から取得可能なご自身の GCR 等に配置してください。

作成したイメージは PROXY_PROTOCOL や PROXY_HOST、PROXY_PATH の環境変数を設定して起動することで任意の HTTP リソースに対してリクエストを Proxy することができます。

$ TMP_DIR=$(mktemp -d) && cd $TMP_DIR

$ cat << EOF > Dockerfile
FROM nginx:alpine

ENV NGINX_PORT=8080

ENV PROXY_PROTOCOL=https
ENV PROXY_HOST=localhost
ENV PROXY_PATH=

COPY ./templates /etc/nginx/templates

EXPOSE 8080
EOF

$ mkdir templates

$ cat << EOF > templates/default.conf.template
server {
    listen ${NGINX_PORT};

    location / {
        proxy_pass ${PROXY_PROTOCOL}://${PROXY_HOST}${PROXY_PATH};
    }
}
EOF

$ tree
.
├── Dockerfile
└── templates
    └── default.conf.template

$ docker build -t gcr.io/your-project/pubsub-proxy:blog .

イメージができたら管理画面より Cloud Run を作成していきます。 Cloud Run からのリクエストの IP を固定化するため VPC コネクタを指定するように注意してください。

image7

image8

Eventarc の作成

最後に PubSub と Cloud Run をつなぐ Eventarc を作成します。 イベントには `google.cloud.pubsub.topic.v1.messagePublished`` を選択することだけ注意してください。

image9

全体の動作確認

それでは作成したアーキテクチャが正常に動作することを確認していきましょう。 動画のとおり、Topic にメッセージを送ると Eventarc を通って Cloud Run で Proxy されて固定 IP(↓ の例では 34.146.21.170 )からのリクエストがローカルのサーバに届くことを確認できました。

movie

おわりに

PubSub 等のマネージドサービスと GKE の GCP PJ が Cross Project となっていて、GKE へのアクセスについては IP 制限をかけたいという前提において PubSub 通知を安全に GKE に対して送ることができるようになりました。

Eventarc の GKE トリガーの GA 版が公開されて Cross Project の GKE クラスタも指定できるようになったら、もうちょっと構成をスッキリさせることが期待できるため楽しみに待ちたいと思います。