kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Try Envoy を "ほぼ" 完走した

2019年11月から Envoy の理解を深めるために,Envoy 公式の学習コンテンツ「Try Envoy」を試しながら,学んだことをブログにアウトプットしてきた.2020年1月末でやっと「ほぼ完走」することができたため,まとめ記事を書く.なお「Try Envoy」はどのコンテンツも「Estimated Time: 10 minutes」となっていて,ザッと流すならすぐ終わるけど,意味がないと思う.そこで,構築する構成図を描いたり,解説のなかったパラメータを調べたり,手順上の誤植を修正したり,自分なりに付加情報を意識しながらアウトプットすることを強く意識していた.

なぜ Try Envoy を選んだ?

新しい技術を学ぶときに,個人的に「できる限り手を動かすこと」を意識している.ただし,闇雲に手を動かすのではなく,体系的にステップバイステップに学びたく,どちらかと言うと「学習コンテンツ系(e-Learning / Hands-On / YouTube など)」を好む傾向にある.仕事柄,すぐに検証するプロダクション環境を持っていないという背景もある.そこで,今回は Envoy 公式の「Try Envoy」を選んだ.Katacoda をベースにしているため,環境構築の必要がないという点も初学者に優しい.

www.envoyproxy.io

www.katacoda.com

コンテンツ一覧

2020年1月末時点だと,Try Envoy では「計11個」のコンテンツが公開されている.以下にコンテンツ名とブログ記事をマッピングする.

Try Envoy kakakakakku blog
Getting Started with Envoy 「Try Envoy」で Envoy を学ぼう!「Getting Started with Envoy」を試した - kakakakakku blog
Migrating from NGINX to Envoy Proxy nginx と Envoy の設定を比較して学べる「Migrating from NGINX to Envoy Proxy」を試した - kakakakakku blog
Migrating from HAProxy to Envoy Proxy 実施なし (*1)
Securing traffic with HTTPS and SSL/TLS Envoy で HTTPS 接続をする設定を学べる「Securing traffic with HTTPS and SSL/TLS」を試した - kakakakakku blog
File Based Dynamic Routing Configuration Envoy のディスカバリサービス (xDS) を学べる「File Based Dynamic Routing Configuration」を試した - kakakakakku blog
API Based Dynamic Routing Configuration Envoy の EDS を REST API で体験する「API Based Dynamic Routing Configuration」を試した - kakakakakku blog
Detecting Down Services with Health Checks Envoy の Health Checking と Outlier Detection の違いを学べる「Detecting Down Services with Health Checks」を試した - kakakakakku blog
Implementing Blue / Green Rollouts Envoy の route.HeaderMatcher を使う「Implementing Blue / Green Rollouts」を試した - kakakakakku blog
Controlling load balancing policies Envoy の lb_policy は ROUND_ROBIN 以外にもある!「Controlling load balancing policies」を試した - kakakakakku blog
Implementing Metrics and Tracing Capabilities Envoy x Prometheus x Grafana x Jaeger に入門する「Implementing Metrics and Tracing Capabilities」を試した - kakakakakku blog
Debugging Envoy Proxy 実施なし (*2)

実は実施しなかった(できなかった)コンテンツが2個ある.よって,タイトルに "ほぼ" と書いた.

  • 実施なし (*1)
    • 個人的に HAProxy を使う場面はなく,nginx で十分だった
  • 実施なし (*2)

良いところ

何よりもまず「Try Envoy」をやり込むことにより,envoy.yaml を読めるようになった(はず).今でも「設定長いなぁ」とは思うものの,Envoy を学ぶ前と比較すると,圧倒的に envoy.yaml に直面したときの「ナニコレ感」はなくなった.これは大きなメリットと言える.

次に Envoy の醍醐味とも言える「xDS」を File Based と API Based で試せたのは良かった.記事にも書いた通り,正直なところ API Based (gRPC) を学びたかったけど,最低限の仕組みを把握できれば,残りは自分で試行錯誤できる.

