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

microservices-infrastructure-with-hashicorp-suite

 microservices-infrastructure-with-hashicorp-suite

HashiTalks: Japan 2020 での発表資料です

7e2a262076c20f155933ae3befe853da?s=128

shuhei

July 02, 2020
Tweet

Transcript

  1. Shuhei Kunikane @ LINE Corporation at HashiTalks: Japan 2020 (2020.7.2)

    Hashicorp Suiteで実現する マイクロサービス基盤 – Nomad編
  2. • Shuhei Kunikane 国兼 周平 @shuheikun_i (twitter) • LINE Corporation

    フィナンシャル開発センター SREチーム • 主にLINE証券の基盤を担当 ABOUT ME
  3. LINE証券 ABOUT OUR SERVICE • 2019.08 OTCでの株式取引サービス開始 • 2019.10 かんたん本⼈確認(eKYC)開始

    • 2019.11 投資信託サービス開始 • 2020.03 FXサービス開始 • 2020.05 取引所取引および信⽤取引サービス開始 • 2020.06 投資信託のつみたて投資サービス開始 ←本⽇紹介する基盤の運⽤開始
  4. LINE証券のマイクロサービス基盤 built around Hashicorp Suite

  5. 構成要素 l Hashicorp社のService Networking⽀援ツール l Service Discovery / Healthcheck システム内で稼働するサービスの状態を収集し状態を監視

    リクエストに応じてクライアントにサービス情報を提供 l KVS Key-Valueで構成されるデータストア アプリケーションのconfiguration repositoryとしても利⽤可能
  6. 構成要素 l Hashicorp社のDeployツール l 宣⾔的サービス定義 ユーザは宣⾔的記述によりサービスの理想的な状態を表現 Nomadはサービスを監視しベストエフォートでそれを維持 l 複数のアプリケーションを連携させ1つのサービスとして定義 l

    Consul / Vault連携 Service / Healthcheck⾃動登録(Consul) KVSの 読み込み / 監視 (Consul,Vault) ACL Token管理の移譲(Vault)
  7. 構成要素 l Hashicorp社のSecret Managementツール l Tokenやパスワードの⽣成 / 配布 / 管理

    l 機密情報の安全な保存 / 提供 l PKI CAとしてサービス提供
  8. 構成要素 l ⾼機能・⾼性能 Proxy Server l xDS Listener, Route, Cluster,

    Endpoint, Secret など、様々な設定を管理サー バ(Control Plane)から動的に取得し動的に反映
  9. 構成要素 l アプリケーションを環境ごとパッケージング l 基盤とアプリケーションの依存関係を限定 Imageとしてパッケージングされたアプリケーションを実⾏するため に必要なのは基本的にDocker Engineのみ アプリケーションのSetupでHost環境を汚さない l

    Bridge Network コンテナ間の通信を⽣かしながら不要なサービスを外部から隠す
  10. 構成要素 l 宣⾔的記述(Playbook)による構成管理 l UIからAnsibleのPlaybookを起動

  11. Subsystem-B Subsystem-A Service Mesh Router Cluster API-Gateway-A Cluster Client Hardware

    LoadBalancer Envoy Envoy Envoy Application Envoy Service-A1 Cluster Application Envoy Service-A2 Cluster Application Envoy API-Gateway-B Cluster Application Envoy Service-B1 Cluster Application Envoy All of about 30 Services in 4 Subsystems are running as Nomad Job Traffic between envoys is protected by mTLS using Vault-issued certificates External Services DB MQ
  12. Service Discovery Node Docker Bridge Network Task Group Application Container

    Envoy Container Task Group Application Container Envoy Container Other Sercvices (Envoys) Control Plane Consul Client Consul Server Nomad Client Nomad Server Ansible/AWX kick job allocate start TaskGroup with service port assign register service propagate service info (Blocking Query) propagate config by xDS (gRPC stream) Dynamic Service Port Business Traffic propagate service info Dynamic Service Port Business Traffic make envoy config propagate config template (Blocking Query) register envoy config template for each service to KVS health check
  13. Nomad ( We are using ver. 0.9.5 )

  14. Task 2 Sidecar Task 1 Application Sidecar PatternのService定義 Ingress Port

    (Static) App Admin Port (Static Port) Service Endpoint (Static Port) Healthcheck Endpoint (Static Port) Consul Other Service Application Task publishes no service directly. Watching if upsterams are healthy (ex: DB) Main Service Ingress Port (Dynamic) App Admin Port (Dynamic) Healthcheck Business Request
  15. Sidecar PatternのService定義 task "sample-service-sidecar" { config { port_map { ingress

    = 3001 appadmin = 9902 } } resources { network { port "ingress" {} port "appadmin" {} } } service { name = "sample-service" port = ”ingress" address_mode = "host" check { name = "sample-service-alive" type = "http" method = "GET" port = "appadmin" path = "/health" interval = "5s" timeout = "5s" } } } Task2 (Sidecar) l Task2(Sidecar)でのみserviceを公開 l config.port_mapでコンテナのサービスポートにLabel をつける l resources.network.portで動的ポートを払い出しLabel 付けされたポートにマップする l service.portで当該serviceが公開するポートを指定 l service.checkでappadminポートへのhealthcheckを定 義する(サービスポートとhealthcheckのポートは同⼀ でなくてもOK) l メトリクス取集などの⽬的でappadminポートを個別 のserviceとしても公開
  16. Node Tasks間の通信 Docker Bridge Network (user-defined) Task Group Task 1

    Application Container Task 2 Sidecar Container 192.168.200.aaa (by DHCP) 192.168.200.bbb (by DHCP) Docker Embedded DNS Server Lookup <name-of-task1> Lookup <name-of-task2> ENV EGRESS_HOST= <name-of-task2> ENV EGRESS_PORT= 3101 <name-of-task1>. IN A 192.168.200.aaa <name-of-task2>. IN A 192.168.200.bbb ENV LOCAL_APP_HOST= <name-of-task1> ENV LOCAL_APP_SERVICE_PORT= 8080 To be registered when Job started Necessary to use user-defined bridge network to enable embedded DNS Server. (not default bridge network)
  17. Tasks間の通信 task " sample-service-sidecar" { driver = "docker" config {

    image = ”ourregistry.com/ourproject/sidecar-envoy:1.0.0" network_mode = ”custom_bridge” network_aliases = ["${NOMAD_TASK_NAME}-${NOMAD_ALLOC_INDEX}"] } env { LOCAL_APP_HOST = " sample-service-app-${NOMAD_ALLOC_INDEX}" LOCAL_APP_SERVICE_PORT = ”8080" } } task ”sample-service-app" { driver = "docker" config { image = ”ourregistry.com/ourproject/sample-service:1.0.0" network_mode = ”custom_bridge” network_aliases = ["${NOMAD_TASK_NAME}-${NOMAD_ALLOC_INDEX}"] } env { EGRESS_HOST = " sample-service-sidecar-${NOMAD_ALLOC_INDEX}" EGRESS_PORT = ”3101" } } Task1 (Application) Task2 (Sidecar) l config.network_modeでユーザ定義bridge networkを指定(事前に各nodeにsetupしておく) l config.network_aliasesでcontainerに別名をつけておく(これがDNSに登録される) NOMAD_TASK_NAME や NOMAD_ALLOC_INDEX などのNomad環境変数を利⽤し、TaskGroup内 の他のTaskから予測可能な値とする l envで通信相⼿となるTaskの宛先情報をContainerに伝える
  18. Updateパラメータのチューニング Before Update Alloc1 Other Service Consul Control Plane Request

    Update Started Alloc1 Other Service Consul Control Plane Deregister Service Request Service Info (Alloc1,Alloc2) Update Kicked l UpdateがKickされると、Nomad Jobは最初にConsulからサービス情報を削除する l この時点でUpdate中のAllocationの情報はConsulのService Discoveryで提供されなくなるが、他サー ビスのRouting情報までは反映されておらず、 Requestは継続して届く Alloc2 Alloc2 Service Info (Alloc1,Alloc2) Service Info (Alloc1,Alloc2) Service Info (Alloc1,Alloc2)
  19. Updateパラメータのチューニング l 時間が経過すると他サービスのRouting情報に削除が反映され、Requestが届かなくなる l [Routing情報に削除が反映されるまでの時間]+[残存リクエストへの応答にかかる時間] に少し余裕を もった値をshutdown_delayにセットしておく必要がある l アクセス状況などにより必要な待機時間は変動する可能性があるので、Envoyの設定とあわせて チューニングが必要

    shutdown_delay Passed New Allocation Start Before Shutdown Alloc1 Other Service Consul Control Plane Request Service Info (Alloc1,Alloc2) Alloc2 Service Info (Alloc1,Alloc2) Shutdown Alloc1 Other Service Consul Control Plane Request Alloc2 Service Info (Alloc2) Service Info (Alloc2)
  20. Nomad Server Nomad Client Vault連携 - Task Server Token Task

    Client Token Issued and injected when agent started Issued and injected when job started l Nomad Server Agentの起動時にServer Tokenを注⼊する l Nomad ServerはJobの起動時にServer Tokenを使ってClient Tokenを発⾏しTaskに注⼊する l TaskはClient Tokenを使ってVaultにアクセスしSecretを取得する Secret Secret Secret Approle Vault
  21. Vault連携 - Task l Nomad ServerがClient Tokenを発⾏する際に使うToken l Nomad Server

    Agentの起動時に注⼊される l Serverが起動している間は⾃動的にrenewする l Client Tokenを管理するためのcapabilitiesが要求される Server Token path "kv/*" { capabilities = ["read","list"] } path "auth/token/create/nomad-client" { capabilities = ["update"] } path "auth/token/roles/nomad-client" { capabilities = ["read"] } path "auth/token/lookup" { capabilities = ["update"] } path "auth/token/revoke-accessor" { capabilities = ["update"] } path "sys/capabilities-self" { capabilities = ["update"] } path "auth/token/renew-self" { capabilities = ["update"] } nomad-server-policy.hcl (vault)
  22. Vault連携 - Task l Nomad Client上で動くTaskがVaultにアクセスする際に使うToken l Job起動時にNomad Serverにより発⾏/注⼊される l

    Taskが起動している間は⾃動的にrenewする l どのroleから発⾏するかはserver agentのconfigで指定 ※1 l 適⽤するpolicyはTask単位で指定 ※2 Client Token vault { enabled = true address = "https://example-vault.com:8200" create_from_role = "nomad-client" } job "example-job" { group "example-group" { task "example-task" { vault { policies = ["nomad-client-1"] } } } ※1 agent.hcl (nomad) ※2 job.hcl (nomad) path "kv/*" { capabilities = ["read","list"] } nomad-client-policy-1.hcl (vault)
  23. Vault連携 - Task job "example-job" { group "example-group" { task

    "example-task" { vault { policies = ["nomad-client"] change_mode = "noop" } template { data = <<EOH {{ with secret "kv/data/example" }} EXAMPLE_SECRET_1="{{ .Data.data.secret1 }}" EXAMPLE_SECRET_2="{{ .Data.data.secret2 }}" {{ end }} EOH destination = "secrets/file.env" env = true change_mode = "noop" } } } } job.hcl (nomad) l template stanza でsecret取得のScriptを埋め込む l vault.change_mode は Client Tokenが新しくなったときの挙 動を設定する Defaultはrestart(Tsakの再起動) 主にrenew失敗したときに発⽣する l template.change_mode は取得したsecretにvault側で変化が あった場合の挙動を設定する Defaultはrestart(Tsakの再起動) NomadTaskはVault内のSecretをポーリングにより監視する l 起動時にだけSecretアクセスが発⽣するような場合は、どち らもnoopに設定しておいた⽅が安全 Task Definition
  24. Vault連携 - ACL l Nomad ACL には Tokenの有効期限を管理する機能がない l Vaultに対してNomad

    ACLの管理権限を委譲することにより有効期限の制御が可能になる l Nomad ACL Tokenに関する運⽤上のリクエストはVaultが受付ける l Vaultには様々なツール⽤のSecret Engineが⽤意されている 当然Consulも同じことができる Nomad Vault Nomad Secret Engine ACL Token Role Issue / Revoke creds request Policy TTL Control
  25. Nomad Watcher l Nomad Agentの出⼒するLogはエラー通知などには利⽤しにくい (出⼒単位やLevelの設定などが運⽤の観点と異なる) l Nomadでは終了したJobやAllocationの情報はGCにより削除されて いくため、過去に遡った調査を可能にするためには⻑期間保存す る仕組みを別途⽤意する必要がある

    l LINE証券では監視ツール(Nomad Watcher)を開発 すべての Allocation / Job / Node の状態変化を捕捉し履歴を保存 前後の状態から正常性を診断、異常なら発報
  26. 今後の展望 最新版にUpdateし、新機能を取り⼊れてさらに運⽤を改善していきたい l Consul Connect with Nomad / CNI l

    Lifecycle (Task Dependency) l podman driver l Auto Scale l Multi DC
  27. 過去の発表資料 l Envoy Meetup Tokyo #1 (2020.01.08) https://speakerdeck.com/kencharos/microservices-infrastructure- with-envoy-consul-nomad l

    LINE Financialエンジニア採⽤説明会 (2019.10.19) https://logmi.jp/tech/articles/322097
  28. WE ARE HIRING ! 私たちのチームで⼀緒に働いてくれる仲間を募集しています 興味をもっていただけた⽅はDMください! @shuheikun_i (twitter)

  29. THANK YOU