新しいOSSプロキシ Envoy ことはじめ

2017.12.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
Envoyは、ライドシェアサービスのLyftが開発し現在はCloud Native Computing Foundationにコードが寄贈されているOSSのプロキシソフトウェアです。Kuberenetesでマイクロサービスを提供するIstioのコアコンポーネントとして一躍注目を集めています。
個人的には、ハイパフォーマンスでL4/L7両方の機能を持つ高機能なのでリバースプロキシ単体でもいろいろ使いドコロがありそう!ということで、年末年始にいじってみようかなと思っています。現状日本語の情報が皆無のようなので、まずはEnvoyの試し方についてご紹介してみます。

動作確認環境

  • OS : macOS High Sierra
  • Docker : Docker for Mac Community Edition Version 17.09.1-ce-mac42 (21090)

バイナリの提供はDockerイメージ

以下のページの手順を辿ってみます。

EnvoyはC++で書かれていて、ビルドオプションなどを調整しつつビルドして使うのがお作法のようです。お試しとしては、バイナリを含んだDockerイメージが公開されているので、それを利用するのが楽です。

今回はenvoyproxy/envoy:latestを利用します。このコンテナにはEnvoyの設定ファイルenvoy.jsonが含まれていないのでgoogle.comへのトラフィックをプロキシする以下のサンプルコンフィグを作成し、それをカスタムコンテナに含めるDockerfileを用意します。

envoy.json

{
    "listeners": [{
        "address": "tcp://0.0.0.0:10000",
        "filters": [{
            "name": "http_connection_manager",
            "config": {
                "codec_type": "auto",
                "stat_prefix": "ingress_http",
                "route_config": {
                    "virtual_hosts": [{
                        "name": "local_service",
                        "domains": [
                            "*"
                        ],
                        "routes": [{
                            "timeout_ms": 0,
                            "prefix": "/",
                            "host_rewrite": "www.google.com",
                            "cluster": "service_google"
                        }]
                    }]
                },
                "filters": [{
                    "name": "router",
                    "config": {}
                }]
            }
        }]
    }],
    "admin": {
        "access_log_path": "/tmp/admin_access.log",
        "address": "tcp://0.0.0.0:9901"
    },
    "cluster_manager": {
        "clusters": [{
            "name": "service_google",
            "connect_timeout_ms": 250,
            "type": "logical_dns",
            "lb_type": "round_robin",
            "hosts": [{
                "url": "tcp://google.com:443"
            }],
            "ssl_context": {
                "sni": "www.google.com"
            }
        }]
    }
}

Dockerfile

FROM envoyproxy/envoy:latest
RUN apt-get update
COPY envoy.json /etc/envoy.json
CMD /usr/local/bin/envoy -c /etc/envoy.json

docker buildコマンドでDockerイメージを作成します。

$ docker build -t takipone/envoy:v1 .
Sending build context to Docker daemon  4.096kB
Step 1/4 : FROM envoyproxy/envoy:latest
 ---> 5e13d70b9530
Step 2/4 : RUN apt-get update
 ---> Using cache
 ---> 7f1797498a97
Step 3/4 : COPY envoy.json /etc/envoy.json
 ---> 8165c5fb15fd
Step 4/4 : CMD /usr/local/bin/envoy -c /etc/envoy.json
 ---> Running in 2918e71c972f
 ---> 36173b31d31a
Removing intermediate container 2918e71c972f
Successfully built 36173b31d31a
Successfully tagged takipone/envoy:v1
$

では、Dockerコンテナを実行します。今回はプロキシのリスナポートが10000、管理APIのリスナポートが9901なのでそれぞれポートマップを指定します。

$ docker run -d -p 8080:10000 -p 9901:9901 takipone/envoy:v1
252c1c9dad52f1c61b180b6a7cc7041fd738b3c1c6d472ad53610e3d062e6d75
$

これでOKです。では、cURLで叩いてみます。まずはプロキシから。

$ curl localhost:8080
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="https://www.google.co.jp/?gfe_rd=cr&amp;dcr=0&amp;ei=aM88WoC8NtDd8Aej9p6oBQ">here</A>.
</BODY></HTML>
$

google.comからのレスポンスが正しく返ってきました。続いて管理APIを叩いてみます。

$ curl localhost:9901
envoy admin commands:
  /certs: print certs on machine
  /clusters: upstream cluster status
  /cpuprofiler: enable/disable the CPU profiler
  /healthcheck/fail: cause the server to fail health checks
  /healthcheck/ok: cause the server to pass health checks
  /hot_restart_version: print the hot restart compatability version
  /listeners: print listener addresses
  /logging: query/change logging levels
  /quitquitquit: exit the server
  /reset_counters: reset all counters to zero
  /routes: print out currently loaded dynamic HTTP route tables
  /server_info: print server version/status information
  /stats: print server stats
$ curl localhost:9901/listeners
["0.0.0.0:10000"]
$ curl localhost:9901/server_info
envoy 0640bdb78c79c83b793c540ff5878202f0ab0bad/Clean/RELEASE live 889 889 0

いろいろな情報の取得や操作ができそうです。

まとめ

Envoyをまずは動かしてみた様子をご紹介しました。L4とL7を縦横に操作するようなプラグインを書いてみれたらなぁという野望を抱きつつ、年末もう少し触ってみたいと思います。皆さんも試してみてください!