最後は「ルーティング」の仕組みをたくさん学べた点で,nginx からのマイグレーションも,ロードバランシング,カナリーデプロイ,HTTP Header ベースルーティングも学べた.まだまだ Envoy の機能の一部ではあるものの,多機能であることは十分にわかった.

フィードバック

「Try Envoy」をより良くするためにフィードバックをまとめておく.

まず,Envoy を使った「ルーティング」を学ぶという側面が強く,例えば「マイクロサービス文脈(リトライ/サーキットブレイク/タイムアウト/スロットリング)」のコンテンツもあると良かった.とは言え,Envoy はあくまでデータプレーンなので,Istio などコントロールプレーン側のコンテンツで学ぶべきだ!と言われればそれも納得できるところではある.

なお,関連するコンテンツ「Learn Envoy」では,以下の分類になっていて,バランス良く構成されているように思う.

  • Getting Started
  • Dynamic Configuration
  • Observability
  • Deployment Models
  • Resilience
  • Building On Envoy

次に「コンテンツは古め」という点も気になる.Envoy 自体の進化も早く,ドキュメントが頻繁に書き換わるため,コンテンツからリンクされているドキュメントが 404 になっている場面もあった.正直 latest のドキュメントを参照していると,影響を受けすぎる気もする.

他にも envoy.yaml の記法として cluseterhostsEnvoy 1.8.0 (Oct 4, 2018) で既に deprecated になっていて,現在は load_assignment を使う必要があるのに,ほとんどのコンテンツは hosts のままになっていた.経験者なら気付けるけど,初学者だと「動くけど本当は deprecated」には気付けないと思う.最近の変更だと,Envoy 1.12.0 (October 31, 2019)tracing.operation_name も deprecated になっている.

www.envoyproxy.io

ただし,プルリクエストは定期的に merge してもらえる(デプロイはされていないけど).よって,コンテンツ自体も OSS であるという気持ちで,一緒に改善していくのが良さそう.

github.com

まとめ

これで「Try Envoy」の連載は終わり!

今後 Envoy を学ぶ人たちの参考になれば嬉しいなーと😃

Envoy x Prometheus x Grafana x Jaeger に入門する「Implementing Metrics and Tracing Capabilities」を試した

今回は「Try Envoy」「Implementing Metrics and Tracing Capabilities」を紹介する.Envoy を実戦投入するときには「モニタリング」「トレーシング」など,関連する技術トピックも把握しておく必要があると思う.今回の「Implementing Metrics and Tracing Capabilities」では「Envoy x Prometheus x Grafana x Jaeger」をまとめて試せる「お得すぎる!」コンテンツになっている.

Implementing Metrics and Tracing Capabilities

手順は以下の「計7種類」ある.

  • Step.1 「Start Envoy」
  • Step.2 「Adding Metrics」
  • Step.3 「Adding Tracing」
  • Step.4 「Generating Traffic」
  • Step.5 「Viewing Metrics」
  • Step.6 「Dashboarding Metrics with Grafana」
  • Step.7 「Viewing Tracing」

www.envoyproxy.io

www.katacoda.com

Step.1 「Start Envoy」

まず,Envoy と katacoda/docker-http-server:healthy を起動し,動作確認をしておく.

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

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

$ curl 172.18.0.3
<h1>A healthy request was processed by host: 23fe941d8f04</h1>
$ curl 172.18.0.4
<h1>A healthy request was processed by host: bc3b328e6fbf</h1>

$ curl localhost
<h1>A healthy request was processed by host: bc3b328e6fbf</h1>
$ curl localhost
<h1>A healthy request was processed by host: 23fe941d8f04</h1>

ただし,今まで紹介した Try Envoy のコンテンツには出てなかった設定が envoy.yaml にある.例えば tracing で,今回試していく.

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

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:
          codec_type: auto
          stat_prefix: ingress_http
          generate_request_id: true
          tracing:
            operation_name: egress
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router
  clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]
    health_checks:
      - timeout: 1s
        interval: 10s
        interval_jitter: 1s
        unhealthy_threshold: 6
        healthy_threshold: 1
        http_health_check:
          path: "/health"
  - name: jaeger
    connect_timeout: 1s
    type: strict_dns
    lb_policy: round_robin
    load_assignment:
      cluster_name: jaeger
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 172.18.0.6
                port_value: 9411
