Upgrade to Pro — share decks privately, control downloads, hide ads and more …

⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み

⛵️ Istioのサービス間通信を実現するサービスディスカバリーの仕組み

3-shake SRE Tech Talk 2022』の登壇資料です

Istioのサービスディスカバリーの仕組みについて、Envoyを交えながら解説しました。

スライドでは仕組みの詳細を解説できませんでしたので、ぜひ元記事 (Istioのサービス間通信を実現するサービスディスカバリーの仕組み) も参照ください👍

長谷川広樹 (俺です)

December 15, 2022
Tweet

More Decks by 長谷川広樹 (俺です)

Other Decks in Programming

Transcript

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  9. 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にリクエストを送信

    View full-size slide

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

    View full-size slide

  11. 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にリクエストをロードバラシング

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  14. 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をじっくり冒険していただけると

    View full-size slide

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

    View full-size slide

  16. リスナー値を確認する
    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のリスナー値を
    確認したとする

    View full-size slide

  17. 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
    ... 中略

    View full-size slide

  18. ルート値を確認する
    $ 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のルート値を
    確認したとする

    View full-size slide

  19. 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
    ... 中略

    View full-size slide

  20. クラスター値を確認する
    $ 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のクラスター値を
    確認したとする

    View full-size slide

  21. 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
    ... 中略

    View full-size slide

  22. エンドポイント値を確認する
    ここでは
    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 から確認できる

    View full-size slide

  23. 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:
    ... 中略

    View full-size slide

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

    View full-size slide