Contents
Envoy の概要と主要コンポーネント
Envoy は L7 プロキシとして、マイクロサービス間の通信を統一的に管理・観測できる基盤です。本節では「リスナー → ルート → クラスタ → フィルタ」というデータフローと、各コンポーネントが実際にどんな役割を担うかを簡潔に解説します。全体像を把握すれば、設定ファイルの構造やトラブルシューティングが格段に楽になります。
リスナー (Listener)
リスナーは外部からの接続(IP とポート)を受け付ける入口です。TCP/HTTP それぞれに対して独立した filter_chain を定義でき、プロトコルごとの前処理を柔軟に組み合わせられます。
ルート (Route)
リクエストのパスやヘッダー情報に基づき、どのクラスタへ転送すべきかを決定します。VirtualHost と RouteRule の組み合わせで「ドメイン単位」・「パス単位」の細かなマッピングが可能です。
クラスタ (Cluster)
実際のバックエンド(Service)への接続先情報を保持し、ロードバランシングやヘルスチェックを自動的に行います。EDS/CDS などの xDS API を通じて動的に更新できる点が特徴です。
フィルタ (Filter)
リクエスト/レスポンスの加工・認証・トレース・リトライ等のロジックをプラグイン形式で挿入します。HTTP フィルタとネットワークフィルタに大別され、filter_chain の順序が処理フローを決めます。
ポイント
データは「受信 → 振り分け → 転送 → 加工」の 4 段階で流れるため、設定ファイル上の位置と実際の動作が対応付くように意識するとミスが減ります。
インストールと起動方法
Envoy は公式バイナリまたは Docker イメージとして配布されており、数ステップでローカル環境にデプロイできます。本節では Linux/macOS 向けのバイナリ取得手順と、Docker を用いた最小構成の起動例を紹介します。どちらの方法でも v1.29.2(2024‑03‑13 リリース)を対象にしています。
公式バイナリの取得手順
まずは GitHub のリリースページから tar.gz をダウンロードし、実行権限を付与します。
|
1 2 3 4 5 6 7 |
# ダウンロード (GitHub Release) curl -L -o envoy.tar.gz \ https://github.com/envoyproxy/envoy/releases/download/v1.29.2/envoy-1.29.2-linux-amd64.tar.gz tar xf envoy.tar.gz sudo mv envoy /usr/local/bin/ |
バージョン確認は次のコマンドで行います。
|
1 2 3 |
envoy --version # → Envoy/1.29.2 (git-...) |
Docker イメージのプルと実行例
Docker Hub の公式イメージ envoyproxy/envoy を利用すれば、設定ファイルだけで即座に起動できます。
|
1 2 3 4 5 6 7 8 |
docker pull envoyproxy/envoy:v1.29-latest docker run -d --name envoy \ -p 10000:10000 -p 9901:9901 \ -v "$(pwd)/envoy.yaml:/etc/envoy/envoy.yaml" \ envoyproxy/envoy:v1.29-latest \ /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --log-level info |
起動直後に以下のようなログが出れば成功です(日時は実行時刻に合わせて表示されます)。
|
1 2 3 4 |
[2024-06-04 10:15:23.123][info][main] starting main thread... [2024-06-04 10:15:23.124][info][listener] adding listener address=0.0.0.0:10000 [2024-06-04 10:15:23.125][info][admin] admin server listening on http://0.0.0.0:9901 |
参考: Docker Hub – envoyproxy/envoy
静的設定ファイルの構造と最小構成例
Envoy が起動時に読み込む 静的設定 は static_resources 配下に必須要素(listeners, clusters)を配置します。本節では最小限の YAML と JSON のサンプルを示し、各フィールドの意味と注意点を解説します。
基本スキーマ(YAML)
以下は「ポート 10000 → バックエンド 127.0.0.1:8080」への単純転送を実現するテンプレートです。
|
1 2 3 4 5 6 7 8 9 10 11 |
static_resources: listeners: [] # 後述のリスナー定義が入ります clusters: [] # 後述のクラスタ定義が入ります admin: access_log_path: /tmp/admin_access.log address: socket_address: address: 0.0.0.0 port_value: 9901 |
リスナー → HTTP Connection Manager → クラスタまで(YAML)
envoy.yaml の全容です。コメントは省略していますが、重要なポイントだけ抜粋します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
static_resources: listeners: - name: listener_10000 address: socket_address: address: 0.0.0.0 port_value: 10000 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: backend domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: service_a } http_filters: - name: envoy.filters.http.router clusters: - name: service_a connect_timeout: 0.25s type: STATIC load_assignment: cluster_name: service_a endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 8080 admin: access_log_path: /tmp/admin_access.log address: socket_address: address: 0.0.0.0 port_value: 9901 |
同等の JSON(抜粋)
JSON でも同様に記述できます。typed_config の @type フィールドは必ず保持してください。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
{ "static_resources": { "listeners": [ { "name": "listener_10000", "address": { "socket_address": { "address": "0.0.0.0", "port_value": 10000 } }, "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": "backend", "domains": ["*"], "routes": [{ "match": { "prefix": "/" }, "route": { "cluster": "service_a" } }] } ] }, "http_filters": [{ "name": "envoy.filters.http.router" }] } } ] } ] } ], "clusters": [ { "name": "service_a", "connect_timeout": "0.250s", "type": "STATIC", "load_assignment": { "cluster_name": "service_a", "endpoints": [ { "lb_endpoints": [ { "endpoint": { "address": { "socket_address": { "address": "127.0.0.1", "port_value": 8080 } } } } ] } ] } } ] }, "admin": { "access_log_path": "/tmp/admin_access.log", "address": { "socket_address": { "address": "0.0.0.0", "port_value": 9901 } } } } |
実装上の注意
-http_connection_managerが無いと HTTP リクエストは処理されません。
-STATICクラスタは開発・テスト向きです。本番ではEDS/STRICT_DNSへ置き換えることを推奨します。
管理 API とデバッグ・プロファイリング
Envoy の admin インターフェース(デフォルト 9901)は、稼働中の設定や統計情報にリアルタイムでアクセスできる強力なツールです。本節では代表的エンドポイントと、ログレベル変更・filter_chain 可視化の実例を示します。
主な admin エンドポイント
| パス | 内容 |
|---|---|
/stats |
全統計項目(リクエスト数、レイテンシ等)をテキストで取得 |
/clusters |
各クラスタのヘルス状態・ロードバランサ情報 |
/listeners |
ロードされたリスナーと filter_chain の詳細 |
/config_dump |
静的+動的設定全体のスナップショット(JSON) |
使用例
bash
curl -s http://localhost:9901/listeners | jq .
ログレベルのリアルタイム切替え
起動時に --log-level を指定するだけでなく、admin API からも変更できます。
|
1 2 3 |
# デバッグログへ一時的に切り替える curl -X POST "http://localhost:9901/logging?level=debug" |
filter_chain の可視化
config_dump の中から ListenersConfigDump を抽出すると、実際に適用されているフィルタ順序が分かります。
|
1 2 3 |
curl -s http://localhost:9901/config_dump \ | jq '.configs[] | select(.["@type"]=="type.googleapis.com/envoy.admin.v3.ListenersConfigDump")' |
ベストプラクティス
admin API はローカル(127.0.0.1)に限定して公開し、ネットワーク上からのアクセスはファイアウォールで遮断してください。
動的設定 (xDS) と Kubernetes 連携
本番環境ではサービスの増減やポッドの再スケジュールに自動追従させるため、xDS API を利用した動的構成が必須です。本節では Envoy が ADS(Aggregated Discovery Service)経由でクラスタ情報を取得する流れと、Kubernetes 上での典型的なデプロイ手順を解説します。
xDS の概念図と主要 API
- ADS: 1 本の gRPC ストリームで CDS・EDS・RDS 等すべてを配信。
- CDS (Cluster Discovery Service): クラスタ定義を動的に提供。
- EDS (Endpoint Discovery Service): 各クラスタのエンドポイント(IP/Port)を通知。
これらは Control Plane(例: Istio Pilot、Envoy‑Control‑Plane)が実装し、Envoy は起動時に ads_config で指定された gRPC エンドポイントへ接続します。
ConfigMap に格納した xDS 設定サンプル
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
apiVersion: v1 kind: ConfigMap metadata: name: envoy-xds-config data: envoy.yaml: | static_resources: listeners: - name: listener_10000 address: socket_address: address: 0.0.0.0 port_value: 10000 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: backend domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: service_a } http_filters: - name: envoy.filters.http.router dynamic_resources: cds_config: ads: {} eds_config: ads: {} ads_config: api_type: GRPC grpc_services: - envoy_grpc: cluster_name: xds_cluster clusters: - name: xds_cluster connect_timeout: 0.25s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: xds_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: envoy-xds-controlplane.default.svc.cluster.local port_value: 18000 |
Kubernetes デプロイマニフェスト(簡易例)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
apiVersion: apps/v1 kind: Deployment metadata: name: envoy-proxy spec: replicas: 2 selector: matchLabels: app: envoy template: metadata: labels: app: envoy spec: containers: - name: envoy image: envoyproxy/envoy:v1.29-latest args: ["-c", "/etc/envoy/envoy.yaml", "--service-cluster", "my-envoy"] ports: - containerPort: 10000 # アプリケーション用 - containerPort: 9901 # admin 用 volumeMounts: - name: envoy-config mountPath: /etc/envoy volumes: - name: envoy-config configMap: name: envoy-xds-config |
デプロイ後は kubectl logs に以下のように表示されます(Control Plane から取得したクラスタ情報がロードされたことを示す)。
|
1 2 3 |
kubectl logs deployment/envoy-proxy -c envoy | grep "added cluster service_a" # ... added cluster 'service_a' via EDS ... |
ポイント
-ads_config.grpc_servicesに記載する DNS 名は Kubernetes の Service 名で解決できることを前提にします。
- ConfigMap が更新されると Envoy は自動的に再取得し、ロールアウト時のダウンタイムが不要になります。
代表的ユースケースと次のステップ
Envoy の機能はリバースプロキシ・ロードバランサ以外にも、ヘッダー操作や高度なリトライ/タイムアウト設定でアプリケーションの信頼性を向上させます。本節では実務でよく使われる 2 パターンを具体例とベストプラクティスと共に示し、学習のロードマップを提示します。
ユースケース 1 – リバースプロキシ+ロードバランシング
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
static_resources: listeners: - name: listener_http 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: api_route virtual_hosts: - name: api_service domains: ["api.example.com"] routes: - match: { prefix: "/" } route: cluster: api_backend timeout: 5s retry_policy: num_retries: 3 per_try_timeout: 2s http_filters: - name: envoy.filters.http.router clusters: - name: api_backend type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: api_backend endpoints: - lb_endpoints: - endpoint: address: socket_address: address: api-backend.default.svc.cluster.local port_value: 8080 |
- ロードバランシングは
ROUND_ROBINがデフォルトで、ヘルスチェック (health_checks) を併用すれば障害時に自動フェイルオーバーが可能です。 - リトライポリシーは外部 API の一過性エラー対策として有効です(
num_retriesとper_try_timeoutを適切に設定)。
ユースケース 2 – ヘッダー操作とタイムアウトのベストプラクティス
|
1 2 3 4 5 6 7 8 9 10 11 |
http_filters: - name: envoy.filters.http.header_to_metadata typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config request_rules: - header: "x-request-id" on_header_present: metadata_namespace: "envoy.lb" key: "request_id" - name: envoy.filters.http.router |
- header_to_metadata フィルタでリクエストヘッダーをメタデータに変換し、後続のロードバランサや認可ロジックで参照できます。
- タイムアウト設定は
route.timeoutのほか、クラスタ側でもconnect_timeout・per_try_timeoutを個別に調整できるため、サービスごとの SLA に合わせたチューニングが可能です。
学習ロードマップの提案
| フェーズ | 目的 | 主な学習項目 |
|---|---|---|
| 1️⃣ 基礎 | 静的設定で単体プロキシを動かす | Listener・Cluster・Filter の関係、admin API |
| 2️⃣ 実践 | Docker/K8s へデプロイし CI に組み込む | Dockerfile、Helm Chart、ConfigMap |
| 3️⃣ 拡張 | xDS と Control Plane を導入 | ADS、CDS/EDS、Istio Pilot の概念 |
| 4️⃣ 最適化 | 可観測性・パフォーマンスチューニング | stats、tracing (OpenTelemetry)、リトライ/タイムアウト |
次のステップ
1. 本稿の YAML をローカルで動かし、admin UI(http://localhost:9901/) にアクセスしてみましょう。
2. 同じ設定を ConfigMap 化し、Kubernetes クラスタへデプロイします。
3. 必要に応じて xDS 用の Control Plane を導入し、動的構成へ移行してください。
参考リンク(外部情報)
- Envoy GitHub Releases: https://github.com/envoyproxy/envoy/releases
- Docker Hub – envoyproxy/envoy: https://hub.docker.com/r/envoyproxy/envoy
- Qiita 記事「Envoy の基本構成」: https://qiita.com/example_user/items/abcdef1234567890(執筆者:example_user、2023‑12‑01)
- Envoy 官方ドキュメント – xDS API: https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol
これらを手元に置きながら実装を進めれば、Envoy の基礎から本番運用まで一貫した知識が身につくはずです。 Happy Envoy!