ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

LEARN ENVOY - Getting Started / On Your Laptop

www.envoyproxy.io

動かした。つまりこういうこと。

f:id:take_she12:20200105214208p:plain

補足

  • service[12]-container において、envoy process と flask process の group は表現できなかった
  • なんか最初の user -> front-envoy のフローで http スキーマのあとの // が消えて斜線になってしまった
  • front の cluster からの通信では、docker-compose の alias で service[12] で 名前解決している
  • listen してる port とか表現できてないけど通信の URL でわかってほしい
  • 肝心の match prefix service/1 の最後の数字が消えてる。。。
  • admin port は省略している。でも 8001 で browser でアクセスするといろんな情報みれて便利

感想

スッと動いて便利。最初の最初にこれやるのはよさそう。

UML

最近また plantuml 使いはじめた。たのしい。こういう Editor で。

PlantUML Editor

uml
@startuml

package "front-envoy-container" {
    [front-envoy-listener]
  [service1-cluster]
  [service2-cluster]
}

package "service1-container" {
    [service1-listener]
  [service1_local_service-cluster]
  [service1_flask]
}

package "service2-container" {
    [service2-listener]
  [service2_local_service-cluster]
  [service2_flask]
}

[user] --> [front-envoy-listener] : "http://localhost:8000/service/1 or http://localhost:8000/service/2"
[front-envoy-listener] --> [service1-cluster] : match: prefix: "/service/1"
[front-envoy-listener] --> [service2-cluster] : match: prefix: "/service/2"
[service1-cluster] --> [service1-listener] : http://service1/service/1:80
[service2-cluster] --> [service2-listener] : http://service2/service/2:80
[service1-listener] --> [service1_local_service-cluster] : match: prefix: "/service"
[service2-listener] --> [service2_local_service-cluster] : match: prefix: "/service"
[service1_local_service-cluster] --> [service1_flask] : http://127.0.0.1:8080
[service2_local_service-cluster] --> [service2_flask] : http://127.0.0.1:8080
@enduml

Service 間通信を Envoy 経由で行い、Metrics を取得する

はじめに

現職では Application は すべて Kubernetes 上で動いている。その場合、インターネットからの通信経路は以下のようになる。

Internet -> Reverse Proxy(Nginx) -> Service Router(Nginx) -> Kubernetes Service -> Pod

で、後半の Service Router から先が Kubernetes Cluster となっている。Type: LoadBalancer で 受けたあと、forwarding して service-router と呼んでいる Nginx に飛ばしている。

現状、一部で Microservices が動いていたり、Distributed Monolith を Microservices に切ろうとしていたりするが、Service Router 以降の、Pod(Application)同士の通信は Kubernetes Service 作成時に kube-dns に自動的に登録される domain 名で、直接通信している。

インターネット経由でのアクセスの場合は Reverse Proxy や Service Router での Metrics は取得できるが、そうではない、Service 間の通信は現状 Application Layer でしか Metrics を取得できないという問題がある。

それの何が問題かというと、Microservices 単位で SLI/SLO を設定するときに困る。NewRelic などの APM でも取得できるのだが、現状 SLI/SLO は DataDog Widget で管理しているので、なんにせよ Datadog のほうで SLI の計測は行いたいのだ。

どうする

直接通信する代わりに、間に Envoy を Proxy として挟む。

Before

