好奇心の赴くままに

好奇心の赴くままに

やりたいことを書いています。

Try EnvoyのGetting Started with EnvoyでEnvoyに入門してみる

最近Envoyを勉強する機運が高まっていて、 Envoyでいい感じのチュートリアルがないか探してみたら、有名ブロガーのカックさんが紹介していたTry EnvoyがEnvoyの入門に良さそうだったので、
Try EnvoyGetting Started with Envoyをやってみました.

kakakakakku.hatenablog.com

Try Envoy

Try EnvoyはKatacodaで提供されているEnvoyを学習できるプラットフォームで 全部で12個のEnvoyに関するコースがあります. www.envoyproxy.io

Getting Started with Envoy

以下の4つの手順で構成されています.

  1. Create Proxy Config
  2. Start Proxy
  3. Admin View
  4. Route to Docker Containers

1. Create Proxy Config

envoy.yamlの書き方について学ぶ.
内容としては、Envoyコンテナにリクエストを投げると、google.comに転送される設定になっている.
以下進める上でのポイント

  • envoy.yamlは、Listeners,Fillters,Clustersの3要素から構成されている.
  • Listeners には、リクエストを受ける設定を書く
  • Fillters には、どのようにリクエストを処理するかをかく
  • Clusters には、リクエストの転送先を書く

実際のenvoy.yamlファイルは以下

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 }

2. Start Proxy

先ほど作成したenvoy.yamlでEnovyコンテナを起動する

$ docker run --name=proxy -d \
  -p 80:10000 \
  -v $(pwd)/envoy/envoy.yaml:/etc/envoy/envoy.yaml \
  envoyproxy/envoy:latest

起動したEnvoyコンテナにアクセスするとgoogle.comに転送されることが確認できる.

3. Admin View

先ほどのenvoy.yamlのadminの部分で設定していた Administration interfaceの機能を試す.

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

Administration interfaceでは、起動したEnvoyの統計情報、メトリクスなどが確認できる.
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

以下ような画面が確認できる.

4. Route to Docker Containers

Envoyコンテナとその背後に2つのPythonアプリケーションがあり、 Envoyへのリクエストを背後のPythonアプリケーションにそれぞれパスベースでルーティングする 構成になっている. (service/1へのリクエストはService1,service/2へのリクエストはService2にルーティングされる)

Envoyとその背後の2つのFlaskコンテナは以下のようなdocker-compose.yamlファイルで 構築されている.

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: {}

Enovyコンテナのenvoy.yamlファイルは以下. routesの部分で今回のパスベースルーティングの設定をしている.

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

実際に起動して、リクエストすると想定通りにEnvoyへのリクエストが パスルーティングされて背後のPythonアプリケーションに転送されることが確認できた.

$ docker-compose -f ~/envoy/examples/front-proxy/docker-compose.yml up -d
$ curl localhost:8000/service/1
Hello from behind Envoy (service 1)! hostname: 35cfe0a1d806 resolvedhostname: 172.17.0.2
$ curl localhost:8000/service/2
Hello from behind Envoy (service 2)! hostname: d72bb6cc73d0 resolvedhostname: 172.17.0.4

まとめ

とっつきにくかったEnovyについて前よりほんの少し馴染めるようになった気がする.

参考

www.envoyproxy.io kakakakakku.hatenablog.com