tjtjtjのメモ

自分のためのメモです

envoy HTTPロードバランサー

前回は、envoyを介して外部サービスを参照した。今回は自前クラスタのサービスをenvoyを介して参照したい。

準備

hello 2つ立ち上げる

# docker run --rm -d --name hello1 dockercloud/hello-world
# docker run --rm -d --name hello2 dockercloud/hello-world

コンテナからhello-world を試す。

# docker run -it --link hello1 alpine wget -O - hello1

        <h3>My hostname is 0b94df201862</h3>    </body>

# docker run -it --link hello2 alpine wget -O - hello2

        <h3>My hostname is 7fd639de7e3d</h3>    </body>

envoy 起動

envoy.yaml。admin セクションがなくてもいいんだなー。

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0,  port_value: 80 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          stat_prefix: ingress_http
          http_filters:
          - name: envoy.router
          route_config:
            name: route
            virtual_hosts:
            - name: hello_service
              domains: ["hello.local"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: hello_cluster
  clusters:
  - name: hello_cluster
    type: STRICT_DNS
    connect_timeout: 0.25s
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: hello_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: hello1, port_value: 80 }
        - endpoint:
            address:
              socket_address: { address: hello2, port_value: 80 }

envoy 起動。1.10.0が出ていたので使ってみた。

docker run \
    --name envoy --rm --publish 80:80 \
    --link hello1 --link hello2 \
    -v /tmp/envoy:/etc/envoy \
    envoyproxy/envoy:v1.10.0

/etc/hosts に次を加える

127.0.0.1 hello.local

curl する。

curl httpd.local

        <h3>My hostname is 0b94df201862</h3>    </body>

curl httpd.local

        <h3>My hostname is 7fd639de7e3d</h3>    </body>

helloクラスタ 1コ落とす

これだけだと、前回と変わらない。試しにhelloクラスタ 1コ落とす。

# docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                           NAMES
c4f6d6e58250        envoyproxy/envoy:v1.9.0   "/usr/bin/dumb-init …"   10 minutes ago      Up 10 minutes       0.0.0.0:80->80/tcp, 10000/tcp   envoy
7fd639de7e3d        dockercloud/hello-world   "/bin/sh -c /run.sh"     18 minutes ago      Up 18 minutes       80/tcp                          hello2
0b94df201862        dockercloud/hello-world   "/bin/sh -c /run.sh"     19 minutes ago      Up 19 minutes       80/tcp                          hello1
# docker stop hello1
hello1
# docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                           NAMES
c4f6d6e58250        envoyproxy/envoy:v1.9.0   "/usr/bin/dumb-init …"   11 minutes ago      Up 11 minutes       0.0.0.0:80->80/tcp, 10000/tcp   envoy
7fd639de7e3d        dockercloud/hello-world   "/bin/sh -c /run.sh"     19 minutes ago      Up 19 minutes       80/tcp                          hello2

curl。成功したり失敗したりを繰り返す。envoy が503 を返している。落ちたほうを勝手に切り離すとかはやってくれない。

# curl hello.local
        <h3>My hostname is 7fd639de7e3d</h3>    </body>

# curl hello.local
upstream connect error or disconnect/reset before headers. reset reason: connection failure

# curl -i hello.local
HTTP/1.1 503 Service Unavailable
content-length: 91
content-type: text/plain
date: Wed, 19 Jun 2019 11:49:29 GMT
server: envoy

upstream connect error or disconnect/reset before headers. reset reason: connection failure

health_checks を試す

envoy.yaml clusters に health_checks を追加。これで hello1 と envoy起動。envoy起動時 hello1 がないと怒られます。

  clusters:
  - name: hello_cluster
    type: STRICT_DNS
    connect_timeout: 0.25s
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: hello_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: hello1, port_value: 80 }
        - endpoint:
            address:
              socket_address: { address: hello2, port_value: 80 }
    health_checks:
      - timeout: 1s
        interval: 5s
        unhealthy_threshold: 1
        healthy_threshold: 1
        http_health_check: 
          path: /

hello1 を落として curl。なんど試しても問題ない。

# docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                           NAMES
599434dba3ff        envoyproxy/envoy:v1.10.0   "/docker-entrypoint.…"   47 seconds ago      Up 45 seconds       0.0.0.0:80->80/tcp, 10000/tcp   envoy
41a26ecb6ce4        dockercloud/hello-world    "/bin/sh -c /run.sh"     6 minutes ago       Up 6 minutes        80/tcp                          hello1
7fd639de7e3d        dockercloud/hello-world    "/bin/sh -c /run.sh"     About an hour ago   Up About an hour    80/tcp                          hello2
# docker stop hello1
hello1
# curl hello.local
        <h3>My hostname is 7fd639de7e3d</h3>    </body>

# curl hello.local
        <h3>My hostname is 7fd639de7e3d</h3>    </body>

hello1 を起動して curl。何度か試したらhello1が反応した。

# docker run --rm -d --name hello1 dockercloud/hello-world
391fad84edc08a8a56a3101e88c1b7ff76e79d6e615de3f0b5be81111e59b84a
# curl hello.local
        <h3>My hostname is 7fd639de7e3d</h3>    </body>

# curl hello.local
        <h3>My hostname is 7fd639de7e3d</h3>    </body>

# curl hello.local
        <h3>My hostname is 391fad84edc0</h3>    </body>

参考

i-beam.org