Service A --(http://service_b)--> Service B

After

Service A --(http://localhost:10000)-->Envoy-->(http://service_b)-->Service B

Service A の Container と Envoy の Container は同一 Pod として動いている。いわゆる Sidecar である。

具体的な設定差分はこんな感じになる。

configmap でも Deployment の env でもなんでもいいが、(最悪直接書いてもいいが)Service A の Container の環境変数に、Service B への URL をいれる。

            - name: SERVICE_B_URL
              value: localhost:10000

Envoy の config は以下のようになる。

apiVersion: v1
kind: ConfigMap
metadata:
  name: "${SERVICE_NAME}-envoy-config"
data:
  envoy.yaml: |
    admin:
      access_log_path: /dev/stdout
      address:
        socket_address: { address: 127.0.0.1, 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:
              stat_prefix: ingress_http
              codec_type: AUTO
              route_config:
                name: local_route
                virtual_hosts:
                - name: service1_grpc
                  domains: ["*"]
                  routes:
                  # Envoy admin endpoints
                  - match: { prefix: "/server_info" }
                    route: { cluster: envoy_admin }
                  - match: { prefix: "/stats" }
                    route: { cluster: envoy_admin }
                  # HTTP endpoint
                  - match: { prefix: "/v1/example/todo" }
                    route: { cluster: service_b_http }
                  - match: { prefix: "/v2/example/todo" }
                    route: { cluster: service_b_http }
              http_filters:
              - name: envoy.router
                config: {}
      clusters:
      - name: service_b_http
        connect_timeout: 5s
        type: STRICT_DNS
        lb_policy: ROUND_ROBIN
        dns_lookup_family: V4_ONLY
        load_assignment:
          cluster_name: service_b_http
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: service_b
                    port_value: 80
      - name: envoy_admin
        connect_timeout: 0.250s
        type: LOGICAL_DNS
        lb_policy: ROUND_ROBIN
        hosts:
        - socket_address:
            protocol: TCP
            address: 127.0.0.1
            port_value: 9901

実はこれ以外にも gRPC の Client Load Balancing としても Envoy を以前から利用していた。今回は http を proxy することで metrics を取得した。envoy の metris はこの設定のように /stats をあけておいて、annotation を設定すればよい。

docs.datadoghq.com

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: "${SERVICE_NAME}"
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: "${SERVICE_NAME}"
  template:
    metadata:
      name: "${SERVICE_NAME}"
      labels:
        app: "${SERVICE_NAME}"
        version: v0.1
      annotations:
        ad.datadoghq.com/${SERVICE_NAME}-envoy.check_names: |
          ["envoy"]
        ad.datadoghq.com/${SERVICE_NAME}-envoy.init_configs: |
          [{}]
        ad.datadoghq.com/${SERVICE_NAME}-envoy.instances: |
          [
            {
              "stats_url": "http://%%host%%:10000/stats"
            }
          ]

Envoy の config

以下のドキュメントを参考にすれば簡単に動いた。

www.envoyproxy.io

google.com へ https で proxy してる部分を http にしただけだ。

ただ、知っておくべき概念だけ簡単に復習しておく。

static_resources の対になるところは dynamic_resources だと思うが、それはまたそのうち。

Listeners

listeners (Listener) Static Listeners. These listeners are available regardless of LDS configuration.

はい。

www.envoyproxy.io

Listeners 以下の設定例はこれだが、そもそも何かというと、名前の通り、どういう基準で通信を受け付けるか、ということを記述するところである。

address のみが Required になっている。

Listener は複数設定できる。今回の例では address はこうなっている。

      listeners:
      - name: listener_0
        address:
          socket_address: { address: 0.0.0.0, port_value: 10000 }

任意の IP Address の port 10000 で受け付ける。

さらに、条件を絞るために filter_chains という設定がある。

www.envoyproxy.io

filter_chain_match でその criteria を記載する。

www.envoyproxy.io

ここの apply ordering は重要そうである。

The following order applies:

  1. Destination port.
  2. Destination IP address.
  3. Server name (e.g. SNI for TLS protocol),
  4. Transport protocol.
  5. Application protocols (e.g. ALPN for TLS protocol).
  6. Source type (e.g. any, local or external network).
  7. Source IP address.
  8. Source port.

今回はこの filter_chains ではなく、 filters を使っている。

Order matters as the filters are processed sequentially as connection events happen とある通り順番重要。

さらに typed_config に潜っていきたいが、それ自体の説明はない。

もう一度 Getting Started の config を見てみると、

listeners:
- name: listener_0
  address:
    socket_address: { address: 0.0.0.0, port_value: 10000 }
  filter_chains:
  - filters:
    - name: envoy.http_connection_manager
      typed_config:
        "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
        stat_prefix: ingress_http
        codec_type: AUTO
        route_config:
          name: local_route
          virtual_hosts:
          - name: local_service
            domains: ["*"]
            routes:
            - match: { prefix: "/" }
              route: { host_rewrite: www.google.com, cluster: service_google }

http_connection_manager とやらを使っていて、そこの設定を使っているのだろう。

http_connection_manager とは何かというと

www.envoyproxy.io

やばい!飽きてきた。まぁこんな風に filters として使えるものがプロトコルによって異なるものを採用できる、プラガブルになっていることがわかった。

Network Filters の一覧はこのへん。

www.envoyproxy.io

例えば MySQL とか MongoDB とか Redis とかありますね。これらへの接続も Envoy Proxy 経由で行うことでいい感じにすることができそう。今は掘らない。

Clusters

Clusters は Listeners で受けたものを流す対象。Listener は Clusters のみを知っていればよく、実際の通信先は Clusters がいい感じに知っているという仕組みになっているようだ。Service Discovery を Clusters が担っている。

www.envoyproxy.io

基本的には通信を proxy する upstream やらをどうやって discovery するかを書けば良さそうだ。

もう一度 Getting Started の Example から。

clusters:
- name: service_google
  connect_timeout: 0.25s
  type: LOGICAL_DNS
  # Comment out the following line to test on v6 networks
  dns_lookup_family: V4_ONLY
  lb_policy: ROUND_ROBIN
  load_assignment:
    cluster_name: service_google
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: www.google.com
              port_value: 443
  transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
      "@type": type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext
      sni: www.google.com

ここで多分きっと重要な type を深掘りしておこう。

type (Cluster.DiscoveryType) The service discovery type to use for resolving the cluster.

Only one of type, cluster_type may be set.

service discovery type だと言っている。

さて詳細はこちらの Document にのっている。

www.envoyproxy.io

5種類の Type がある。

Static

Static is the simplest service discovery type. The configuration explicitly specifies the resolved network name (IP address/port, unix domain socket, etc.) of each upstream host.

その名の通り IP Address なり Range なりを Static に記述するタイプですね。具体的な設定例はこんな感じになりそう。

  clusters:
    - name: service_ipsum_echo_1
      connect_timeout: 0.25s
      http_protocol_options: {}
      lb_policy: ROUND_ROBIN
      type: STATIC
      hosts:
        - socket_address: {address: 172.16.221.30, port_value: 8000 }

Strict DNS

When using strict DNS service discovery, Envoy will continuously and asynchronously resolve the specified DNS targets. Each returned IP address in the DNS result will be considered an explicit host in the upstream cluster. This means that if the query returns three IP addresses, Envoy will assume the cluster has three hosts, and all three should be load balanced to. If a host is removed from the result Envoy assumes it no longer exists and will drain traffic from any existing connection pools. Note that Envoy never synchronously resolves DNS in the forwarding path. At the expense of eventual consistency, there is never a worry of blocking on a long running DNS query.

決められたタイミングで DNS 問い合わせを行い、その結果を採用する。3つの IP アドレスが解決されれば 3つホストがあると認識するし、いなくなればいなくなったと判断する。毎回の DNS Query にて service discovery を行うように読み取れる。ふむという感じ。

Logical DNS

Logical DNS uses a similar asynchronous resolution mechanism to strict DNS. However, instead of strictly taking the results of the DNS query and assuming that they comprise the entire upstream cluster, a logical DNS cluster only uses the first IP address returned when a new connection needs to be initiated. Thus, a single logical connection pool may contain physical connections to a variety of different upstream hosts. Connections are never drained. This service discovery type is optimal for large scale web services that must be accessed via DNS. Such services typically use round robin DNS to return many different IP addresses. Typically a different result is returned for each query. If strict DNS were used in this scenario, Envoy would assume that the cluster’s members were changing during every resolution interval which would lead to draining connection pools, connection cycling, etc. Instead, with logical DNS, connections stay alive until they get cycled. When interacting with large scale web services, this is the best of all possible worlds: asynchronous/eventually consistent DNS resolution, long lived connections, and zero blocking in the forwarding path.

非同期的に DNS 問い合わせを行う点は Strict DNS と同じだが、Logical DNS は新規接続時に DNS 問い合わせを行い、得た結果の最初の1つのみを採用して通信を行う。

ポイントは Connections are never drained というところで、一度 Connection を確立した場合、再度問い合わせを行ったりせずにずっとその IP アドレスを使うという点だろう。

イマイチ When interacting with large scale web services, this is the best of all possible worlds なポイントがしっくりきていない。Strict だと Member が変わった時一気に接続先が更新されて Gradually じゃない点がよくないってことなんだろうか、?

Original destination

Original destination cluster can be used when incoming connections are redirected to Envoy either via an iptables REDIRECT or TPROXY target or with Proxy Protocol. In these cases requests routed to an original destination cluster are forwarded to upstream hosts as addressed by the redirection metadata, without any explicit host configuration or upstream host discovery. Connections to upstream hosts are pooled and unused hosts are flushed out when they have been idle longer than cleanup_interval, which defaults to 5000ms. If the original destination address is not available, no upstream connection is opened. Envoy can also pickup the original destination from a HTTP header. Original destination service discovery must be used with the original destination load balancer.

when incoming connections are redirected to Envoy either via an iptables REDIRECT or TPROXY target or with Proxy Protocol

iptables REDIRECT か TPROXY target で受けた場合に機能すると言っている。のでそうなんだろう。Istio とかがやってるのはこれなのかもしれない。わからない。

Endpoint discovery service (EDS)

The endpoint discovery service is a xDS management server based on gRPC or REST-JSON API server used by Envoy to fetch cluster members. The cluster members are called “endpoint” in Envoy terminology. For each cluster, Envoy fetch the endpoints from the discovery service. EDS is the preferred service discovery mechanism for a few reasons:

xDS management server を使って dynamic に routing 先を取得したりするんだろうか。

今後

軽く公式ドキュメント追いかけながらメモしようと思ってはじめたが思いの外長くなったのでこのへんで終わる。

年末に http で通信している Service 間通信に Envoy をいれる PR を出したので年明け早々に Production に出すつもりである。

まだまだ Envoy は入門したばかりなので、今後も定期的に Official Document を見て機能を理解していきたい。具体的には、Learn Envoy をざっと見て、Envoy でできることをざっくり理解する。

www.envoyproxy.io

目下現実的に優先度高くやりたいと思っているのは Circuit Breaking 。さっさと当たり前の世界にしていきたい。あとは Dynamic Configuration もおさえておきたい。

あとは Kakku さんがやってる Try Envoy も一通りみておきたい。

kakakakakku.hatenablog.com

タイトル眺めた感じ。。。どれも見ておいたほうがよさそうだな。

最終的には全 Service 間通信に Envoy を経由するようにしたい。手元でやるには限界がくるので、そのタイミングでより上位の Service Mesh の Software を検討することになると思う。

Envoy でやれることをちゃんと理解した上で、Istio / AppMesh も動作検証していきたい。

追記

タイトルにある通り、ちゃんと Metrics はとれました。

代表的な HTTP での Availability / Latency の SLI となる Metrics がとれたので安心。

f:id:take_she12:20200105183137p:plain

2020年

雑感。

まぁ目標は数ヶ月でなかったことになるよね。そうならないようにクォータごとに振り返りしたらいいんでないかと思うけどそれもなされないままでした。

オライリーSafari はやめちゃったし、健康面は無限に太ったままだし、お金も無限に使っているままである。

仕事(SRE)と英語にフォーカスしてばっかりだった気がする。あと酒。

期待と違った点は

  • SRECon Asia に登壇した
  • 英語学習をはじめた。今も継続できている。
  • チームで自分がバリューを発揮できるところができた 一通りなんでもSREの仕事ができるようになった上で、自分がリードしての改善も月に1つ以上はできるようになる。
  • 社内、社外ともにネットワーキングが広がった

ところが嬉しい誤算。

あと仕事面ではこっちでも振り返りをしたばっかりだったり。

blog.chaspy.me

ひとつずつみていこう。


2019年振り返り

blog.chaspy.me

Engineering

Engineering SREとしてもっと「いい感じ」に。学習は英語主体に、スピードが落ちないように、本質をつかむようにやっていく。オライリーSafariをちゃんと元とったって言えるように使う。

幸い、日頃の運用業務、他チームからの依頼に加えて、中・長期的な改善、ビッグプロジェクトとやりがいのあるチームにいる。一通りなんでもSREの仕事ができるようになった上で、自分がリードしての改善も月に1つ以上はできるようになる。

今足りてないのは、日常のひとつひとつの動作の効率化なので、それは継続的にメンテナンスする。大きめな/新しめなことを学ぶときは登壇と合わせてアウトプット駆動にする。本を読んで終わりにしなくてちゃんと手を動かすか、まわりに伝える、という学習法にしたい。

Engineering Skill は伸びたかというと微妙だけど、後半書いてることはできてるんじゃないかと思う。

English

English 今年一番力をいれたい。TOEICを目標にするつもりはないので、定量的な力が出しづらいところ。

とりあえず直近は2月にフィリピンに行くので、最低限の英会話ができるようになること。あとは仕事上の読み書きを調べずに大意を読めるようになること。(特に書きがまだ検索しながらで、チャットでのレスポンスが遅れがち)。海外カンファレンスのキーノートスピーチの英語ぐらいは理解できるようになること。

英語でのプレゼンテーションもやれるようにしたい。

まさかまさかの SRECon 登壇、そして 日々のオンライン英会話、SRE-Global のアサインと、やっとのこと英語が日常に溶けてきたと思う。

とはいえ実力は全然ついてないので、来年こそ質をあげて、確かな「ビジネス英語」力を身につけたい。

あとほかブログに書いてるのはまぁダメ。

でも結構やっていった1年だと思う。

登壇

https://chaspy.me/presentation/

meetup 4本、conference 2本、うち1つは海外、うち1つは 600規模ということでこれまでできなかった一歩が踏み出せたと思う。

コミュニティ活動

SRE Lounge(SRE NEXT)と Terraform-jp とまぁ毎月なにかしらはやっている感じだった。

本当にネットワーキングが広がった1年だと思う。

SRE NEXT うまくいきますように。

その他

  • カメラはじめた
  • 太った

そんなもん。たくさん旅行したな。

2020年

Engineering / Career

本とか、カンファレンスとか、あと知り合いとかから、自分たちより進んでいる事例を聴いて、自分たちの方向性や位置を確かめることができる機会がいくらかあった。

あとはそれを実現するための技術力だが、技術力って問題を解決した数であり、なんかもうやるしかないんじゃないかっていう気がする。開き直りかもしれない。

実は問題を正しく捉えることが難しいので、そこの感度を、コミュニティに頼りながらあげていき、確実に効果が得られるものを技術で実現していきたい。

自分は良い意味で技術にこだわりがないと思っているので、方法はなんでもいい。

  • 先行事例、他社事例を本、カンファレンス、記事、コミュニティから得ることで、今後自分たちが直面する課題に対する打ち手の選択肢を持っておく
  • 目指す姿と現状の問題の解像度を高く持つことで、自分たちが直面している課題の優先順位を決められるようにする
  • 既存の技術がどのような問題をどのように解決するのか、その思想や原理を理解することで、実装時に迷ったり失敗する確率を下げる

抽象度が高くなったが、このあたりを心得ると良さそう。

1つ目はコミュニティのおかげかだいぶ得る機会を持てたと思う。引き続き交流を広げていきたいし、こちらかも Give していきたい。

2つ目は足りてないので2020年は特に注力したい。社内ではプラットフォームを使うユーザは開発者であり、開発者の要望をもっと得る必要がある。特にいまは Global を主に見ているので、フィリピン、インドネシアの Developer とのコミュニケーションをかなり密に持ちたい。あとは Global のビジネスの規模や今後の方向性もちゃんと理解したい。年末カントリーマネージャーと話したのはよかった。ビジネスの展望と、その成長のためのプラットフォームの成長の足踏みを合わせる必要があると思う。

3つ目はずっとずっと課題に思っていることだ。悪い意味で技術にこだわりがないので、問題に直面しない限り深掘りしないというのは Software Engineer としていかがなものかという葛藤もある。(とはいえ時間は有限だし、ね)このあたりも2つ目で未来をより見通すことで、「これはやっておかないといけない」という気持ちになって深掘りすることになるのかもしれない。直近だと ServiceMesh(Envoy / Istio) は事前に先取りしておかないとな、という気持ちはある。

というわけでこうやって言語化できたのはよかったんではないか。(自己満足)

そう考えると問題を解決しまくれる職場というのは技術者にとっていい職場ですね。

Career とも書いてるな。少なくともやることは山積みなので次の1年は転職はないです。

English

2019年8月から DMM 英会話を中心に、だんだんと英語を使う機会も、時間も増えてきて、しかもそれを継続できているのは本当に去年で1番よかったことだと思う。僕はまず継続が1番の敵だと思っていたからだ。これに関しては素直に自分を賞賛したい。

一方で、目指すべきレベルにはまだ達していないと思う。英語学習をはじめたときの目標を再掲。

  • 国際カンファレンスで聴講者として英語で質疑応答ができる
  • 国際カンファレンスで発表者として英語で質疑応答ができる
  • 社内の英語話者と仕事に関する議論を電話会議でできる

特に現場で求められてるのは3つ目で、Global の Developer との Communication の密度が全然足りてないと思う。日本だと Slack での議論とか、ランチだとかでふわっとわかっているようなことが足りてないと思うので、ここを次の1年でできるレベルまで引き上げたい。引き上げながらやりたいし、やりながら引き上げたい。

そうやって Global でいろいろ試したことを、日本にも展開するとか、その逆とか、そういう日本オフィスにいる日本語話者で Global Platform を見ているものとしてのバリューも発揮できたらいいなと思う。

継続してやることで、自分が苦手だと思っている「リスニング」について、どう苦手なのかの解像度もあがってきた。

英語の音としては聴こえてくるが、それを意味として自分の脳が理解できていない。まだ脳が訳そうとしているのかもしれない。いわゆる「英語を英語のまま理解する」のスピードが足りない。

これに関する打ち手は2つで、

  • シャドーイング。おそらく相当の量が必要だと思う。英語のリズムごと叩き込んで、内容を自分が理解している英文をひたすら自分で発して染み込ませていく
  • 語彙。単語、イディオム両方。おそらくこれの絶対量が足りないので、1分中に「?」が複数個あって止まるんだと思う。これが1つ程度だと推測でいけたりするんだと思う

ということで、たぶんこのあたりの量をあげることでどこかでブレイクスルーがくるんじゃないかと思っている。

DMM 英会話については継続。理由は「1年はやるって決めたから」というのもあるが、教材を使っている(フリートークではない)のでインプットにもなっているので。

シャドーイングKubernetes Podcast を興味があるテーマに絞ってなんども繰り返し聞いている。おそらくこういうのも最初は時間がかかる類だと思うが、そこで折れずに、1度でダメなら3度、3度でダメなら5度と繰り返しやっていきたい。あとは字幕ありでやったり、音読をしたりと同じテーマでやり方をいろいろ変えてとにかく量をこなしたい。対象は他には Google の SRE 関連の教材や、SRECon の動画も取り入れる。

語彙に関してはこれからだが、iKnow か abceed あたりのアプリを頼りたい。電車内でやるのが良さそう。

学習時間としては、

  • DMM英会話:自宅、出勤前か帰宅後25分
  • シャドーイング:通勤徒歩 and 一駅か二駅歩くことで1時間ほど確保
  • 単語:電車で20分

これでもまだ1日2時間満たないので、こまったな。あとは今受けてる Coursera みたいに英語の動画を見て技術学ぶようなのができれば完璧な気がする。字幕見ながら動画見るのを20分追加しようかな。

あとはモチベーションの維持だったり振り返る機会の創出だったり、自分の位置を正しく理解するために、試験の類は定期的に受けていく。

12月に受けたが、TOEIC。しんどいので受けたくはないが、年10回開催なので2回に1回は受ける。

あと英検準一級。

あとは versant を受けてみたいと思いつつ年が明けてしまった。他におすすめのテストの類あったら教えてください。

Output

大きめの仕事をやるたびに会社の Blog を書くのは今後もやっていく。

登壇、来年は数をしぼりつつも、自分がどれだけ仕事をやっていったか、課題を解決したかの指標にもなり、同時にポートフォリオにもなるので、CFPはガンガン出していきたい。

逆に、あんまり無理もしない。準備にはそれ相応のコストがかかる。その時間で仕事の進捗を出した方がいいこともある。

年3、4回ぐらいできればいいかな。数は必要ないので、インパクトが出せそうな場所、タイミングで。

その他

カメラはゆるゆると続けていきたい。

健康はシャドーイングでのもりもりウォーキングでなんとかならないかなって思ってるけどたぶんなんとかならない。休日登山でもするかなって毎年言ってるな。

お金はもう貯められない人種なので年明け帰国後に定期預金申し込みに行きます。

でももうなんかこれでいっぱいいっぱいだな。プライベートの視野がどんどん狭くなっているような。こまったな。

おしまい。

入社してから1年半

前回

blog.chaspy.me

いつも通りシュッと書く。

この1年を見返すと、「まぁまぁたいていの仕事は1人でできるようになった」「改善や新しい仕組みの導入もできた」「オンボーディングやExperience mapなどチーム視点での取組もできた」でまぁ60点といったところだ。

この状態から半年たった。すごく密度がある半年だったようには思う。

この期間はいくらか大物を倒して、Software Engineer として幾分か成長したように思う。しんどかったのはこいつ。

quipper.hatenablog.com

あとは SLO について、1人でやっていたところからようやくみんなを巻き込みはじめるフェーズになってきて、コツコツやってきたものが実を結び始めているのも嬉しい。

そしてオンボーディングについて、1年間の総集編のようにシメを、ぼちぼちな規模のカンファレンスで話せたのも、成長の一歩だと思う。(社内でも表彰してもらえた)

blog.chaspy.me

コミュニティ活動についても、SRE Lounge, SRE NEXT, terrform-jp といろいろ貢献できた半年だったと思う。

強く思うのが、Developer だけではない、社内のひとたちとの交流が広がって、それが仕事に活きる、という機会が増えてきたこと。これは僕や周囲だけではなく、人事の方々の社内制度によるものの貢献が大きい。ありがたい。

SRE は他職種との Communication が非常に重要だということを、ひしひしと体感している次第だ。具体的に、今は Reliability Engineering をいかに Product Team に伝播させるか、といったところに注力している。組織を見つめて、サービスを見つめて、しっかりひとを知って、それぞれと丁寧にコミュニケーションをしないと簡単にはうまくいかない。(もちろん今でもすごくうまくいってる!というわけではないが、丁寧なコミュニケーションは心がけているつもり。)

もはやパターン化しつつあるが、Product Team が自己完結的に、Reliability を担保する手段として Design Doc, Production Readiness Check, Schedule Scaling, SLO を導入 / 運用してきた。Developer Team のみんなが優秀かつ思いやりのある人たちなので、いたらない点がありつつもなんとかやってこれていて本当に感謝している。

今後は上記をより強化して、Secure で 安心してできるような制約は最小限にしつつ、Platform の安定性を高めつつ、Product Team が学習コスト低く Reliability Engineering ができるような世界を作っていくつもりだ。

一方まだ足りないと思っているのが Engineering と English。おいおいマジかよそこメインというか、そこじゃん、お前は。みたいな感じでギャグのような話だが、本当の話である。

Engineering に関しては伸ばし方がさっぱりわからない。1つ1つの課題にちゃんと向き合う、というぼやっとした意識づけぐらいしか浮かんでおらず、具体的なアクションも分かっていない。今どれぐらいで、何を学ぶべきで、何をすべきで、どう活かすべきなのか。

コードで問題を解決すること、といっても広いし。なんらか基礎的なトレーニングをしないと問題が問題として解像度高く見えてこないというのもあるかもしれない。

月に一度は Golang でツールを作る、とかを目標にすればいいのかな。手段と目的感あるけど。

英語に関しては7月からオンライン英会話をはじめて、まぁ9割以上、ほぼ毎日続けている。はじめる前に比べると幾分か語彙は増えたし、喋るハードルも下がったし、楽しんだりつらかったりしながらまぁ続けられるかなという程度には習慣化できたことは大きい。

一方質というか、方法についてはオンライン英会話だけではダメで、現状は流れてくる英語を英語として、意味を認識する部分のトレーニングが必要で、リピーティング、シャドーイングをもっとしないといけないと感じている。これについてはようやく PodcastKubernetes Podcast を通勤中聴いてパクパクしている。あとは SRECon の動画なんかも休日に1本見るとかしたい。あとちょうど今日受け始めた SLO に関するトレーニングも動画で英語なので、これもついでに何周かしてシャドーイングの教材にしようと思う。

www.coursera.org

一本道でうまくなんていかないし、うまくいかないことだって、はじめてみないとわからないんだから、大丈夫、ちゃんと進んでいるよ、と自分に声かけて頑張っていきたい。

10月から(チームががっつりわかれたとかではないんだが)主に Global のほうをフォーカスすることになって、仕事上の機会も増えているんだが、英語力がないせいで失っているチャンスは気づいていないだけでたくさんあると思う。それがとても悔しい。

1月にはフィリピンとインドネシアにいくので、みんなとなかよしになってこようと思う。

というわけで次の半年がたつともう2年なんですね。いよいよベテラン感出てきてしまいますね。こまった。

得意な点、Communication や Culture making, Networking なんかは活かしつつも、苦手な点 Engineering, English をより強化して、もりもりバリュー出していきたいと思います。

おわり。

July Tech Festa 2019 で登壇した

はじめに

した。

オンボーディングのひろげかた

昨年の12月にはじめたオンボーディングが、1年という期間を経て、Quipper の文化として十分定着したと言える状態になったと思う。それまでの旅路を、いままで Blog や登壇でしてきたものも含めて、シメることができた。もちろんこれで終わりではなく、これからも俺たちのオンボーディングは続く!

今回 JTF のテーマが「Share! Your Engineering Culture!」だということもあって、ぴったりだと思って Proposal を出したら通った。良い機会をもらえた。

出た質問

  • Q もっとこうしてほしかった、鋭い声、みたいな、厳しめなフィードバックはあったか
  • A 実際にアンケートを見ると、手を動かすコンテンツがあるといい、ドメイン知識とコードとの関係の理解が難しいという意見があった。しかしこれはアクションとしてドメイン知識勉強会を実施して解消している。
  • Q 成果ははかっていないと言ったが、やるとしたらどういう項目が考えうるか
  • A Pull Request を出すまでの時間、Production へコードを投入するまでの時間、を考えたことがあるが、チーム・状況に依存する。半年後とかに状況を確認する Survey をするのもいいかもしれない。が、何を持って「成果」とするかも難しい。(今書きながら思ったのが、オンボーディングはチームビルディングと地続きなので、チームの成果で見られると良い気がする)
  • Q ゴールを設定してから実際に運用するまでにハードルを感じる。難しくなかったか。
  • A そこはあまり苦労しなかった。ゴールはゆるくていいし、実際ゴールを設定してないチームもある。まずはじめてやってみて、あとから改善すればいい、ぐらいのスタンスではじめることのほうが大事だと思う。
  • (終了後)Q. Global, 他拠点のメンバーをつなぐようなオンボーディングをしているか
  • A まったくできていない。Web Developer Team に関して言えば実装上の問題があれば必要に応じて GitHub 上で Communication を取っている。SRE に関しては Global を含め関わるし、それは必要だと思う。具体的な策はないが、各 Product の説明みたいなところは足りてないので、それを説明しつつ、機を見て出張して顔を見て話す、のが効果的かなとは思う。

関心をもってくれてるひとが集まったのもあって、質問も出たというのはよかった。

1人でもこの発表を受けてオンボーディングについて考えはじめたり、あわよくば具体的なアクションにつながるひとがいれば幸いです。

私とJTF

2年前から参加していて、今年で3回目。すごく好きなカンファレンスです。何が好きって言語化は難しいのだけれど。

2年前、まだ SRE になる前に rrreeeyyy さんの発表を聞いて SRE すげーってなったり、nari さんの発表で感銘を受けたりして、いつかこのカンファレンスで登壇したい、と思ったのが今年叶ったというのが嬉しくて、懇親会では主催のハートビーツ藤崎さんにそれを伝えられてよかった。

今回の発表は SRE に関するものではなかったけれど、同じところまであがってこれたなあというのが、後ろを振り返るとたった2年前だけど、随分遠くにきたように感じる。

JTF のおかげでキャリアが築けているといっても過言ではないので、その恩返しができて嬉しい。

前職の先輩が応援にきてくれた

JTF、去年は一応 Proposal を出したんだけど、落ちてしまって、それが確か転職するしないぐらいのタイミングでした。その Proposal で書いた内容が前職の最後の期間にやったことだったので、連絡していて、そのときのメールが gmail で発掘されたので、懐かしくなってよかったらきてねーと伝えたらきてくれました。

元気そうな姿を見せられたのも、よかったなと思います。

Design Proposal は文化を創る

今回一番楽しみにしていたセッション。

Kubernetes の Design Proposal から着想を得て、社内のああゆる提案をちゃんと Document 書こうよということで Design Proposal という形で書いていくと、文化として浸透していくよという話。

sakabe さんのセッション、結構がっつりスライドと内部の実際のissueいったりきたりしていて、生Live感がよかったし、そのやり方自体をぼくも直後の自分のセッションで真似できたのでいい体験ができた。

Conference で Speaker として参加しつつ、他の Talk を聞いて自分の Talk への Feedback となる体験すごくいい。

Wantedly さんは Microservices Monday に遊びにいったり、CTO 川崎さんとオンボーディングの話をしたり、インフラチームの 南さん に業務でやってることの情報交換をしにいったり、Terraformまわりで 田中さん と話したりで、いろいろ交流がある中で、インフラチームリーダーの坂部さんは物理でお会いしたことがなかったので、話を聴けてよかった。

オフィスが近いので何か一緒にできたらいいなあと思っている(だけで動けていない)

ちゃんとセッションを聞いて、TODOに起こしたので、本当に聴けてよかったです。

f:id:take_she12:20191209031906p:plain

Postmortem, Design Doc, Production Readiness Check, Scheduled Scaling といくつか Templates 化しているものもあって、なんとなしちゃんと運用まわってはいるんだけど、ちゃんとドキュメントとして残そうと思いました。

社外の登壇者と合同発表練習

今回、もちろん Quipper 社内でも発表練習を行なったが、45分という長いセッションに2回も3回も付き合ってもらうことに抵抗があったこともあって、いろんな視点からの意見をもらうという意味と、セッションが6並列でなかなか見れないセッションも多いということで、同じ登壇者の方と練習を行なった。

オイシックスさんがショートセッション3連発で出られていて、もともと もりはやさん青木さん とは Terraform meetup で面識があったので、ちょうどいいということで提案して、受け入れてくれました。登壇者だけでなく、彼らの上司の方々も見てくれて、非常に良い体験でした。

また、Twitter で募集したところ、ariakiさんが声をかけてくれて、はじめましてですが練習をして、すごく良いフィードバックをもらえました。

当日は並列で走ってるのもあってなかなかセッションが見れないことも多いし、いい感じに緊張感が保てるので、今後もこういうのはやっていきたい。

カンファレンスの廊下

これ最初聞いた時よくわかんなかったんですが、完全に意味がわかりました。

はてなhokkai7go さんと、廊下ではないですが外を散歩したり、終わったあとビールを飲んだりして最高の体験をしました。

とはいえもともと知っていた間柄というのが前提なので、誰でもできるかというとなかなか難しいですね。

次の登壇

テーマはがらっと変わって、SRE NEXT で SLO について話します。SLO について話すということは、きっと絶対 Site Reliability Engineering についての話もします。

https://sre-next.dev/schedule

SRE なので、SRE についての発表がようやくできるというのも嬉しい。SRE Lounge のスタッフやってることもあってそういう場がないので SRE NEXT 作ったってのもある。こっちも良いカンファレンスになるといいな。登壇者としても、スタッフとしても、あともう少し頑張っていこう。

おわりに

登壇を楽しくやれたのも、すごいよかった。

話したひと、JTFスタッフ、登壇者、参加者、みなさんありがとうございました!また来年も会えたらいいな。

Production Engineer

SRECon みてると「Production Engineer」という Role で登場するひとがまぁまぁいて、まぁ本番環境で Operation をしうるひとで、SREもうそうっちゃそうなんだろうなあと思いつつ、どういう Role なのかを調べてみる。

SRECon EMEA 2019

www.usenix.org

Production Engineer の肩書きのひとを探してみる。

SoundCloud

SRE in the Third Age

SRE in the Third Age | USENIX

Uber

A Tale of Two Rotations: Building a Humane & Effective On-Call | USENIX

Shopify

Network Monitor: A Tale of ACKnowledging an Observability Gap | USENIX

Zero-Downtime Rebalancing and Data Migration of a Mature Multi-Shard Platform | USENIX

Advanced Napkin Math: Estimating System Performance from First Principles | USENIX

Expect the Unexpected: Preparing SRE Teams for Responding to Novel Failures | USENIX

多いな。すごい。

Google

All of Our ML Ideas Are Bad (and We Should Feel Bad) | USENIX

Facebook

Load Balancing Building Blocks | USENIX

Job Description

出てきた会社の JD を漁ってみる。

SoundCloud

Enginnering Levels の記事がなぜかでてきて読んでしまった。

developers.soundcloud.com

で、job のページみたけどいまはオープンになってないようだ。

jobs.soundcloud.com

Uber

あった。

https://www.uber.com/global/ja/careers/list/46494/

読んだけど SRE との違いがよくわからん。

Production Engineering is an organization of engineers who work with our production services throughout their entire life cycle, from design and architecture, through implementation, deployment, and sustaining operation.

よりメタなんだろうか。どうなんだろう。

Senior SRE をみてみる。

https://www.uber.com/global/ja/careers/list/56139/

Production Engineer と同じジャン。。。

Shopify

Production Engineer - Sr Kafka Engineer

Kafka のことばっか注力してる感じだな。

https://www.linkedin.com/jobs/view/1131575400?trk=d_flagship3_salary_explorer&refId=f7bf60f0-b6a3-47c9-a91d-b44c0221c7c8

This position for the Production Engineering team is a hybrid software/system engineer on the Product Sourcing team. Our team covers the disciplines of site reliability engineering, infrastructure engineering, and developer productivity, all to empower merchants and boost their confidence in Shopify’s products.

Site Reliability Engineering だけでなく、なんでもする感じ。

Facebook

www.facebook.com

Production Engineers at Facebook are hybrid software/systems engineers who ensure that Facebook's services run smoothly and have the capacity for future growth. They are embedded in every one of Facebook's product and infrastructure teams, and are core participants in every significant engineering effort underway in the company. Our team is comprised of varying levels of experience and backgrounds, from new grads to industry veterans. Relevant industry experience is important (Site Reliability Engineer (SRE), Systems Engineer, Software Engineer, DevOps Engineer, Network Engineer, Systems Administrator, Linux Administrator, Database Administrator or similar role), but ultimately less so than your demonstrated abilities and attitude. We sail into uncharted waters every day at Facebook in Production Engineering, and we are always learning.

Uber と似たようなことが書いてある。

career のページで SRE を探したけど出てこなかったので、 Production Engineer に統一しているのかもしれない。

おわり

たいした違いはなくて、呼び方の問題ぽい。

Unicorn の Metrics

Rails で使われているアプリケーションサーバUnicorn

bogomips.org

Master Process から fork して Worker Process が実際の処理を行う。

Unicorn Worker Killer

一定回数以上リクエストがくるか、一定量以上のメモリを使用した場合、Worker Process を再起動する君。

github.com

設定

config/unicorn.rb

  • worker_processes: Worker Process の数
  • timeout: timeoutの秒数

prometheus_exporter

Metrics を取得するため、prometheus_exporter を読み込んでいる。

github.com

同僚の takeyama さんの記事

qiita.com

コードをみてみる。

prometheus_exporter/lib/prometheus_exporter/instrumentation/unicorn.rb

github.com

指定された frequency で pid_file から pid を取得して unicorn_collector.collect で metrics を取得して json で返す。

collect_unicorn_stats でとっているのは以下3つ。

  • metric[:active_workers_total] = stats.active
  • metric[:request_backlog_total] = stats.queued
  • metric[:workers_total] = worker_process_count

worker_process_count は直後の private method で定義されている通りで、単純に pgrep で取ってきている。

      result = `pgrep -P #{pid} -f unicorn -a`
      result.lines.count

stats というのがどこからくるかというと listener_address_stats という private method からきていて、tcp であれば Raindrops::Linux.tcp_listener_stats([@listener_address])[@listener_address] を返している。

Raindrops

はてさて Raindrops とは何か。

bogomips.org

raindrops is a real-time stats toolkit to show statistics for Rack HTTP servers. It is designed for preforking servers such as unicorn, but should support any Rack HTTP server on platforms supporting POSIX shared memory. It may also be used as a generic scoreboard for sharing atomic counters across multiple processes.

ほー。

というわけで

Prometheus Exporter で取れる 3つの Metrics は以下

github.com

  • workers_total: 'Number of unicorn workers.',
  • active_workers_total: 'Number of active unicorn workers',
  • request_backlog_total: 'Number of requests waiting to be processed by a unicorn worker.'

active ってのは実際に処理をしているってことなのかな?queued は unicorn に処理されるのを待っているリクエストの数。

request_backlog_total が高い状態が続いた場合、Timeout となってしまいそうだ。

どう解決すればいいのか

  • Unicorn の Pod の Replicas そのものを増やす?
  • Unicorn の Worker 数を増やす?
  • 時間がかかっている処理を高速化する?

Horizontal Pod Autoscaler の Custom Metrics でいけないかな?と思ってググったけどたどり着けず。

kubernetes.io

その他の Metrics

内製の gem が送っているやつがあるようだ。

/proc/pid/stats の cpu time をもってきて、毎秒比較し、それが変化していなければ idle と判定しており、そのほかの metrics はそれに基づいて計算している。 その結果をDatadog に送るもの。

おわりに

request_backlog_total がしばしば増えていて、それによって エラーも出ているようなのでまずは Metrics の理解が大事だと思ったのでいろいろみてみた。勉強になった。さてどうしよう。