Slide 1

Slide 1 text

1 2022/12/15 3-shake SRE Tech Talk 株式会社スリーシェイク 長谷川広樹 @Hiroki_IT github.com/hiroki-it hiroki-hasegawa.hatenablog.jp はてな Istio のサービス間通信を実現する サービスディスカバリーの 仕組み

Slide 2

Slide 2 text

マイクロサービスアーキのインフラ領域が仕事 ・マイクロサービスアーキを支えるインフラ技術 ・ドメイン駆動設計 俺です 社内で色々ふざけ過ぎてるので、そろそろ怒られるかもー ・サービスメッシュ (Istio ←推し❤) ・IaC (Kubernetes, Helm, Terraform) ・CICD (GitLab CI, ArgoCD) ・監視 (Prometheus, Fluentd, Kiali, OpenTelemetry入門中) ・クラウドインフラ (AWS, ちょいGoogle Cloud) マイクロサービスアーキ関連の技術が好き 虫捕りついでに 虫食ってた話 する?

Slide 3

Slide 3 text

発表の元記事 サービスディスカバリーの詳細な仕組み については元記事を見てね 🔎 (本発表の参考リンクも記事中にあるよ) https://hiroki-hasegawa.hatenablog.jp/entry/2022/12/25/060000

Slide 4

Slide 4 text

サービスディスカバリー (以下 SD) とは

Slide 5

Slide 5 text

マイクロサービスアーキテクチャにおけるSDとは 宛先マイクロサービスを検出し 送信元マイクロサービスが宛先と通信できるようにする

Slide 6

Slide 6 text

なぜSDが必要なのか 宛先マイクロサービスのインスタンスは スケーリングで増減するたびに ネットワーク上の宛先を変化させる 宛先をその都度検出し 送信元マイクロサービスが 宛先と継続的に通信できる必要性

Slide 7

Slide 7 text

SDの要素 要素 責務 送信元マイクロサービス リクエストを送信 宛先マイクロサービス リクエストを受信 サービスレジストリ 宛先マイクロサービスの宛先情報を保管 ロードバランサー 宛先マイクロサービスのインスタンスにロードバランシング 名前解決 DNSベースのSDで使用するため、IstioのSDでは扱わない

Slide 8

Slide 8 text

Istioにおける サービスディスカバリーの仕組み

Slide 9

Slide 9 text

IstioによるSDの仕組み Podに自動注入される istio-proxyコンテナが軸 1. kube-apiserverがPod等の宛先情報を etcdなどに保管 (これはK8sの通常の仕組み) 2. discoveryはkube-apiserverから Pod等の宛先情報を取得して保管 3. istio-proxyはdiscoveryから Pod等の宛先情報を取得 4. 送信元マイクロサービスが 宛先マイクロサービスにリクエストを送信し iptablesがistio-proxyにリダイレクト 5. istio-proxy内でロードバランシングされ 宛先Podにリクエストを送信

Slide 10

Slide 10 text

(あなたの心の声が聞こえます) istio-proxyコンテナ 詳しく知りたいなぁ...😒

Slide 11

Slide 11 text

IstioによるSDの仕組み istio-proxyを少し詳しく... 1. kube-apiserverがPod等の宛先情報を etcdなどに保管 (これはK8sの通常の仕組み) 2. discoveryはkube-apiserverから Pod等の宛先情報を取得してメモリ上に保管 3. istio-proxy内のEnvoyはpilot-agentを介して discoveryのADS-APIからPod等の宛先情報を取得 4. 送信元マイクロサービスが 宛先マイクロサービスにリクエストを送信し iptablesがistio-proxyにリダイレクト 5. istio-proxy内のEnvoyは 宛先Podにリクエストをロードバラシング

Slide 12

Slide 12 text

(あなたの心の声が聞こえます) Envoyが取得した宛先情報 見てみたいなぁ...😒

Slide 13

Slide 13 text

Envoy が ADS-APIから取得した情報を 見てみよう

Slide 14

Slide 14 text

EnvoyがADS-APIから取得した情報を見てみよう $ kubectl exec \ -it foo-pod \ -n foo-namespace \ -c istio-proxy \ -- bash -c "curl http://localhost:15000/config_dump" | yq -P 実際にEnvoyに登録されている宛先情報は istio-proxyの localhost:15000/config_dump からJSONで取得可能 JSONだと見にくいので、yqコマンドでYAMLに変換するとよい フォントサイズの制約上『中略』が多くなっています󰣹 お手元のIstioで、後ほどEnvoyをじっくり冒険していただけると

Slide 15

Slide 15 text

