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

Consul Spring-Cloud-Consul 入門 / Consul and Spri...

Consul Spring-Cloud-Consul 入門 / Consul and Spring-Cloud-Consul introduction

2020/4/8 at JSUG.
sample code is https://github.com/kencharos/consul-spring-tutorial

Kentaro Maeda

April 08, 2020
Tweet

More Decks by Kentaro Maeda

Other Decks in Programming

Transcript

  1. Spring Cloud Consul https://spring.io/projects/spring-cloud-consul より、 Spring Cloud Consul は HashiCorp

    Consul と連携して、Spring Boot に⼤規模分 散システムを構築するための機能として Service Discovery, Distributed Configuration, Control Bus を提供する。 Spring Cloud Consul で提供される機能は Consul の機能であり、 Spring Cloud Consul を活⽤するには、Consul の理解が⽋かせない。 4
  2. HashiCorp Consul について https://www.consul.io 分散システム上のサービス管理を⾏うソフトウェア ・Service Discovery - どのノードに何のサービスがあるかカタログ化 ・Health

    Check - ノード・サービスの死活監視と通知 ・Key/Value Storage - サービス横断で設定を参照・更新する ・Multi Datacenter - 別のDCにあるConsulクラスタと接続・同期する ・Service Mesh - サービス間のセキュアな通信を管理する 5
  3. Consul の特徴 ・Go⾔語製のシングルバイナリと設定ファイルのみで動く ・DBなどは不要。インストールとノードの追加が楽 ・Server/Agent によるクラスタ構成 ・Agent は⾃ノードの情報をServerに伝え、ヘルスチェックを⾏う ・Server はAgentの情報を収集・同期する

    ・Server/Agentはどちらも同じバイナリで設定内容が異なる ・⾼可⽤性 ・Server の過半数が⽣存していればクラスタを維持できる ・Agentの追加が容易であり、⼤規模なクラスタを構築しやすい ・WebAPI, CLI, DNS, UI など複数のインタフェースがある 6
  4. Service の登録 Consul へのサービス登録・削除は⾃分でAPI経由で⾏う。⾃動収集はしない。 ・例) service1 のアドレス、HTTPヘルスチェックを設定して登録 { // service1.json

    "ID": "service1", // consul 全体でユニークなID "Name": "service1", // 同じ種類のサービスをグルーピングするサービス名 "Address": "127.0.0.1", "Port": 8080, "Check": { "DeregisterCriticalServiceAfter": "60m", "HTTP": "http://127.0.0.1:8080/actuator/health", "Interval": "5s" } } # 同⼀ノードのagent に対してAPI 呼び出し curl -X PUT http://localhost:8500/v1/agent/service/register -d @service1.json 8
  5. サービス情報の取得 登録したサービスはAPI, CLI, DNS経由で参照できる。 別ノードのAgentで登録されたサービスの情報も参照できるので、ノードやサービス が増えても常にローカルAgentに問い合わせれば良い。 #DNS $ dig @127.0.0.1

    -p 8600 service1.service.dc1.consul. SRV ;; ANSWER SECTION: service1.service.dc1.consul. 0 IN SRV 1 1 8080 myhost.node.dc1.consul. ;; ADDITIONAL SECTION: myhost.node.dc1.consul. 0 IN A 127.0.0.1 myhost.node.dc1.consul. 0 IN TXT "consul-network-segment=" // API 呼び出し。レスポンスは⼀部省略 $ curl http://localhost:8500/v1/health/service/service1 [ { "Node": { "ID": "xxx", "Node": "myhost", "Address": "127.0.0.1",}, "Service": { "ID": "service1", "Service": "service1","Address":"127.0.0.1", "Port": 8080 }, "Checks": [//] } ] 9
  6. Key/Value Storage consul クラスタ間で設定の登録・参照を⾏う 登録された値はクラスタ内で共有 # key1=value1 で登録 $ curl

    -X PUT http://localhost:8500/v1/kv/key1 -d "value1" # common/key2=value2 で登録 $ curl -X PUT http://localhost:8500/v1/kv/common/key2 -d "value2" # key1 をJSON で取得。value は base64 エンコード $ curl http://localhost:8500/v1/kv/key1 [{ "Key": "key1", "Value": "dmFsdWUx","LockIndex": 0, "Flags": 0, "CreateIndex": 22,"ModifyIndex": 22 }] # common/key2 を RAW 形式で取得 curl http://localhost:8500/v1/common/key2 value2 10
  7. Watch/Event サービスの状態の変化やKey/Valueの変化、ヘルスチェック、任意のイベントについ て通知を受け取ることができる。 # service1 サービスの状態を監視し、変化したら hoge.sh を実⾏する consul watch

    -type service -service "service1" ./hoge.sh # 任意のイベント発⾏ consul event -name=test value1 # イベント通知が来たら cat で内容を出⼒ consul watch -type=event -name=test cat Web APIの場合、Blocking Query というロングポーリングの⼿段がある # 特定の時点(index=83) 以降 key1 の値が変化するまで10 秒待つ $ curl http://localhost:8500/v1/kv/key1?index=83&wait=10s 11
  8. Consul のユースケース Consul はクラスタ内のサービスの状態管理とKey/Valueの値の保持に専念 これを使って何をするかは実装者次第。 Consul Connect, Spring Cloud Consul

    はサービス間通信をConsulで⾏う ・例1) サービス情報を使⽤して、動的な構成変更に追従するサービス間通信を⾏う ・Consul Connect, Spring Cloud Consul ・例2) Key/Value Storage でクラスタ全体で共有する設定を⼀元管理する ・Spring Cloud Consul ・例3) 負荷分散対象のサービスをwatchで監視して、変化があればロードバランサー の設定を変更して再起動 ・例4) Multi Datacenterで クラウド/オンプレミス/k8s を横断するサービス⼀覧を 作る 12
  9. Consul Connect (Service Mesh) Consul に標準で組み込まれている、サービス間通信を管理する機能 ・L4プロキシ か L7プロキシ(envoy) をサービスごとにサイドカーとして起動し、サ

    ービス間通信で使⽤するローカルポートを提供 ・サービス間、負荷分散、死活監視はConsul側で提供 ・通信相⼿のサービスがどのノード・ポートにあってもローカルポートに繋げば Consulが解決する ・通信経路は mTLSで暗号化、Consul クラスタ外からのアクセスは不可 ・Consul APIで通信許可を⾃由に設定できる ・L7 Traffic Management, Mesh Gateway など機能強化により、⾼度なルーティン グや複数DC間での通信もできるようになった 13
  10. Consul Connect の設定 サービス登録時にサイドカープロキシの設定で通信先とポートの設定を⾏う { "ID": "service1", "Name": "service1", "Address":

    "127.0.0.1", "Port": 8080, "Connect": { "SidecarService":{ "Proxy":{ "upstreams": [{ // service2 に 9000 ポートで接続したい! "destination_name": "service2", "local_bind_port": 9000 }]}}} サイドカープロキシをサービスごとに起動する consul connect proxy -sidecar-for service1 アプリケーションは service2呼び出しを locahost:9000 経由で⾏う @FeignClient(name = "service2", url = "${service2.url}") // 設定ファイル or 環境変数 public interface Service2Client { @GetMapping(value="/hello", produces = "text/plain") String hello(); } 14
  11. Spring Cloud Consul Consul と連携して、以下の機能を提供する ・設定ファイル,アノテーションにより Consulへのサービス登録・削除を⾃動化する ・Consul で管理しているサービスに対して Service

    Discovery とクライアントサイ ドロードバランシングを提供し、ライブラリとしてサービス間通信を⾏う ・Consul Key/Value Storage の内容を Spring Boot のプロパティとして使⽤でき る(Distributed Configuration) ・Spring Cloud Bus のバックエンドとしてConsulを使⽤し、Spring Boot アプリケ ーションの⼀括管理を⾏う(はず) ・動作しなかったので紹介しません 17
  12. (参考)Spring Cloud Consul の代替 同様の機能を提供するライブラリは他にもあるので、使⽤しているミドルウェアに合 わせて選択可能 Service Discovery ・Spring Cloud

    Zookeeper ・Spring Cloud Netflix(Eureka) ・Eurekaは今でもSpring Cloudでサポート中 Distributed Configuration ・Spring Cloud Zookeeper ・Spring Cloud Config 18
  13. (参考)サービスメッシュ とライブラリの⽐較 システムの規模、構成に合わせてどちらを採⽤するかを検討 項⽬ サービスメッシュ ライブラリ 主な製品 Istio, Consul Connect,

    Dapr Spring Cloud Consul/Eureka 実現⽅法 Sidecar Proxyによる通信仲介 プロセス中に組み込み メリット サービスと疎結合 他⾔語に対応できる プロキシに接続すれば通信可能 導⼊が容易 サービス間直接通信 デメリット サービスメッシュ基盤が必要 分散トレースの伝播不可 ホップ数が増える ⾔語・フレームワークが固定 ライブラリのAPIを使う必要がある サービスごとに設定や導⼊が必要 20
  14. Spring Cloud Consul を始める Spring Cloud Consulの依存性を追加する ext { set('springCloudVersion',

    "Hoxton.SR1") } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } } dependencies { // 全ての機能を使⽤する場合 implementation 'org.springframework.cloud:spring-cloud-starter-consul-all' // 機能を個別に選択する場合 implementation 'org.springframework.cloud:spring-cloud-starter-consul-config' implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery' //implementation 'org.springframework.cloud:spring-cloud-starter-consul-bus' } 21
  15. Spring Cloud Consul を設定する bootstrap.ymlと spring.application.name が必須 spring: application: name:

    springcloudservice1 # 以下はデフォルト設定なので省略可能 cloud: consul: host: localhost port: 8500 依存性と上記設定だけで以下の処理が⾃動的に⾏われる。 ・Spring Boot 起動時に spring.application.name の値でConsulにサービス登録 ・Spring Boot Actuatorの healthエンドポイントに対してヘルスチェック設定 ・Spring Boot 終了時に Consulからサービス削除 ・bootstrap.ymlの設定でカスタマイズ可能 22
  16. Service Discovery - Discovery Client サービス名を与えるとアドレス⼀覧を取得する DiscoveryClient が使⽤可能。 Consulからアドレスを取得していて、Consul Watch

    により最新の状態に同期され る。 @Autowired DiscoveryClient discovery; public void getService() { // springcloudservice2 サービスのアドレス⼀覧を取得 discovery.getInstances("springcloudservice2") .forEach(srv -> System.out.println(srv.getHost() +":" + srv.getPort())); } 23
  17. Spring Cloud LoadBalancer(1) DiscoveryClient を使⽤してクライアントサイドロードバランシングを⾏う、 Spring Cloud LoadBalancerも使⽤できる。 RestTemplate, WebClient,

    OpenFeignなどに組み込み、URLにサービス名を与える ことで当該サービスのアドレス⼀覧に対してラウンドロビンで通信を⾏う OpenFeign など 宣⾔型HTTPクライアントの場合は、 @LoadBalancerClient を使 い、URL設定にサービス名を付与 @LoadBalancerClient // DiscoveryClient を組み込むアノテーション @FeignClient("springcloudservice2") // URL の代わりにサービス名 public interface Service2Client { @GetMapping(value = "/hello", produces = "text/plain") String hello2(); } 24
  18. Spring Cloud LoadBalancer(2) RestTemplate/WebClient の場合は @Bean と⼀緒に @LoadBlanced を付与し、 HTTPアクセス時にホスト名にサービス名を設定する

    @LoadBalanced @Bean public WebClient.Builder loadBalancedWebClientBuilder() { return WebClient.builder(); } @Autowired WebClient.Builder builder; public void fetch() { // ホスト名にサービス名を与えると、DiscoveryClient からアドレス解決する builder.build().get() .uri("http://springcloudservice2/hello2").exchange(); } さらに、 @LoadBalancerClient を使⽤してWebClinetインスタンスを事前に構築す る⽅法もある(https://spring.io/guides/gs/spring-cloud-loadbalancer/) 25
  19. Distributed Configuration Consul の Key/Value Storage を Spring Boot のプロパティとして使う機能

    config/< サービス名>/< プロパティ> に値を設定すると、起動時にConsulから取得する # springcloudservice2 サービスの greeting.service2 にB-1 を設定 consul kv put config/springcloudservice2/greeting/service2 B-1 @Value や ConfigurationPropertiesから参照可能 @RestController public class Hello2Controller { // B-2 がインジェクション @Value("${greeting.service2}") String greeting; @GetMapping(value = "/hello", produces = "text/plain") public String greeting() { return greeting; } } 26
  20. Key/Value Storageのフォーマット bootstrap.yaml の以下のformat設定で、値に設定するフォーマットを変更できる spring.cloud.consul.config.format: YAML|PROPERTIES|FILES|KEY_VALUE(default) YAML, PROPERTIES config/< サービス名><,PROFILE>/data

    キーに、yaml またはproperties 形式で複数 の値をまとめて設定できる FILES config/< サービス名><-PROFILE>.yml(.properties) のキーで設定ファイルの内容その ものを値に設定できる。 Key/Value Storageに設定する内容をgitで管理し、デプロイ時に反映する場合などに 便利 28
  21. リフレッシュスコープ Consulから取得したプロパティは、 @RefreshScope を付与したBeanについて、 Key/Value Storage の値を更新するとBeanのリフレッシュ(DIのやり直し)する ・⾃動的にリフレッシュするか、明⽰的に actuator/refresh を実⾏するか、無効に

    するか設定で選択できる ・ConfigurationProperies は暗黙的に RefreshScope に含まれる @RestController @RefreshScope public class Hello2Controller { // @RefreshScope により、KVS の変更時にリフレッシュされる @Value("${greeting.service2}") String greeting; @GetMapping(value = "/hello", produces = "text/plain") public String greeting() { return greeting; } } 29
  22. Spring Cloud Gateway + Service Discovery Spring Cloud Gateway の

    DiscoveryClient 連携を使⽤すると、 Spring Cloud Gateway から < サービス名>/< 各サービスのエンドポイント> で、各サービ スに接続できる。 API Gatewayとして各サービスの接続の統合や認証の⼀元化などに期待できる spring: application: name: sprnigcloudgateway cloud: gateway: discovery: # use consul service discovery locator: enabled: true 30
  23. Demo2 - Spring Cloud Consul ・ServiceDiscovery によるサービス間接続 ・Key/Value Storage によるプロパティ設定とリフレッシュ

    ・Spring Cloud Gateway 連携 ・https://github.com/kencharos/consul-spring- tutorial/tree/master/springcloudservice1 31
  24. (おまけ) Consul を本番で使うためには ・エージェント間通信やAPIを暗号化するためにTLS必須 ・Consulが使⽤するポートは結構多いのでFirewallの設定に抜けがないように ・デフォルトでは全ての操作は認証無しで利⽤可能 ・ACL(ポリシーとトークン)を有効にして、使⽤可能なAPIを最⼩限にする ・パスワードなどの機密情報を Key/Value Storage

    に置かない ・機密情報管理のためのソフトウェア Hashicorp Valut などを検討する ・機密情報を安全に配布する他、 Consul ACL を AWS IAM などの他の認証機 構と連携するなど、より⾼度なポリシー制御ができる ・Spring Cloud Valut という Valut 連携ライブラリもある 33