tracing:
    http:
      name: envoy.zipkin
      config:
        collector_cluster: jaeger
        collector_endpoint: "/api/v1/spans"
        shared_span_context: false

Step.2 「Adding Metrics」

Envoy をモニタリングするため,Prometheus コンテナを起動する.

$ docker run -d -p 9090:9090 \
    -v /root/envoy/prometheus.yml:/etc/prometheus/prometheus.yml \
    --name prometheus-server \
    prom/prometheus

Prometheus の設定ファイル prometheus.yml は以下となる.簡単に言うと,Envoy の管理画面に 9901 ポートで接続できるため,そこから /stats/prometheus エンドポイントにアクセスし,メトリクスを収集している.

global:
  scrape_interval:     15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'envoy'
    metrics_path: /stats/prometheus
    static_configs:
      - targets: ['172.18.0.2:9901']
        labels:
          group: 'envoy'

Prometheus の詳細は「入門 Prometheus」を読むと良いかと!

kakakakakku.hatenablog.com

すると,Katacoda の公開ドメインから Prometheus の管理画面にも接続できるようになる.

f:id:kakku22:20200127112108p:plain

Step.3 「Adding Tracing」

次は Envoy で「分散トレーシング」を試す.今回は Uber の OSS であり,CNCF に参加するなど,よく知られた「Jaeger」を使う.Jaeger は Twitter の OSS である「Zipkin」の API と互換性があるため,envoy.yamltracing セクションでは,トレースドライバとして envoy.zipkin を指定する.

www.jaegertracing.io

tracing:
  http:
    name: envoy.zipkin
    config:
      collector_cluster: 172.18.0.6
      collector_endpoint: "/api/v1/spans"
      shared_span_context: false

ドキュメントに書いてある通り,Envoy は以下のようなトレースドライバをサポートしている.

  • envoy.lightstep
  • envoy.zipkin
  • envoy.dynamic.ot
  • envoy.tracers.datadog
  • envoy.tracers.opencensus
  • envoy.tracers.xray

www.envoyproxy.io

さらに重要なポイントがあり,envoy.yaml の中に generate_request_idtracing を追加している.generate_request_idtrue にすると,x-request-id ヘッダに UUID を追加することを明示的に設定できる.tracing を設定すると,既に説明した tracing セクションにトレース情報を送信する.

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:
          codec_type: auto
          stat_prefix: ingress_http
          generate_request_id: true
          tracing:
            operation_name: egress

最後にトレーシング用に Jaeger コンテナを起動しておく.

$ docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p 9411:9411 -p 5775:5775/udp -p 16686:16686 jaegertracing/all-in-one:latest

Step.4 「Generating Traffic」

Envoy にリクエストを送り続ける.

$ while true; do curl localhost; sleep .5; done

Step.5 「Viewing Metrics」

ある程度 Envoy にリクエストを送ったら,今度は Prometheus の管理画面で Envoy のメトリクス envoy_cluster_external_upstream_rq をグラフ化する.これは Envoy のリクエスト数となる.

envoy_cluster_external_upstream_rq{envoy_cluster_name="targetCluster"}

すると,以下のようにメトリクスの増加を確認できる.

f:id:kakku22:20200126144500p:plain

Step.6 「Dashboarding Metrics with Grafana」

今度は Prometheus の可視化としてもよく使う「Grafana」を試す.Grafana コンテナを起動する.

$ docker run --name=grafana -d -p 3000:3000 grafana/grafana

次に Prometheus データソースを登録する.HTTP URL に http://172.18.0.5:9090 を設定し「Save & Test」を押す.

f:id:kakku22:20200126144534p:plain

また Envoy 用の Grafana ダッシュボードが用意されているため,ダッシュボード ID 6693 を指定して「Import」を押すと,すぐに Envoy 用のダッシュボードが使えるようになる.

