Envoy のサイトに「Try Envoy」という学習コンテンツがあり,現在は以下の「計11種類」のシナリオから選んで学べる.実際にはブラウザベースで進められる Katacoda の学習コンテンツが埋め込まれているため,特別な環境構築をせずに進められるのは便利.
- Getting Started with Envoy(今回紹介する)
- Migrating from NGINX to Envoy Proxy
- Migrating from HAProxy to Envoy Proxy
- Securing traffic with HTTPS and SSL/TLS
- File Based Dynamic Routing Configuration
- API Based Dynamic Routing Configuration
- Detecting Down Services with Health Checks
- Implementing Blue / Green Rollouts
- Implementing Metrics and Tracing Capabilities
- Debugging Envoy Proxy
- Controlling load balancing policies
学習コンテンツは「Try Envoy」からアクセスできるけど,当然ながら Katacoda にもある.個人的には画面レイアウトの広さという観点から Katacoda を使うと良いと思う.
「Try Envoy」のシナリオを数個試してみて,当然ながら手順通りには動くけど,Envoy 初学者には理解しにくそうな点もあった.そこで,学んだことを整理しつつ,イメージしにくそうな部分をまとめておこうと思う.
Getting Started with Envoy
今回は Envoy に入門するシナリオ「Getting Started with Envoy」を紹介する.Envoy を使ってリクエストを外部サービスに流したり,複数のアプリケーションにパスベースルーティングをする.
手順は以下の「計4種類」ある.サイトに「Estimated Time: 10 minutes」と書いてあるけど,考えながら進めるとすぐに終わらないと思う.時間は参考レベルで見ておくと良さそう.
- Step.1 「Create Proxy Config」
- Step.2 「Start Proxy」
- Step.3 「Admin View」
- Step.4 「Route to Docker Containers」
Step.1 「Create Proxy Config」
最初は Envoy の挙動を設定する envoy.yaml
を作成する.実際にエディタで envoy.yaml
を書く場面はなく,手順上で Copy to Editor
ボタンをクリックすると自動的にエディタに反映される仕組みになっている.Katacoda 便利!その前に基本的な用語を整理しておく.詳細はドキュメントを参照してもらえればと.
Listeners
: リクエストを受ける設定Filters
: リクエストをフィルタする設定(複数のフィルタを設定できる)Clusters
: リクエストを転送する設定
そして envoy.yaml
を読み解く前に構成図を整理しておく.コンテナとして起動した Envoy にリクエストを投げると,そのまま Google に転送される.Envoy を試す最も簡単な構成とも言える.
envoy.yaml
のポイントはザッと以下となる.
listeners
- 10000 Port でリクエストを受ける
filter_chains
route_config
にルーティング設定を書く- プレフィックスが
/
の場合にhost_rewrite
で HTTP Host Header 書き換える service_google
Cluster に転送する
static_resources: listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 10000 } filter_chains: - filters: - name: envoy.http_connection_manager config: stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: { host_rewrite: www.google.com, cluster: service_google } http_filters: - name: envoy.router clusters: - name: service_google connect_timeout: 0.25s type: LOGICAL_DNS dns_lookup_family: V4_ONLY lb_policy: ROUND_ROBIN hosts: [{ socket_address: { address: google.com, port_value: 443 }}] tls_context: { sni: www.google.com } admin: access_log_path: /tmp/admin_access.log address: socket_address: { address: 0.0.0.0, port_value: 9901 }
Envoy で HTTP を制御するフィルタ envoy.http_connection_manager
の詳細は以下のドキュメントに書いてある.
Step.2 「Start Proxy」
さっそく envoy.yaml
を指定して Envoy コンテナを起動する.80 Port にリクエストをすると,Google に転送される.ホスト内だと curl localhost
でも良いし,Katacoda だと https://xxx.environments.katacoda.com
という一時的な URL も使えるため,どちらも使える.
$ docker run --name=proxy -d \ -p 80:10000 \ -v $(pwd)/envoy/envoy.yaml:/etc/envoy/envoy.yaml \ envoyproxy/envoy:latest
Step.3 「Admin View」
次に Envoy の「Administration interface」機能を試す.UI は直感的に理解しにくく感じたけど,メトリクス/統計情報/ログなど,Envoy の状態を確認するときに使える.
$ docker run --name=proxy-with-admin -d \ -p 9901:9901 \ -p 10000:10000 \ -v $(pwd)/envoy/envoy.yaml:/etc/envoy/envoy.yaml \ envoyproxy/envoy:latest
詳しくは以下のドキュメントに書いてある.
Step.4 「Route to Docker Containers」
最後は Python アプリケーションと Envoy を組み合わせて使う.docker-compose.yml
から構成を読み取ると以下となる.リクエストの URL を判断して service1
と service2
にパスベースルーティングをしていて,アプリケーション側は環境変数 SERVICE_NAME
を表示する程度になっている.
なお service1
と service2
は envoyproxy/envoy-alpine:latest
イメージをベースに Python と Flask をインストールしているため,Envoy でよく使われる「サイドカーパターン」になっていない点に注意する.とは言え,今回のように Envoy を試すことが目的の場合は問題ないと言える.
version: '2' services: front-envoy: build: context: . dockerfile: Dockerfile-frontenvoy volumes: - ./front-envoy.yaml:/etc/front-envoy.yaml networks: - envoymesh expose: - "80" - "8001" ports: - "8000:80" - "8001:8001" service1: build: context: . dockerfile: Dockerfile-service volumes: - ./service-envoy.yaml:/etc/service-envoy.yaml networks: envoymesh: aliases: - service1 environment: - SERVICE_NAME=1 expose: - "80" service2: build: context: . dockerfile: Dockerfile-service volumes: - ./service-envoy.yaml:/etc/service-envoy.yaml networks: envoymesh: aliases: - service2 environment: - SERVICE_NAME=2 expose: - "80" networks: envoymesh: {}
front-envoy
の front-envoy.yaml
を以下に載せる.ポイントは filters
の routes
に2種類の prefix
が設定されている点で,URL によって転送する Cluster を変えている.
static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 80 filter_chains: - filters: - name: envoy.http_connection_manager config: codec_type: auto stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: backend domains: - "*" routes: - match: prefix: "/service/1" route: cluster: service1 - match: prefix: "/service/2" route: cluster: service2 http_filters: - name: envoy.router config: {} clusters: - name: service1 connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service1 port_value: 80 - name: service2 connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service2 port_value: 80 admin: access_log_path: "/dev/null" address: socket_address: address: 0.0.0.0 port_value: 8001
実際に起動すると,期待した通りにリクエストをルーティングできた.
$ docker-compose -f ~/envoy/examples/front-proxy/docker-compose.yml up -d $ curl localhost:8000/service/1 Hello from behind Envoy (service 1)! hostname: 211d6aaf214c resolvedhostname: 172.19.0.3 $ curl localhost:8000/service/2 Hello from behind Envoy (service 2)! hostname: 30ce9b84004a resolvedhostname: 172.19.0.2
まとめ
- Envoy のサイトに「Try Envoy」という学習コンテンツがある
- 現在は「計11種類」のシナリオから選べる
- 今回は「Getting Started with Envoy」を試した
- リクエストを外部サービスに流したり,複数のアプリケーションにパスベースルーティングをしたり,基本的な動作確認はできる
- まだ「Envoy の良さ」を感じられる内容ではなく,引き続き「Try Envoy」を進めていく