Envoyの処理の流れ リスナー ⇨ ルート ⇨ クラスター ⇨ エンドポイント 確認できた設定値を、Envoyの処理の流れを当てはめていく...

Slide 16

Slide 16 text

リスナー値を確認する istio-proxyがADS-APIから取得したリスナー値は /config_dump?resource={dynamic_listeners} から確認できる $ kubectl exec \ -it foo-pod \ -n foo-namespace \ -c istio-proxy \ -- bash -c "curl http://localhost:15000/config_dump?resource={dynamic_listeners}" | yq -P ここでは foo-pod内でbar-podのリスナー値を 確認したとする

Slide 17

Slide 17 text

configs: - "@type": type.googleapis.com/envoy.admin.v3.ListenersConfigDump.DynamicListener name: 0.0.0.0_50002 # リスナー名 active_state: listener: "@type": type.googleapis.com/envoy.config.listener.v3.Listener name: 0.0.0.0_50002 address: socket_address: address: 0.0.0.0 # 受信したパケットのうちで、宛先 IPアドレスでフィルタリング port_value: 50002 # 受信したパケットのうちで、宛先ポート番号でフィルタリング filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager rds: route_config_name: 50002 # 本リスナーに紐づくルート名 ... 中略 - "@type": type.googleapis.com/envoy.admin.v3.ListenersConfigDump.DynamicListener ... 中略

Slide 18

Slide 18 text

ルート値を確認する $ kubectl exec \ -it foo-pod \ -n foo-namespace \ -c istio-proxy \ -- bash -c "curl http://localhost:15000/config_dump?resource={dynamic_route_configs}" | yq -P istio-proxyがADS-APIから取得したルート値は /config_dump?resource={dynamic_route_configs} から確認できる ここでは foo-pod内でbar-podのルート値を 確認したとする

Slide 19

Slide 19 text

configs: - "@type": type.googleapis.com/envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig route_config: "@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration name: 50002 # ルート名 virtual_hosts: - name: bar-service.bar-namespace.svc.cluster.local:50002 domains: - bar-service.bar-namespace.svc.cluster.local # ホストベースルーティング ... 中略 routes: - match: prefix: / # パスベースルーティング route: cluster: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local # 本ルートに紐づくクラスター名 ... 中略 - '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig ... 中略

Slide 20

Slide 20 text

クラスター値を確認する $ kubectl exec \ -it foo-pod \ -n foo-namespace \ -c istio-proxy \ -- bash -c "curl http://localhost:15000/config_dump?resource={dynamic_active_clusters}" | yq -P istio-proxyがADS-APIから取得したクラスター値は /config_dump?resource={dynamic_active_clusters} から確認できる ここでは foo-pod内でbar-podのクラスター値を 確認したとする

Slide 21

Slide 21 text

configs: - "@type": type.googleapis.com/envoy.admin.v3.ClustersConfigDump.DynamicCluster cluster: "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local # クラスター名 type: EDS eds_cluster_config: eds_config: ads: {} initial_fetch_timeout: 0s resource_api_version: V3 # クラスターに紐づくエンドポイントの親名 service_name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local ... 中略 - "@type": type.googleapis.com/envoy.admin.v3.ClustersConfigDump.DynamicCluster ... 中略

Slide 22

Slide 22 text

エンドポイント値を確認する ここでは foo-pod内でbar-podのエンドポイント値を 確認したとする $ kubectl exec \ -it foo-pod \ -n foo-namespace \ -c istio-proxy \ -- bash -c "curl http://localhost:15000/config_dump?include_eds" | yq -P istio-proxyがADS-APIから取得したエンドポイント値は /config_dump?include_eds から確認できる

Slide 23

Slide 23 text

configs: dynamic_endpoint_configs: - endpoint_config: "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment cluster_name: outbound|50002|v1|bar-service.bar-namespace.svc.cluster.local # エンドポイントの親名を指定している。 endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 11.0.0.1 # 冗長化されたbar-podのIPアドレス port_value: 50002 # bar-pod内のコンテナが待ち受けているポート番号 ... 中略 - endpoint: address: socket_address: address: 11.0.0.2 # 冗長化されたbar-podのIPアドレス port_value: 50002 # bar-pod内のコンテナが待ち受けているポート番号 ... 中略 - endpoint_config: ... 中略

Slide 24

Slide 24 text

EnvoyがADS-APIから取得した値を整理する 送信元マイクロサービスが “<任意のIP>/:50002” 宛てのリクエストを送信した場合 0.0.0.0_50002 リスナーで受信し bar-pod (11.0.0.X/:50002) にロードバランシング