grafana.com

f:id:kakku22:20200126144612p:plain

f:id:kakku22:20200127112740p:plain

もう1度 Envoy にリクエストを送り続ける.途中で /unhealthy エンドポイントを使ってヘルスチェックを落としたり,/healthy エンドポイントを使って復活させたり,HTTP 200 以外のエラーが出るように操作した.

$ while true; do curl localhost; sleep .1; done

$ curl 172.18.0.3/unhealthy
$ curl 172.18.0.4/unhealthy

$ curl 172.18.0.3/healthy
$ curl 172.18.0.4/healthy

すると,Prometheus のグラフに HTTP 500 の件数も表示される.今回はダッシュボードを拡張し,Grafana で確認できるようにした.

f:id:kakku22:20200127114026p:plain

Step.7 「Viewing Tracing」

最後は Jaeger UI を確認する.以下は Jaeger の「トレース分布(横軸 : 時系列 / 縦軸 : レスポンス)」「トレース詳細」を確認した.とは言え,本格的なトレースにはなってなく,得られる情報も少なかった.今回はあくまで動作確認を目的にしていると言えそう.

f:id:kakku22:20200127114552p:plain

f:id:kakku22:20200127114607p:plain

まとめ

  • 「Try Envoy」「Implementing Metrics and Tracing Capabilities」を試した
  • 内容としては「浅く広く」ではあるものの「Envoy x Prometheus x Grafana x Jaeger」をまとめて試せるお得感はある
  • やっと「Try Envoy」を(ほぼ)完走した 🎉

プルリクエスト

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

github.com

Try Envoy 関連

Envoy の lb_policy は ROUND_ROBIN 以外にもある!「Controlling load balancing policies」を試した

今回は「Try Envoy」「Controlling load balancing policies」を紹介する.Envoy でサポートされている「ロードバランスポリシー」の種類を学べる.ただし,Weighted round robin の動作確認は期待通りに動かず,消化不良な感じになってしまった.個人的には「Controlling load balancing policies」は実施しなくて良いと思う.可能なら Katacoda 側で内容を見直してもらえると良さそう.

Detecting Down Services with Health Checks

手順は以下の「計3種類」ある.

  • Step.1 「Load balancing policies」
  • Step.2 「Weighted round robin」
  • Step.3 「Generating Traffic」

なお,最近 Try Envoy にあるリンクは 404 エラーになってしまった(年末までは見れていた).ただ Katacoda を使えば,引き続き同じコンテンツを実施できる.

www.katacoda.com

Step.1 「Load balancing policies」

Envoy では Cluster の lb_policy「ロードバランスポリシー」を設定できる.今まで試してきた Try Envoy では,全て ROUND_ROBIN を使っていたけど,実際には多くの種類が実装されている.

  • Weighted round robin (ROUND_ROBIN)
    • デフォルト設定
  • Weighted least request (LEAST_REQUEST)
  • Ring hash (RING_HASH)
  • Random (RANDOM)
  • Original destination (ORIGINAL_DST_LB)
    • Envoy v1.12.0 から非推奨で CLUSTER_PROVIDED を使う
  • Maglev (MAGLEV)
  • Cluster Provided (CLUSTER_PROVIDED)

RING_HASH は名前の通り Consistent Hashing の実装となる.ドキュメントを読むと ketama という C で実装されたライブラリのリンクがあり,Envoy の内部で使われているとのことだった.また MAGLEV は今回はじめて知ったけど,Google から論文が出ているアルゴリズムらしく,ketama よりも高速とのこと.気になる!

github.com

「ロードバランスポリシー」の詳細は以下のドキュメントに載っている.

www.envoyproxy.io

www.envoyproxy.io

Step.2 「Weighted round robin」

envoy.yamllb_policyROUND_ROBIN を設定する.今までの Try Envoy で何度も試したため,正直言うと他のロードバランスポリシーを試したかった.なお,今回は clusters の中に hosts を設定せず,新しく load_assignment を設定していた.よくよく調べると,Envoy v1.8.0 から hosts は非推奨になり load_assignment が推奨になっていた.今までの Try Envoy は非推奨の設定を使っていたことに気付く.ううう!

