kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Envoy のディスカバリサービス (xDS) を学べる「File Based Dynamic Routing Configuration」を試した

今回は「Try Envoy」「File Based Dynamic Routing Configuration」を紹介する.今までの内容は envoy.yaml に static な設定をしていたけど,設定を dynamic に反映できる Envoy の「ディスカバリサービス (xDS)」を学べる.また Envoy は xDS として「File Based(ファイル)」「API Based(REST / gRPC)」をサポートしている.今回は「File Based」を試す.

File Based Dynamic Routing Configuration

手順は以下の「計8種類」ある.それでもなお「Estimated Time: 10 minutes」と書いてあって,雑すぎるでしょ!

  • Step.1 「Envoy Dynamic Configuration」
  • Step.2 「Cluster ID」
  • Step.3 「EDS Configuration」
  • Step.4 「EDS Configuration」
  • Step.5 「Start Envoy」
  • Step.6 「Apply Changes」
  • Step.7 「CDS Configuration」
  • Step.8 「CDS Apply Changes」

www.envoyproxy.io

www.katacoda.com

Step.1 「Envoy Dynamic Configuration」

Envoy には,今まで使ってきた static な設定以外に dynamic な設定があり,「ディスカバリサービス (xDS)」と言う.xDS と言われている通り,様々な種類がある.今回のコンテンツでは「EDS / CDS / LDS」を試す.

  • EDS (Endpoint Discovery Service)
  • CDS (Cluster Discovery Service)
  • RDS (Route Discovery Service)
  • LDS (Listener Discovery Service)
  • SDS (Secret Discovery Service)

ドキュメントを読むと,コンテンツに載っている xDS 以外にも種類があった.例えば,以下など.

  • VHDS (Virtual Host Discovery Service)
  • SRDS (Scoped Route Discovery Service)
  • RTDS (RunTime Discovery Service)

www.envoyproxy.io

Step.2 「Cluster ID」

最初に envoy.yamlnode を設定する.この設定は今までのコンテンツには出てこなかった.xDS を使うときに Envoy 自体を識別する ID となり,今回は適当に id_1 とした.

node:
  id: id_1
  cluster: test

Step.3 「EDS Configuration」

今までは envoy.yamlclusters に転送するホストを static に設定していたけど,今回は EDS (Endpoint Discovery Service) を使うため eds_configeds.conf を指定する.ファイル自体は Step.4 で作成する.

clusters:
- name: targetCluster
  connect_timeout: 0.25s
  lb_policy: ROUND_ROBIN
  type: EDS
  eds_cluster_config:
    service_name: localservices
    eds_config:
      path: '/etc/envoy/eds.conf'

今回は「File Based」なので path を指定した.もし api_config_source を指定すると「API Based」になる.

www.envoyproxy.io

Step.4 「EDS Configuration」

次に eds.conf を作成する.まず,エンドポイントを1個にして,IP アドレスを 172.18.0.3 にする.

{
  "version_info": "0",
  "resources": [{
    "@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
    "cluster_name": "localservices",
    "endpoints": [{
      "lb_endpoints": [{
        "endpoint": {
          "address": {
            "socket_address": {
              "address": "172.18.0.3",
              "port_value": 80
            }
          }
        }
      }]
    }]
  }]
}

Step.5 「Start Envoy」

実際に Envoy と katacoda/docker-http-server を起動し,以下の構成図のようになる.

$ docker run --name=proxy-eds-filebased -d \
    -p 9901:9901 \
    -p 80:10000 \
    -v /root/:/etc/envoy \
    envoyproxy/envoy:latest

$ docker run -d katacoda/docker-http-server

$ docker run -d katacoda/docker-http-server

f:id:kakku22:20191217065539p:plain

eds.conf にエンドポイントを1個しか設定していないため,何度リクエストを送っても,特定のコンテナに転送される.

$ curl localhost
<h1>This request was processed by host: c9d6a2229f32</h1>

$ curl localhost
<h1>This request was processed by host: c9d6a2229f32</h1>

$ curl localhost
<h1>This request was processed by host: c9d6a2229f32</h1>

Step.6 「Apply Changes」

eds.conf を修正し,エンドポイントを2個にする.以下の構成図のようになる.

{
  "version_info": "0",
  "resources": [{
    "@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
    "cluster_name": "localservices",
    "endpoints": [{
      "lb_endpoints": [{
        "endpoint": {
          "address": {
            "socket_address": {
              "address": "172.18.0.3",
              "port_value": 80
            }
          }
        }
      },
        {
        "endpoint": {
          "address": {
            "socket_address": {
              "address": "172.18.0.4",
              "port_value": 80
            }
          }
        }
      }]
    }]
  }]
}

f:id:kakku22:20191217065554p:plain

修正した eds.conf を Envoy に自動的に反映するために mv コマンドを使ってファイルを差し替える.ドキュメントにも記載がある通り,Envoy はファイルの mv を監視している.

# Envoy will only watch the file path for moves.
$ mv eds.conf tmp; mv tmp eds.conf

直後に Envoy にリクエストを送ると,Envoy コンテナを再起動せずに eds.conf を反映できた.

$ curl localhost
<h1>This request was processed by host: c9d6a2229f32</h1>

$ curl localhost
<h1>This request was processed by host: edd664e9d604</h1>

$ curl localhost
<h1>This request was processed by host: c9d6a2229f32</h1>

$ curl localhost
<h1>This request was processed by host: edd664e9d604</h1>

Step.7 「CDS Configuration」

