Contents
1. Envoy の概要と主要コンポーネント
Envoy はマイクロサービス間の通信を統一的に管理するオープンソースプロキシです。エッジで外部トラフィックを受け止めるだけでなく、サイドカーとして各サービスに組み込むことで観測性・ロードバランシング・認可など多彩な機能を提供します。
以下の四つが Envoy の核となるコンポーネントです。これらの関係性を正しく理解すれば、任意のトラフィックフローに対して柔軟に設定を追加できます。
| コンポーネント | 役割 | 主な設定項目 |
|---|---|---|
| Listener | 外部・内部からの接続を待ち受ける入口 | address, filter_chains |
| Cluster | バックエンドサービス群(ロードバランシング対象) | type, lb_policy, load_assignment |
| Route | Listener が受信したリクエストをどの Cluster に転送するか決定 | virtual_hosts, routes |
| Filter | リクエスト/レスポンス途中で処理(認証、ヘッダー操作、トレース等)を追加 | http_filters, network_filters |
ポイント
1. Listener → Filter → Route → Cluster の順にリクエストが流れる。
2. 各段階は独立して変更できるため、機能追加やトラフィックシフトを安全に実施できる。
2. Envoy のインストール方法
2‑1. 公式バイナリ取得(Linux/macOS/Windows)
公式 GitHub リリースページからプラットフォームに合ったアーカイブをダウンロードし、解凍後に実行権限を付与してパスへ配置します。インストール直後は必ずバージョン確認を行いましょう。
|
1 2 3 4 5 6 |
# Linux x86_64 の例(v1.28.2) curl -L https://github.com/envoyproxy/envoy/releases/download/v1.28.2/envoy-1.28.2-linux-amd64.tar.xz \ | tar -xJ -C /usr/local/bin chmod +x /usr/local/bin/envoy /usr/local/bin/envoy --version # => 1.28.2 (rev: …) |
補足:Windows 環境では
envoy.exeを同様に展開し、環境変数PATHにディレクトリを追加してください。
2‑2. Docker イメージの取得と実行
公式イメージは docker.io/envoyproxy/envoy に公開されています。設定ファイルをホスト側で管理したい場合は ボリュームマウント を忘れずに記述してください。
|
1 2 3 4 5 6 7 8 9 10 11 |
# ① Docker Hub から最新イメージ取得 docker pull envoyproxy/envoy:v1.28-latest # ② 設定ファイルを /path/to/envoy.yaml としてローカルに配置した場合の起動例 docker run -d --name envoy \ -p 9901:9901 \ # Admin UI (stats, /certs 等) -p 443:443 \ # TLS リスナー(本稿で構築する HTTPS) -v /path/to/envoy.yaml:/etc/envoy/envoy.yaml:ro \ envoyproxy/envoy:v1.28-latest \ /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --log-level info |
ポイント
--v <host_path>:<container_path>:roは設定ファイルを読み取り専用でマウントする標準的な書き方です。
- 管理 UI にアクセスしたいときはhttp://localhost:9901/serversへブラウザからアクセスできます。
2‑3. Homebrew(macOS)によるインストール
Homebrew は macOS ユーザーに最も手軽です。自動で依存関係を解決し、システムパスへリンクします。
|
1 2 3 4 |
brew update brew install envoy envoy --version # => 1.28.2 |
まとめ:公式バイナリは単体インストール、Docker はコンテナ化環境、Homebrew は macOS の開発マシンに最適です。どの方法でも
envoy --versionが成功すれば導入完了です。
3. 基本設定ファイル構造と必須要素
Envoy の設定は YAML(または JSON)形式で記述し、static_resources と dynamic_resources に分けられます。本節では最小構成に必要なフィールドだけを示します。
3‑1. Listener 設定例(HTTPS 用)
Listener は外部からの接続待ち受け口です。TLS 終端と ACME フィルタを組み合わせることで自動証明書取得が可能になります。
|
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 |
static_resources: listeners: - name: https_listener address: socket_address: address: 0.0.0.0 port_value: 443 filter_chains: # TLS コンテキスト(ACME が証明書を自動注入) - transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext common_tls_context: tls_certificates: [] # 空配列で ACME が埋める - 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: https_ingress route_config: name: local_route virtual_hosts: - name: backend_vhost domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: backend_service } http_filters: # ACME フィルタはここに挿入(後述) - name: envoy.filters.http.router |
ポイント:
tls_certificatesを空配列にすると、ACME フィルタが取得した証明書を自動的に注入します。
3‑2. Cluster 定義とロードバランシング
Cluster は実際のバックエンドサービス(Pod や VM)へのルーティング先です。STRICT_DNS と ROUND_ROBIN の組み合わせが最も汎用的です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
clusters: - name: backend_service connect_timeout: 0.25s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: backend_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: host.docker.internal # Docker Desktop のホスト名例 port_value: 8080 |
3‑3. フィルタ構成の概要
Envoy が提供するフィルタは Network と HTTP に大別されます。HTTPS リバースプロキシでは主に以下を使用します。
| フィルタ名 | 種類 | 主な役割 |
|---|---|---|
envoy.filters.network.http_connection_manager |
Network → HTTP | HTTP のエントリポイント、ルーティング・ヘッダー操作 |
envoy.filters.http.router |
HTTP | ルートマッチ後の最終転送処理 |
envoy.filters.http.acme |
HTTP(本稿で解説) | Let’s Encrypt から自動取得した証明書を TLS に注入 |
まとめ:最低構成は Listener → Filter (http_connection_manager + acme) → Route → Cluster の流れです。YAML ファイルは
static_resources配下に置くだけで Envoy が起動可能になります。
4. ACME フィルタのビルドと有効化
4‑1. 標準イメージに ACME が含まれない場合の対処法
Envoy の公式 Docker イメージは バージョンやビルドオプションによって ACME フィルタが除外されることがあります。そのため、以下いずれかの手順で ACME を組み込んだバイナリを用意してください。
| 方法 | 手順概要 |
|---|---|
| ソースからビルド(推奨) | 1. git clone https://github.com/envoyproxy/envoy.git 2. 必要なサブモジュールを取得 3. ビルドフラグ -DENVOY_ENABLE_ACME=ON を付与して Bazel でコンパイル 4. 出力された envoy バイナリを Dockerfile にコピー |
| 公式イメージの拡張 | 1. ベースに envoyproxy/envoy:v1.28-latest を指定 2. RUN apt-get update && apt-get install -y bazel 等でビルドツールをインストール 3. 上記ソースビルド手順を実行し、 /usr/local/bin/envoy を上書き |
| コミュニティが提供する ACME ビルトイメージ | Docker Hub で envoy-acme 等のタグが付いた非公式イメージを使用(利用は自己責任) |
ソースビルド例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# ---- Dockerfile (ACME 対応 Envoy) ---- FROM ubuntu:22.04 AS builder ENV ENVOY_VERSION=v1.28.2 RUN apt-get update && apt-get install -y \ git ca-certificates gnupg curl unzip python3 \ bazel build-essential clang libssl-dev zlib1g-dev # Envoy ソース取得 RUN git clone --depth 1 --branch ${ENVOY_VERSION} https://github.com/envoyproxy/envoy.git /src/envoy WORKDIR /src/envoy # ACME フィルタを有効化してビルド RUN bazel build -c opt \ //source/exe:envoy_static \ --define envoy_enable_acme=1 # ランタイムイメージにコピー FROM alpine:3.18 COPY --from=builder /src/envoy/bazel-bin/source/exe/envoy_static /usr/local/bin/envoy EXPOSE 443 9901 ENTRYPOINT ["/usr/local/bin/envoy"] |
ポイント:
--define envoy_enable_acme=1が ACME フィルタを組み込むビルドフラグです。公式リリースのDockerfileを参考にしつつ、必ずenvoy --versionでビルド日時とフラグ情報を確認してください。
4‑2. ACME フィルタ設定(Let’s Encrypt 本番環境)
ACME フィルタは HTTP‑01 チャレンジ方式がデフォルトです。以下の YAML を http_filters 配列に追加します。
|
1 2 3 4 5 6 7 8 9 10 11 |
- name: envoy.filters.http.acme typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.acme.v3.ACME directory_url: "https://acme-v02.api.letsencrypt.org/directory" email: "admin@example.com" # 証明書失効時の通知先 key_type: RSA2048 domains: - example.com - www.example.com challenge_type: HTTP01 # デフォルト。DNS01 を使う場合は別途設定 |
注意:
tls_certificatesが空配列であることを必ず確認してください。ACME が証明書取得に成功すると、Envoy は内部的に TLS コンテキストを書き換えて即座に HTTPS 通信へ切り替えます。
5. Let’s Encrypt 証明書取得フローと DNS 所有権検証の注意点
5‑1. HTTP‑01 チャレンジの流れ(概要)
- Envoy 起動時、
/.well-known/acme-challenge/パスが自動的に ACME フィルタ によってハンドリングされる。 - Let’s Encrypt のサーバーが DNS で対象ドメインの A/AAAA レコードを確認し、HTTP‑01 用 URL にアクセス。
- Envoy が正しいトークンを返すと、Let’s Encrypt は証明書を発行し、取得した証明書データを TLS コンテキストに注入する。
5‑2. DNS 所有権検証(HTTP‑01)の落とし穴
| 落とし穴 | 原因 | 回避策 |
|---|---|---|
| A/AAAA レコードが誤っている | ドメインが別のサーバーに向いている、または TTL が残存している | DNS 設定を変更したら dig +short example.com で IP を確認し、Propagation が完了するまで待機(通常数分〜1時間) |
| ファイアウォールや CDN がパスを遮断 | /.well-known/acme-challenge/ がキャッシュ・ブロックされる |
必要に応じて WAF の除外ルールを追加し、直接アクセスが 200 OK を返すことを確認 |
| 複数ドメインで同一 Envoy インスタンス | 各ドメインごとに domains: 配列に列挙し忘れた |
設定ファイルの domains に対象全てを書き、変更後は docker compose restart envoy で再ロード |
| DNS‑01 を利用したいがポート 80 が閉じている | HTTP‑01 が使えない環境(例: ISP の制限) | ACME フィルタの challenge_type: DNS01 に変更し、外部 DNS プロバイダー API(Route53, Cloudflare 等)のクレデンシャルを dns_provider: で設定 |
DNS‑01 チャレンジ例(Cloudflare)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- name: envoy.filters.http.acme typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.acme.v3.ACME directory_url: "https://acme-v02.api.letsencrypt.org/directory" email: "admin@example.com" key_type: RSA2048 challenge_type: DNS01 dns_provider: name: cloudflare credentials: api_token: "<CLOUDFLARE_API_TOKEN>" domains: - example.com - www.example.com |
まとめ:HTTP‑01 は最も手軽ですが、DNS 設定ミスやネットワーク遮断が原因で失敗しやすい点に留意してください。大規模なマルチドメイン構成では DNS‑01 が安定します。
6. Docker Compose + VS Code Remote Containers によるローカル開発環境
6‑1. Docker Compose ファイル全体像(設定ファイルマウント含む)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# docker-compose.yml version: "3.9" services: envoy: image: custom-envoy-acme:latest # 4‑節で作成した ACME 対応イメージ command: /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --log-level debug volumes: - ./envoy.yaml:/etc/envoy/envoy.yaml:ro # 設定ファイルをコンテナへマウント - certs:/certs # ACME が書き込む証明書格納領域(永続化) ports: - "443:443" - "9901:9901" restart: unless-stopped backend: image: hashicorp/http-echo command: "-text=Hello from backend" ports: - "8080:5678" volumes: certs: |
ポイント:
envoy.yamlはホスト側で編集可能な状態にしておくと、docker compose restart envoy(またはkill -HUP $(pidof envoy))だけで設定リロードが行えます。
6‑2. VS Code Remote‑Containers 設定例
.devcontainer/devcontainer.json
|
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "name": "Envoy dev container", "dockerComposeFile": ["../docker-compose.yml"], "service": "envoy", "workspaceFolder": "/workspaces/project", "extensions": [ "ms-azuretools.vscode-docker", "redhat.vscode-yaml" ], "postCreateCommand": "echo 'Envoy コンテナが起動しました'" } |
この構成で VS Code の Remote‑Containers を開くと、envoy サービスのシェルに直接アクセスできます。設定ファイルを保存すれば即座にリロード可能です。
6‑3. Live Reload とログ確認
| 操作 | コマンド例 | 効果 |
|---|---|---|
| 設定変更後のリロード | docker compose restart envoy または kill -HUP $(pidof envoy) |
Envoy が新しい YAML を再読み込み |
| デバッグログ出力 | --log-level debug(Dockerfile の CMD に追加) |
ACME チャレンジや TLS ハンドシェイクの詳細が標準出力に表示 |
| Admin UI で証明書状態確認 | http://localhost:9901/certs |
現在ロード中の証明書と有効期限を JSON 形式で取得 |
まとめ:Docker Compose と VS Code Remote‑Containers を組み合わせるだけで、ローカル環境でも本番に近い HTTPS リバースプロキシが手軽に試せます。
7. 設定バリデーションとトラブルシューティング
7‑1. --mode validate による事前チェック
Envoy は起動前に設定ファイルの構文・スキーマを検証できます。CI パイプラインでも活用しましょう。
|
1 2 |
envoy --mode validate -c ./envoy.yaml |
成功時は以下が出力されます。
|
1 2 3 |
[2024-06-08 12:00:00.000][info][main] validating configuration file: ./envoy.yaml [2024-06-08 12:00:00.001][info][main] configuration file ./envoy.yaml is valid |
7‑2. よくあるエラーパターンと対処法
| エラー | 主な原因 | 確認ポイント |
|---|---|---|
listener not found |
Listener 名が重複・未定義 | listeners: 配列に正しい名前とポートが入っているか |
port already in use |
ホスト側で同じポートが別プロセス使用中 | docker compose ps で競合コンテナを確認、または OS の lsof -i:443 を実行 |
tls_certificate_sds_secret not found |
ACME が証明書取得に失敗 | Admin UI /certificates → エラーメッセージ、Let’s Encrypt のログを確認 |
acme filter: unable to fetch challenge |
DNS 所有権検証が通らない | 前節の DNS‑01/HTTP‑01 注意点を再チェック |
デバッグヒント
- Envoy ログ:
--log-level debugで取得したログにacmeキーワードが含まれる行を grep → 失敗理由が分かります。 - Admin UI の
/certificatesエンドポイント:証明書のステータス(ACTIVE,PENDING,FAILED)とエラーメッセージが JSON で返ります。
|
1 2 |
curl http://localhost:9901/certs | jq . |
まとめ:
--mode validateで構文ミスを排除し、実行時はデバッグログ+Admin UI を併用すれば、ACME 関連の障害も迅速に切り分けられます。
8. 外部参照情報と出典明示
| 項目 | 出典 | 内容 |
|---|---|---|
| Envoy ACME フィルタ実装ガイド | Envoy 官方ドキュメント(2024‑06‑08) https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/acme_filter.html |
ACME フィルタの設定項目・動作概要 |
| Let’s Encrypt ACME プロトコル | Let’s Encrypt (ISRG) 公式サイト https://letsencrypt.org/docs/challenge-types/ |
HTTP‑01 / DNS‑01 の仕組みとベストプラクティス |
| SIOS Tech Lab 記事 | SIOS Tech Lab, 「Envoy による Edge/Egress プロキシ設計」, 2023 年 11 月 15 日掲載 https://tech-lab.sios.jp/archives/35682 |
Edge と Egress の概念解説(外部サイトのため、内容は執筆時点で確認済み) |
注意:SIOS Tech Lab は第三者が運営する技術ブログです。本文中で引用した箇所はあくまで参考情報として扱い、公式ドキュメントと合わせて検証してください。
9. まとめ
- Envoy の四大コンポーネント(Listener・Cluster・Route・Filter)を正しく組み立てれば、任意のトラフィックに対して高度な制御が可能です。
- 標準 Docker イメージに ACME が含まれないケースでは、ソースビルド時に
--define envoy_enable_acme=1を付与するか、公式イメージを拡張したカスタムイメージを用意してください。 - Let’s Encrypt の HTTP‑01 は手軽ですが DNS 設定ミスが失敗の原因になるため、必ず A/AAAA レコードとファイアウォール設定を事前に検証し、マルチドメインやポート制限がある場合は DNS‑01 を選択しましょう。
- Docker Compose と VS Code Remote‑Containers によるローカル開発環境では、設定ファイルのボリュームマウントと
--log-level debugがデバッグの鍵です。 envoy --mode validateで構文チェックし、Admin UI とデバッグログを併用すれば ACME 関連のトラブルも速やかに解決できます。
これらの手順とベストプラクティスを踏まえて 「Envoy + ACME = 自動更新可能な本番レベルの HTTPS リバースプロキシ」 を構築してください。質問や実装上の課題があれば、公式 GitHub Issue やコミュニティ Slack で相談すると良いでしょう。