www.envoyproxy.io

さらに load_assignment の挿入場所に誤りがあり,Envoy の起動時にエラーになる.正しくは clusters のパラメータなので,以下のように lb_policy と並べる必要がある.修正はプルリクエストを送っているけど,取り込まれるまでは要注意!

envoyproxy.io

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:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router
  clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
        cluster_name: targetCluster
        endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                    socket_address:
                        address: 172.18.0.3
                        port_value: 80
            load_balancing_weight: 90
        - lb_endpoints:
            - endpoint:
                address:
                    socket_address:
                        address: 172.18.0.4
                        port_value: 80

そして,Envoy と katacoda/docker-http-server:healthy を起動する.

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

$ docker run -d katacoda/docker-http-server:healthy;
$ docker run -d katacoda/docker-http-server:healthy;

Step.3 「Generating Traffic」

実際に while で Envoy にリクエストを送り続ける.

ドキュメントを読むと,endpoint.LocalityLbEndpointsendpoint.LbEndpoint に対する load_balancing_weight があり,混乱した.今回は前者の設定となり,172.18.0.3 側に多くのリクエストが送られるのかと予想したけど,動作確認をしてもルーティングに差は出なかった.うーん?理解が間違っている?よくわからず,もう少し Try Envoy として解説を書いて欲しいなと思う.

$ while true; do curl localhost; sleep .5; done

まとめ

  • 「Try Envoy」のコンテンツ「Controlling load balancing policies」を試した
  • Weighted round robin の動作確認は期待通りに動かず,消化不良な感じになってしまった
    • 実施しなくて良いと思う 😇

残るは1個!引き続き,進めていくぞ!

プルリクエスト

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

github.com

Try Envoy 関連

2019年の振り返りと2020年の抱負

既に1月後半になり,遅くなってしまったけど,毎年恒例の「振り返りと抱負」をまとめておこうと思う.

2019年の振り返り 🎉

幅広く技術を学べた

2019年の目標は「幅広く技術を語れるように学び続ける」としていた.未経験の技術は無限にあるし,苦手意識のある技術領域もある.2019年は意図的に「幅広さ」を意識した1年だった.そして,この戦略は正解だったとも感じる.1年前と比べて「技術的な幅広さ」という観点では少なからず成長実感がある.

ブログのカテゴリを見ても,例えば「Python, React, Envoy, GraphQL, Docker, Ansible, Kubernetes, Prometheus, HashiCorp」などなど,技術領域の制限はせず,様々な技術に挑戦できた.そして幅広く学んだからこそ,さらなる「未経験の技術の発見」もできた.本当に未経験の技術は無限にある!Trello のチケットは日々増えているけど,1年間を通してずっと「楽しく学び続けられた」ことは良かった.

当然ながら「技術的な深さを追い求めること」は課題となる.認識はしている.しかし,仕事柄プロダクションコードを書く機会はないし,2018年まで3年間連続で目標にしていた「実践投入力を高める」場面もないことから,今の自分には「幅広さを追求すること」にプライオリティの高さを感じている.2020年も同じ目標を掲げる.

教える / 教える / 教える

技術講師として,1年間ずっと「教えるとは何か?」を考えていた.考えて,実践し,失敗し,改善する.そんなサイクルを繰り返し,ようやく自分のスタイルに到達できた気がする(あくまで気がする).例えば「ラーニングピラミッド」「経験学習モデル」を意識した教授戦略プランを考えたり,初学者に「どういうところに難しさを感じるか?」というヒアリングをして,初学者の域を過ぎた自分では気付けなくなった「難しさの観点」を整理してみたりもした.

また「ペアプログラミング」「モブプログラミング」のメリットを研修の場に適用し,思考の透明性を高める施策なども実践した.さらに2019年の後半3ヶ月は「テスト駆動開発 x モブプログラミング」を体験してもらう社内研修を計10回も開催した.とにかく1年間ずっと「教える」ことに没頭していたし,天職であると思う.