最後 2 Steps は CDS (Cluster Discovery Service)LDS (Listener Discovery Service) を試す.まず,CDS の設定となる cds.conf を作成する.既に作成した EDS と連携している.

{
  "version_info": "0",
  "resources": [{
    "@type": "type.googleapis.com/envoy.api.v2.Cluster",
    "name": "targetCluster",
    "connect_timeout": "0.25s",
    "lb_policy": "ROUND_ROBIN",
    "type": "EDS",
    "eds_cluster_config": {
      "service_name": "localservices",
      "eds_config": {
        "path": "/etc/envoy/eds.conf"
      }
    }
  }]
}

次に LDS の設定をする lds.conf を作成する.今まで envoy.yaml に設定していた filters を LDS に移したイメージとなる.

{
  "version_info": "0",
  "resources": [{
    "@type": "type.googleapis.com/envoy.api.v2.Listener",
    "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",
          "codec_type": "AUTO",
          "route_config": {
            "name": "local_route",
            "virtual_hosts": [{
              "name": "local_service",
              "domains": [
                "*"
              ],
              "routes": [{
                "match": {
                  "prefix": "/"
                },
                "route": {
                  "cluster": "targetCluster"
                }
              }]
            }]
          },
          "http_filters": [{
            "name": "envoy.router"
          }]
        }
      }]
    }]
  }]
}

最後に新しく envoy1.yaml を作成し,cds.conflds.conf を設定している.全てを dynamic_resources の中に設定したため,とてもシンプルになった.おおおー!

node:
  id: id_1
  cluster: test

dynamic_resources:
  cds_config:
    path: "/etc/envoy/cds.conf"
  lds_config:
    path: "/etc/envoy/lds.conf"

既に Envoy を起動しているため,今回は 81 Port で新しい Envoy を起動する.特に挙動は変わらないけど,以下の構成図のようになる.

docker run --name=proxy-eds-cds-lds-filebased -d \
    -p 9902:9901 \
    -p 81:10000 \
    -v /root/:/etc/envoy \
    -v /root/envoy1.yaml:/etc/envoy/envoy.yaml \
    envoyproxy/envoy:latest

$ curl localhost:81
<h1>This request was processed by host: c9d6a2229f32</h1>

$ curl localhost:81
<h1>This request was processed by host: edd664e9d604</h1>

$ curl localhost:81
<h1>This request was processed by host: c9d6a2229f32</h1>

$ curl localhost:81
<h1>This request was processed by host: edd664e9d604</h1>

f:id:kakku22:20191217070613p:plain

Step.8 「CDS Apply Changes」

最後は cds.conflds.conf を修正して Envoy に反映する.まず,新しく cds.conf に Cluster newTargetCluster を追加する.

{
  "version_info": "0",
  "resources": [{
      "@type": "type.googleapis.com/envoy.api.v2.Cluster",
      "name": "targetCluster",
      "connect_timeout": "0.25s",
      "lb_policy": "ROUND_ROBIN",
      "type": "EDS",
      "eds_cluster_config": {
        "service_name": "localservices",
        "eds_config": {
          "path": "/etc/envoy/eds.conf"
        }
      }
    },
    {
      "@type": "type.googleapis.com/envoy.api.v2.Cluster",
      "name": "newTargetCluster",
      "connect_timeout": "0.25s",
      "lb_policy": "ROUND_ROBIN",
      "type": "EDS",
      "eds_cluster_config": {
        "service_name": "localservices",
        "eds_config": {
          "path": "/etc/envoy/eds1.conf"
        }
      }
    }
  ]
}

Cluster newTargetCluster から転送されるエンドポイントも新しく eds1.conf として設定する.

{
  "version_info": "0",
  "resources": [{
    "@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
    "cluster_name": "localservices",
    "endpoints": [{
      "lb_endpoints": [{
          "endpoint": {
            "address": {
              "socket_address": {
                "address": "172.18.0.6",
                "port_value": 80
              }
            }
          }
        },
        {
          "endpoint": {
            "address": {
              "socket_address": {
                "address": "172.18.0.7",
                "port_value": 80
              }
            }
          }
        }
      ]
    }]
  }]
}

lds.conf は Cluster を newTargetCluster に変更しておく.

"route": {
  "cluster": "newTargetCluster"
}

修正した cds.conflds.confmv コマンドを使って差し替える.すると,自動的に新しく起動した katacoda/docker-http-server に接続できるようになった.

$ docker run -d katacoda/docker-http-server

$ docker run -d katacoda/docker-http-server

$ mv cds.conf tmp; mv tmp cds.conf; mv lds.conf tmp; mv tmp lds.conf

$ curl localhost:81
<h1>This request was processed by host: beac7d8bc5d3</h1>

$ curl localhost:81
<h1>This request was processed by host: 8d90f60e8a19</h1>

$ curl localhost:81
<h1>This request was processed by host: beac7d8bc5d3</h1>

$ curl localhost:81
<h1>This request was processed by host: 8d90f60e8a19</h1>

最終的に構成図は以下のようになる.

f:id:kakku22:20191217071552p:plain

まとめ

  • 「Try Envoy」のコンテンツ「File Based Dynamic Routing Configuration」を試した
  • Envoy でサポートされている「ディスカバリサービス (xDS)」の一部を学べた
    • EDS (Endpoint Discovery Service)
    • CDS (Cluster Discovery Service)
    • LDS (Listener Discovery Service)
  • 次は 「API Based」な xDS を試すために「API Based Dynamic Routing Configuration」をまとめる!

プルリクエスト

試しながら気付いた誤りを修正してプルリクエストを送っておいた!

github.com

Try Envoy 関連