今回は「Try Envoy」の「API Based Dynamic Routing Configuration」を紹介する.前回紹介した「File Based Dynamic Routing Configuration」と関連した内容だけど,今回は API を使った「ディスカバリサービス (xDS)」を学べる.特に Envoy は REST と gRPC をサポートしているけど,今回のコンテンツだと REST を学べる.なお,前回の記事も載せておく.
API Based Dynamic Routing Configuration
手順は以下の「計7種類」ある.今までの Katacoda と同じく文章だと理解しにくい点も多く,自分なりに理解を整理しながら進めた.
- Step.1 「Introduction」
- Step.2 「EDS Configuration」
- Step.3 「Start upstream services」
- Step.4 「Start EDS」
- Step.5 「Add endpoint to EDS」
- Step.6 「Delete Endpoint」
- Step.7 「Disconnect EDS server」
Step.1 「Introduction」
今回は EDS (Endpoint Discovery Service) を REST API を使って実現することにより,エンドポイント情報を取得する.過去記事の内容を復習すると,エンドポイントはクラスタメンバーと表現することもできて,転送先のことを意味する.xDS API を実装する場合,現在だと Java と Go でコントロールプレーンの実装 (gRPC + Protocol Buffers) が Envoy から公開されていて参考になる.ただし,今回は独自実装の API を試す.
- GitHub - envoyproxy/java-control-plane: Java implementation of an Envoy gRPC control plane
- GitHub - envoyproxy/go-control-plane: Go implementation of data-plane-api
Step.2 「EDS Configuration」
envoy.yaml
の設定は前回と似ている.今回異なるのは eds_config
に api_config_source
を設定している点で「File Based」のときは path
を設定していた.さらに今回は EDS API として,もう1個 Cluster eds_cluster
を追加している.なお,api_type
は REST
(v2) と REST_LEGACY
(v1) があり,既に API v1 は deprecated になっている.API v2 の詳細は以下のドキュメントに載っている.
clusters: - name: targetCluster type: EDS connect_timeout: 0.25s eds_cluster_config: service_name: myservice eds_config: api_config_source: api_type: REST cluster_names: [eds_cluster] refresh_delay: 5s - name: eds_cluster type: STATIC connect_timeout: 0.25s hosts: [{ socket_address: { address: 172.18.0.4, port_value: 8080 }}]
さっそく Envoy を起動する.ただし,EDS API はまだ存在してなく設定のみとなる.構成図は以下のようになる.
$ docker run --name=api-eds -d \ -p 9901:9901 \ -p 80:10000 \ -v /root/:/etc/envoy \ envoyproxy/envoy:latest
Step.3 「Start upstream services」
今回も katacoda/docker-http-server
を起動し,個別に接続確認をしておく.
$ docker run -p 8081:8081 -d -e EDS_SERVER_PORT='8081' katacoda/docker-http-server:v4 $ curl http://localhost:8081 -i HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 36 Server: Werkzeug/0.15.4 Python/2.7.16 Date: Thu, 26 Dec 2019 00:00:00 GMT 35c4aef0-e0df-46ac-bd3b-8b12cb3741c9
ただし,コンテナイメージのタグが v4
になっていて,サイズも大きく,何やら Python 環境が入っているけど,詳細は書かれていなかった.あと,環境変数 EDS_SERVER_PORT
が追加されている点も異なる.
$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" katacoda/docker-http-server REPOSITORY TAG SIZE katacoda/docker-http-server v4 932MB katacoda/docker-http-server latest 7.59MB
Envoy のログを確認すると,まだ EDS API に接続できず,エラーになっている.
$ docker logs xxx [2019-12-26 00:00:00.000][000008][warning][config] [bazel-out/k8-opt/bin/source/common/config/_virtual_includes/http_subscription_lib/common/config/http_subscription_impl.h:101] REST config update failed: fetch failure
構成図は以下のようになる.
Step.4 「Start EDS」
次にやっと EDS API を起動する.今回は Python で実装されたプロトタイプを使うことになり,コードは GitHub に公開されている.ここで Envoy と EDS API の接続はできたけど,まだエンドポイントが設定されてなく,実際に Envoy にリクエストを送ると no healthy upstream
と返ってくる.挙動としては期待値と言える.
$ docker run -p 8080:8080 -d katacoda/eds_server; $ curl http://localhost no healthy upstream
構成図は以下のようになる.
Step.5 「Add endpoint to EDS」
次に EDS API に curl
でリクエストを送り,エンドポイントを追加する.今回は既に起動済の katacoda/docker-http-server
にルーティングする.
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ "hosts": [ { "ip_address": "172.18.0.3", "port": 8081, "tags": { "az": "us-central1-a", "canary": false, "load_balancing_weight": 50 } } ] }' http://localhost:8080/edsservice/myservice
Envoy にリクエストを送ると,同じ結果が返ってくる.
$ curl http://localhost 35c4aef0-e0df-46ac-bd3b-8b12cb3741c9 $ curl http://localhost 35c4aef0-e0df-46ac-bd3b-8b12cb3741c9
次に katacoda/docker-http-server
を4コンテナ追加し,計5コンテナになる.
$ for i in 8082 8083 8084 8085 do docker run -d -e EDS_SERVER_PORT=$i katacoda/docker-http-server:v4; sleep .5 done
追加した4コンテナをエンドポイントとして EDS API に追加する.なお,設定している load_balancing_weight
はドキュメントを読むと「合計値をエンドポイント数で割る」と書いてあるため,5コンテナに均等分散するという意味になる.
$ curl -X PUT --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ "hosts": [ { "ip_address": "172.18.0.3", "port": 8081, "tags": { "az": "us-central1-a", "canary": false, "load_balancing_weight": 50 } }, { "ip_address": "172.18.0.5", "port": 8082, "tags": { "az": "us-central1-a", "canary": false, "load_balancing_weight": 50 } }, { "ip_address": "172.18.0.6", "port": 8083, "tags": { "az": "us-central1-a", "canary": false, "load_balancing_weight": 50 } }, { "ip_address": "172.18.0.7", "port": 8084, "tags": { "az": "us-central1-a", "canary": false, "load_balancing_weight": 50 } }, { "ip_address": "172.18.0.8", "port": 8085, "tags": { "az": "us-central1-a", "canary": false, "load_balancing_weight": 50 } } ] }' http://localhost:8080/edsservice/myservice
実際に Envoy にリクエストを送ると,うまく分散されている.エンドポイント数が少ないからかもしれないけど,たまに2回連続で同じコンテナからレスポンスが返ることもあった.
$ while true; do curl http://localhost; sleep .5; printf '\n'; done dbc1fe2f-7bfa-44e6-8fff-52a57190de95 28959add-c2df-47cf-8045-c09911a9e913 8d366f05-18d8-4f72-936f-ab282615f6ca f7f7599d-1be9-480c-96e9-6619b2843499 35c4aef0-e0df-46ac-bd3b-8b12cb3741c9
構成図は以下のようになる.
Step.6 「Delete Endpoint」
今度は EDS API から5コンテナの情報を消す.すると,Step.4 と同じ no healthy upstream
となった.
$ curl -X PUT --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ "hosts": [ ] }' http://localhost:8080/edsservice/myservice $ curl -v http://localhost no healthy upstream
Step.7 「Disconnect EDS server」
最後は Step.5 と同じくもう1度 EDS API にエンドポイントを追加してから,EDS API を停止する.
$ docker ps -a | awk '{ print $1,$2 }' | grep katacoda/eds_server | awk '{print $1 }' | xargs -I {} docker stop {}; $ docker ps -a | awk '{ print $1,$2 }' | grep katacoda/eds_server | awk '{print $1 }' | xargs -I {} docker rm {}
一度 Envoy 側で EDS API からエンドポイント情報を取得した場合,Envoy 側には影響なしで使えることがわかる.
$ while true; do curl http://localhost; sleep .5; printf '\n'; done 35c4aef0-e0df-46ac-bd3b-8b12cb3741c9 dbc1fe2f-7bfa-44e6-8fff-52a57190de95 8d366f05-18d8-4f72-936f-ab282615f6ca f7f7599d-1be9-480c-96e9-6619b2843499 28959add-c2df-47cf-8045-c09911a9e913
構成図は以下のようになる.
まとめ
- 「Try Envoy」のコンテンツ「API Based Dynamic Routing Configuration」を試した
- EDS (Endpoint Discovery Service) API を REST で起動し,エンドポイントの dynamic な反映を体験できた
katacoda/docker-http-server:v4
の解説がなかったり,gRPC の xDS API の体験がなかったり,もう少し学びたかった点もある
引き続き,進めていくぞ!
Try Envoy 関連
- 「Try Envoy」で Envoy を学ぼう!「Getting Started with Envoy」を試した - kakakakakku blog
- nginx と Envoy の設定を比較して学べる「Migrating from NGINX to Envoy Proxy」を試した - kakakakakku blog
- Envoy で HTTPS 接続をする設定を学べる「Securing traffic with HTTPS and SSL/TLS」を試した - kakakakakku blog
- Envoy のディスカバリサービス (xDS) を学べる「File Based Dynamic Routing Configuration」を試した - kakakakakku blog