ブログメンタリングを継続できた

2019年もブログメンタリングを継続できた.2019年にご一緒させて頂いたメンティは「計28名(現メンティ含む)」で,累計は「計44名(現メンティ含む)」となる.冷静に考えると異常な人数規模になってきたと思うけど,「無料なの意味不明なんですけど!」という褒め言葉を頂くと嬉しくなり,まだまだ続けられそうな気がする.なお,引き続き応募倍率が高くお断りをすることもあるし,募集期間外の問い合わせも増えてきているけど,ベストエフォートで頑張っているため,お待ち頂ければなーというところ.

インプット/アウトプット 💡

登壇

2019年の登壇は計1回だった.「DevLOVE X」で登壇する機会を頂けたのは非常に嬉しかった.自分で言うのもアレだけど,参加者層のペルソナを相当考えたし,練習もしたし,鬼スベリ覚悟のギャグも投入したし,今でも発表会場の雰囲気を思い出せる.そして Togetter を見直すと今でも笑える.詳しくは以下の記事に載せてあるから是非見てもらえると!

kakakakakku.hatenablog.com

勉強会

2019年に参加した勉強会も,登壇した「DevLOVE X」1回だった.過去数年間から考えると明らかに少ないけど,2019年は「勉強会に参加する時間を他の作業時間に回す」という取捨選択を意図的にしていた.そして,もう1個の理由は「ノドのケア」で,仕事柄ノドが生命線だったりもするため「不特定多数の人が集まる場を避けていた」という背景もある(移動中も常にマスクをしている).とは言え,2020年はもう少し参加したいと考えている.

kakakakakku.hatenablog.com

プルリクエスト

2019年は計17個のプルリクエストを OSS に送ることができた.詳細は既にまとめてある.

ブログ

2019年も「週1回」のノルマを達成し「計72記事」を書いた.1年間を通して,1記事も書けなかった週はなく,確実に習慣化はできているなと再確認できた.そして「週x回」のノルマ生活は2015年から5年も続いていることになる.2019年は「幅広く技術を語れるように学び続ける」という目標もあり,すぐ忘れる自分のために書いた記事も多かったけど,累計ブクマ数は2019年で「12281 → 14771 (+2490)」という結果だった.ブクマを集めることは目的ではないけど,誰かの役に立つ記事が書けているのであれば,嬉しいなと思う.

f:id:kakku22:20200121000243p:plain

なお,200 ブクマを超えた記事は5記事だった.

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

書籍

出版に直接携わったわけではないけど,O'Reilly Japan から春に出版された「分散システムデザインパターン」の出版レビューに参加できたことは非常に印象に残っている.今でもパラパラと読み直している.詳しくは以下の記事にまとめてある!

kakakakakku.hatenablog.com

読んだ本

2019年は「計16冊」読んだ.特に忙殺されていた月は書評記事を書けてないけど,それでも2018年よりも多く読むことができた.

Mackerel アンバサダー

光栄なことに2019年3月に「Mackerel アンバサダー」に就任させて頂いた.定量的なアウトプットの規定は(現在のところ)なく,やはり個人的にはブログに期待をして頂いているのかなと感じていたため「3ヶ月に1記事(2019年に3記事)」という目標を掲げていた.ただし,結果としては2記事で未達成となり,反省点が多くある.2020年も同じノルマ「3ヶ月に1記事」で頑張る.

2020年の抱負 ✨

幅広く技術を語れるように学び続ける

振り返りにも書いた通り,2019年に掲げた「幅広く技術を語れるように学び続ける」という目標がうまくハマったため,2020年も継続する.フロントエンド/バックエンド/インフラ/マネジメントなど,技術領域の制限はせず,好奇心のままに貪欲に学び続けていく.特に「OSS」など,オープンな技術を主軸にすることも2019年と変わらず継続する.

