Open4

Cloud Run のサイドカー Envoy でリクエスト URL を操作したい

kj455kj455

目的

Cloud Run の Sidecar 機能を使い、 リクエスト URL を Envoy で書き換えてからアプリケーションに渡したい

kj455kj455

そもそも Envoy が分かっていないので ChatGPT に聞いてみた


Envoy とは?

Envoyは、高パフォーマンスなエッジおよびサービスプロキシであり、クラウドネイティブアプリケーションのために設計されています。簡単に言えば、Envoyはトラフィックを受け取り、何らかの基準やルールに基づいてそのトラフィックを別の場所にルーティングするソフトウェアです。

主な特長

  1. パフォーマンス: EnvoyはC++で書かれており、非常に高速です。
  2. 動的な設定: サービスディスカバリ、ロードバランシング設定、ルーティング設定など、多くの設定を動的に変更可能です。
  3. 多機能: リトライ、タイムアウト、回路ブレーカー、アクセスログ、トレーシングといった多くの機能が組み込まれています。
  4. オブザーバビリティ: 詳細な監視メトリクスやトレーシング情報を提供します。
  5. L7フィルタ: HTTPやgRPCなどのレイヤ7のプロトコルに対するフィルタリングや操作が可能です。

主な用途

  1. エッジプロキシ: 外部からのトラフィックを受け取るフロントエンドのプロキシとして機能します。
  2. サービスメッシュ: マイクロサービス間の通信を管理し、トラフィックをルーティング、バランシング、セキュアにする役割を果たします。例えば、IstioのデータプレーンとしてEnvoyが使用されています。
  3. API Gateway: 外部のクライアントが内部のサービスやAPIにアクセスする際の入り口として機能します。

基本的なコンセプト

  1. Listener: トラフィックを受け取るための設定。IPアドレスとポートを指定して、どのようなトラフィックを受け入れるかを定義します。
  2. Cluster: トラフィックを転送する先のサービスやバックエンドの集合です。これにはロードバランシングの設定やサービスディスカバリの方法などが含まれます。
  3. Route: どのようなトラフィックをどのClusterにルーティングするかを定義する設定です。

総合的に見ると、Envoyはマイクロサービスやクラウドネイティブアプリケーションのトラフィックを効果的にルーティングし、管理するための強力なツールとなっています。


公式ドキュメント も読んでみたが、雰囲気だけ理解した。

色々な機能があるようだが、今回のユースケースである「アプリケーションの前段で HTTP リクエストを受けてその URL を書き換える」リバースプロキシ的な処理は実現できそうなことはわかった。

kj455kj455

Envoy の用語説明

  • Host
    • ネットワーク通信が可能なエンティティ
    • いわゆるサーバーやアプリケーションのことっぽい
  • Downstream
    • Envoy に対してリクエストを送り、レスポンスを受け取る側
  • Upstream
    • Envoy からリクエストを受け取り、レスポンスを返す側
  • Listener
    • Downstream クライアントが接続可能なネットワークロケーション(?)
    • port, unix domain socket 等
  • Cluster
    • Envoy が接続する Upstream ホストのグループ
    • サービスディスカバリを通じて接続先を見つける
kj455kj455

とりあえず /pr-1234/path/to/page/path/to/page にリライトする Envoy 設定ファイルは書けた(もっと簡単に書けるかもだけど)

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 80 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: 
                  safe_regex:
                    google_re2: {}
                    regex: "^/pr-[0-9]+/(.*)"
                route: 
                  cluster: backend
                  regex_rewrite:
                    pattern:
                      google_re2: {}
                      regex: "^/pr-[0-9]+/(.*)"
                    substitution: '/\1'
              - match: 
                  safe_regex:
                    google_re2: {}
                    regex: "^/pr-[0-9]+(.*)"
                route: 
                  cluster: backend
                  regex_rewrite:
                    pattern:
                      google_re2: {}
                      regex: "^/pr-[0-9]+(.*)"
                    substitution: '/\1'
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: backend
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: backend
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: CONAINER_NAME, port_value: PORT_VALUE }