そして,2020年は新たに「教えてもらう」という施策にも取り組んでみたいと思う.背景としては,技術講師として「教えること」を追求しているし,その価値を実感しているのにも関わらず,自分自身は「1年間ずっと独学ばかりしていた」というギャップに悩んでいた.特に新しい技術に入門するときに独学をするのは非効率だし,誤ったベクトルに進んでしまうこともある.そして,何よりもまず「自分自身が気付いていないことは調べることすらできない」という問題があるため,積極的に「達人を味方」にして,学んでいく.教えてー!

定量的な目標は過去2年間と変わらず,以下となる.

  • ブログは変わらず「週1記事」ノルマ
  • ストレッチゴールとして年間「70記事」

まとめ

2020年も攻めていくぞ 🔥

過去の振り返り

Envoy の route.HeaderMatcher を使う「Implementing Blue / Green Rollouts」を試した

今回は「Try Envoy」「Implementing Blue / Green Rollouts」を紹介する.Envoy でサポートされている様々なルーティング設定の中から「HTTP Header ベースルーティング」「加重ラウンドロビン」を学べる.

Implementing Blue / Green Rollouts

手順は以下の「計6種類」ある.

  • Step.1 「Envoy Base Configuration」
  • Step.2 「Header-Based Routing」
  • Step.3 「Deploy Header-Based Routing」
  • Step.4 「Weighted Load Balancing」
  • Step.5 「Rollout 20% Traffic」
  • Step.6 「Rollout 100% Traffic」

www.envoyproxy.io

www.katacoda.com

Step.1 「Envoy Base Configuration」

Step.1 では envoy.yaml を読み解き,クイズに正解する必要がある.理解度確認になって非常に良いと思うし,Katacoda ってクイズ形式も作れるんだ!というプラットフォームの機能の幅広さに驚いたりもした.

  • Question: How many routes have been defined within the configuration?
  • Question: How many clusters have been defined within the configuration?

f:id:kakku22:20200112132842p:plain

Step.2 「Header-Based Routing」

ユーザーに影響を出さず,新機能をテストすることを「ダークリリース (Dark Releases)」と言う(とコンテンツに書いてある).Envoy の route_config は上から順番に比較し,最初に一致したルーティング設定を使うことになるため,今回は /service/2 に対して2種類のルーティング設定をしている.今回は HTTP Header x-canary-versionservice2a という値が設定されている場合に Cluster service2a にルーティングする.

route_config:
  virtual_hosts:
  - name: backend
    domains:
    - "*"
    routes:
    - match:
        prefix: "/service/1"
      route:
        cluster: service1
    - match:
        prefix: "/service/2"
        headers:
        - name: "x-canary-version"
          exact_match: "service2a"
      route:
        cluster: service2a
    - match:
        prefix: "/service/2"
      route:
        cluster: service2

Envoy は routes の設定として route.RouteMatch を使えば,細かくルーティングを制御できる.今回は route.HeaderMatcher を使って HTTP Header ベースのルーティングを実現している.高機能ロードバランサとして機能が揃っている!

www.envoyproxy.io

Step.3 「Deploy Header-Based Routing」

次に Envoy と katacoda/docker-http-server を起動する.katacoda/docker-http-serverv1 を2個 / v2 を2個 / v3 を1個起動する.構成図は以下のようになる.

$ docker run -d --name proxy1 -p 80:8080 -v /root/:/etc/envoy envoyproxy/envoy

$ docker run -d katacoda/docker-http-server:v1
$ docker run -d katacoda/docker-http-server:v1
$ docker run -d katacoda/docker-http-server:v2
$ docker run -d katacoda/docker-http-server:v2
$ docker run -d katacoda/docker-http-server:v3

f:id:kakku22:20200112132915p:plain

katacoda/docker-http-server とコンテナ ID の関係を整理しておくと,以下のようになる.

$ docker ps -q | xargs -n 1 docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} {{ .Config.Hostname }} {{ .Config.Image }}' | sed 's/ \// /'
172.18.0.7 fdf5019381c2 katacoda/docker-http-server:v3
172.18.0.6 64724167bc8d katacoda/docker-http-server:v2
172.18.0.5 63a9ff40f850 katacoda/docker-http-server:v2
172.18.0.4 efab265b509a katacoda/docker-http-server:v1
172.18.0.3 c985d2391163 katacoda/docker-http-server:v1
172.18.0.2 9814e5b162f4 envoyproxy/envoy

動作確認として,まず http://localhost/service/2 にリクエストを送ると,Cluster service2 を経由して efab265b509a にルーティングされる.そして http://localhost/service/2 に HTTP Header を乗せてリクエストを送ると,Cluster service2a を経由して 63a9ff40f850 にルーティングされる.構成図の通りになっている.

# HTTP Header なし
$ curl http://localhost/service/2
<h1>This request was processed by host: efab265b509a</h1>
$ curl http://localhost/service/2
<h1>This request was processed by host: efab265b509a</h1>

# HTTP Header あり
$ curl -H "x-canary-version: service2a" http://localhost/service/2
<h1>New Release! Now v2! This request was processed by host: 63a9ff40f850</h1>
$ curl -H "x-canary-version: service2a" http://localhost/service/2
<h1>New Release! Now v2! This request was processed by host: 63a9ff40f850</h1>

Step.4 「Weighted Load Balancing」

次は「カナリアリリース」のように使える「加重ラウンドロビン」を試す.ルーティング設定に weighted_clusters を追加すると,weight に設定した割合に従ってルーティングされる.今回は /service/3 にリクエストを送ると 80% は Cluster service3a に,そして 20% は Cluster service3b にルーティングされる.

route_config:
  virtual_hosts:
  - name: backend
    domains:
    - "*"
    routes:
    - match:
        prefix: "/service/1"
      route:
        cluster: service1
    - match:
        prefix: "/service/2"
        headers:
        - name: "x-canary-version"
          exact_match: "service2a"
      route:
        cluster: service2a
    - match:
        prefix: "/service/2"
      route:
        cluster: service2
    - match:
        prefix: "/service/3"
      route:
        weighted_clusters:
          clusters:
          - name: service3a
            weight: 80
          - name: service3b
            weight: 20

Step.5 「Rollout 20% Traffic」

設定変更を反映するため Envoy を再起動する.構成図は以下のようになる.

f:id:kakku22:20200112132930p:plain

さっそく http://localhost/service/3 に対してリクエストを送ると,割合に従ってルーティングされる.繰り返し実行していると,キレイに 80% / 20% にならないこともあった.

$ for i in {1..10}; do curl -s http://localhost/service/3; done
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>
<h1>New Another Release! Now v3! This request was processed by host: fdf5019381c2</h1>
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>
<h1>New Another Release! Now v3! This request was processed by host: fdf5019381c2</h1>
<h1>New Release! Now v2! This request was processed by host: 64724167bc8d</h1>

なお,今回は手順を簡単にするために Envoy を再起動したけど,Route Discovery Service (RDS) を使えば,自動的に反映できるようになる.xDS 関連は以下の Try Envoy が参考になる.

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Step.6 「Rollout 100% Traffic」

最後は割合を 100% にする.100% なら weighted_clusters を使う必要はなさそうだけど,実際に動くことを確認する手順になっていた.

route_config:
  virtual_hosts:
  - name: backend
    domains:
    - "*"
    routes:
    - match:
        prefix: "/service/1"
      route:
        cluster: service1
    - match:
        prefix: "/service/2"
        headers:
        - name: "x-canary-version"
          exact_match: "service2a"
      route:
        cluster: service2a
    - match:
        prefix: "/service/2"
      route:
        cluster: service2
    - match:
        prefix: "/service/3"
      route:
        weighted_clusters:
          clusters:
          - name: service3b
            weight: 100

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

f:id:kakku22:20200112133003p:plain

まとめ

  • 「Try Envoy」のコンテンツ「Implementing Blue / Green Rollouts」を試した
  • Envoy は「高機能ロードバランサ」の側面として様々なルーティング設定ができることを学んだ

引き続き,進めていくぞ!

プルリクエスト

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

github.com

Try Envoy 関連