最近 Consul を検証する機会があり,まず全体概要を把握するために「HashiConf 2018」で発表された「HashiCorp Learn Platform」を活用することにした.「HashiCorp Learn Platform」は HashiCorp が提供する学習コンテンツで,現在は Vault / Consul / Terraform / Nomad をサポートしている.Getting Started と Advanced Tracks があり,習熟度に合ったコンテンツを選ぶことができる.興味のある HashiCorp プロダクトがあったらすぐに試してみると良いかと!
- HashiCorp Vault
- Getting Started
- Advanced Tracks
- Day 1: Deploying Your First Vault Cluster
- Secrets Management
- Identity and Access Management
- Encryption as a Service
- Security
- Operations
- Developer
- HashiCorp Consul
- Getting Started
- Getting Started with Kubernetes
- Advanced Tracks
- Day 1: Deploying Your First Datacenter
- Day 2: Advanced Operations
- HashiCorp Terraform
- Getting Started
- Advanced Tracks
- Getting Started - Azure
- Terraform Enterprise
- Developer
- Operations
- AWS Provider
- Azure Provider
- HashiCorp Nomad
- Getting Started
HashiCorp Learn 画面
基本的に動画を見ながら受講する.字幕機能はないけど,下部にスクリプトが載っているので困ることはないし,コマンドをコピーするときにも便利だった.英語も非常に聞き取りやすくなっている.
Learn how to deploy a service mesh with HashiCorp Consul : Getting Started
今回は「Learn how to deploy a service mesh with HashiCorp Consul」の「Getting Started」を実施した.全9ステップから構成されている.累計時間も「49 min」と,コンパクトにまとまっている.
- Install Consul (4 min)
- Run the Consul Agent (7 min)
- Registering Services (6 min)
- Connect (7 min)
- Consul Cluster (8 min)
- Registering Health Checks (5 min)
- KV Data (5 min)
- Web UI (4 min)
- Next Steps (3 min)
Install Consul
まず,Consul をインストールする.今回は Mac で動かすため,brew
を使うことにした.
$ brew install consul $ consul version Consul v1.4.2 Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
OS ごとにバイナリも公開されている.
Run the Consul Agent
次に,Consul Agent を「development server mode」で起動する.Mac で動かす場合,kakakakakku.local
のようにコンピュータ名にピリオドが含まれている場合があり,Consul DNS に影響がある.今回は -node
オプションを使って,名前を指定することにした.
$ consul agent -dev -node machine $ consul members Node Address Status Type Build Protocol DC Segment machine 127.0.0.1:8301 alive server 1.4.2 2 dc1 <all>
Consul では,ノード情報を API と DNS から取得できる.以下は API からノード情報を取得している.
$ curl localhost:8500/v1/catalog/nodes [ { "ID": "11111111-2222-3333-4444-555555555555", "Node": "machine", "Address": "127.0.0.1", "Datacenter": "dc1", "TaggedAddresses": { "lan": "127.0.0.1", "wan": "127.0.0.1" }, "Meta": { "consul-network-segment": "" }, "CreateIndex": 9, "ModifyIndex": 10 } ]
そして Consul DNS にノードの IP を問い合わせる.
$ dig @127.0.0.1 -p 8600 machine.node.consul (中略) ;; QUESTION SECTION: ;web.service.consul. IN A ;; ANSWER SECTION: machine.node.consul. 0 IN A 127.0.0.1 ;; ADDITIONAL SECTION: machine.node.consul. 0 IN TXT "consul-network-segment=" (中略)
Registering Services
Consul にサービスを登録する.まず設定ファイルを管理する ./consul.d
ディレクトリを作成し,以下のように web
サービス用の ./consul.d/web.json
を作成した.
{ "service": { "name": "web", "tags": [ "rails" ], "port": 80 } }
Consul Agent を起動するときに -config-dir
オプションを指定するとディレクトリを指定できる.今回は以下のように起動すると,コンソールにサービスを認識したログが出ていた.
$ consul agent -dev -config-dir=./consul.d -node machine (中略) 2019/03/20 00:00:00 [DEBUG] agent: Service "web" in sync (中略)
Consul DNS にサービスを問い合わせることもできる.
$ dig @127.0.0.1 -p 8600 web.service.consul ;; QUESTION SECTION: ;web.service.consul. IN A ;; ANSWER SECTION: web.service.consul. 0 IN A 127.0.0.1 ;; ADDITIONAL SECTION: web.service.consul. 0 IN TXT "consul-network-segment="
Consul DNS は SRV
レコードを問い合わせることもでき,今回は machine.node.dc1.consul
の 80 ポートで web
サービスが動いていることがわかる.
$ dig @127.0.0.1 -p 8600 web.service.consul SRV ;; QUESTION SECTION: ;web.service.consul. IN SRV ;; ANSWER SECTION: web.service.consul. 0 IN SRV 1 1 80 machine.node.dc1.consul. ;; ADDITIONAL SECTION: machine.node.dc1.consul. 0 IN A 127.0.0.1 machine.node.dc1.consul. 0 IN TXT "consul-network-segment="
当然ながら API でサービスを確認することもできる.また /health
エンドポイントと ?passing
パラメータを組み合わせると正常なインスタンスを確認することもできる.
$ curl http://localhost:8500/v1/catalog/service/web $ curl 'http://localhost:8500/v1/health/service/web?passing'
Connect
次に Consul Connect を学ぶ.Consul Connect とはサービス間の通信を担当するための Sidecar Pattern Proxy と表現することができて,詳細は以下の公式ドキュメントに載っている.
まず,Consul Connect を使わずに,socat
コマンドを使った echo サービスを実装する.Mac に socat
をインストールしておく必要がある.nc
で接続すると,正常に echo できる(オウム返し).
$ brew install socat $ socat -v tcp-l:8181,fork exec:"/bin/cat" $ nc 127.0.0.1 8181 hello hello echo echo
以下の JSON を ./consul.d/socat.json
として保存する.
{ "service": { "name": "socat", "port": 8181, "connect": { "sidecar_service": {} } } }
Consul に設定ファイルを反映する.正確に言うと consul reload
を実行すると Consul プロセスに SIGHUP
シグナルを送ることになる.
$ consul reload Configuration reload triggered
次に Consul Connect の設定をし,サービスに接続すると,Proxy を経由して echo できるようになる.
$ consul connect proxy -sidecar-for socat $ consul connect proxy -service web -upstream socat:9191 $ nc 127.0.0.1 9191 Hello Consul via Connect Hello Consul via Connect
実際に使う場合は ./consul.d/web.json
に依存関係を書くことになる.
{ "service": { "name": "web", "port": 8080, "connect": { "sidecar_service": { "proxy": { "upstreams": [{ "destination_name": "socat", "local_bind_port": 9191 }] } } } } }
改めて Proxy を起動すると echo できるようになる.
$ consul reload Configuration reload triggered $ consul connect proxy -sidecar-for web
さらに,Consul Connect には Intentions と言う「サービス認可」の仕組みもある.以下のように web
→ socat
を deny すると echo できなくなり,設定を削除すると echo できなくなる.
$ consul intention create -deny web socat Created: web => socat (deny) $ nc 127.0.0.1 9191 $ consul intention delete web socat Intention deleted. $ nc 127.0.0.1 9191 Hello Consul via Connect Hello Consul via Connect
Intentions の詳細は公式ドキュメントに載っている.サービスメッシュを実装するときにより詳しく理解しておく必要がある.
Consul Cluster
次に Vagrant を使って仮想環境を2台構築し,Consul Cluster を試す.以下にある Consul デモ用の Vagrantfile
を起動すると n1
と n2
を起動できる.
今回は n1
を Consul Agent Server として,n2
を Consul Agent Client として使う.
[n1] $ consul agent -server -bootstrap-expect=1 \ -data-dir=/tmp/consul -node=agent-one -bind=172.20.20.10 \ -enable-script-checks=true -config-dir=/etc/consul.d [n2] $ consul agent -data-dir=/tmp/consul -node=agent-two \ -bind=172.20.20.11 -enable-script-checks=true -config-dir=/etc/consul.d
n1
で n2
を Consul Cluster に join させると,ノード情報を共有できるようになる.
[n1] $ consul members Node Address Status Type Build Protocol DC Segment agent-one 172.20.20.10:8301 alive server 1.4.3 2 dc1 <all> [n1] $ consul join 172.20.20.11 Successfully joined cluster by contacting 1 nodes. [n1] $ consul members Node Address Status Type Build Protocol DC Segment agent-one 172.20.20.10:8301 alive server 1.4.3 2 dc1 <all> agent-two 172.20.20.11:8301 alive client 1.4.3 2 dc1 <default> [n2] $ consul members Node Address Status Type Build Protocol DC Segment agent-one 172.20.20.10:8301 alive server 1.4.3 2 dc1 <all> agent-two 172.20.20.11:8301 alive client 1.4.3 2 dc1 <default>
そして Consul DNS を使ってノード情報を問い合わせることもできる.
[n1] $ dig @127.0.0.1 -p 8600 agent-two.node.consul ;; QUESTION SECTION: ;agent-two.node.consul. IN A ;; ANSWER SECTION: agent-two.node.consul. 0 IN A 172.20.20.11 ;; ADDITIONAL SECTION: agent-two.node.consul. 0 IN TXT "consul-network-segment="
なお,クラウド環境で Auto Scaling をする場合,自動的に Consul Cluster に join させる必要がある.Amazon EC2 なら tag を指定し,自動化できる.詳細は公式ドキュメントに載っている.
Registering Health Checks
引き続き Consul Cluster 環境を使って,ヘルスチェックを設定する.まず,n2
に2個の設定をする.1個目は google.com
に ping をする /etc/consul.d/ping.json
となる.
{ "check": { "name": "ping", "args": [ "ping", "-c1", "google.com" ], "interval": "30s" } }
2個目は localhost
に curl をする /etc/consul.d/web.json
となる.意図的にヘルスチェックは失敗するようになっている.そして設定後は consul reload
を実行する.
{ "service": { "name": "web", "tags": [ "rails" ], "port": 80, "check": { "args": [ "curl", "localhost" ], "interval": "10s" } } }
以下のエンドポイントを叩くと,異常を確認できる.
[n1] $ curl http://localhost:8500/v1/health/state/critical
異常と判定されているため,Consul DNS に問い合わせをしても,何も返ってこなくなる.
[n1] dig @127.0.0.1 -p 8600 web.service.consul (中略) ;; QUESTION SECTION: ;ping.service.consul. IN A (中略)
KV Data
次に Consul KVS を試す.サンプルとして Redis Configuration などを設定する.-recurse
オプションは覚えておくと良さそう.
$ consul kv get redis/config/minconns Error! No key exists at: redis/config/minconns $ consul kv put redis/config/minconns 1 Success! Data written to: redis/config/minconns $ consul kv put redis/config/maxconns 25 Success! Data written to: redis/config/maxconns $ consul kv put -flags=42 redis/config/users/admin abcd1234 Success! Data written to: redis/config/users/admin $ consul kv get redis/config/minconns 1 $ consul kv get -detailed redis/config/minconns CreateIndex 19 Flags 0 Key redis/config/minconns LockIndex 0 ModifyIndex 19 Session - Value 1 $ consul kv get -recurse redis/config/maxconns:25 redis/config/minconns:1 redis/config/users/admin:abcd1234 $ consul kv delete redis/config/minconns Success! Deleted key: redis/config/minconns $ consul kv delete -recurse redis Success! Deleted keys with prefix: redis
また Consul KVS は「Check-And-Set operation」をサポートしている.最新更新を表現する ModifyIndex
を指定することにより,アトミックに更新できるようになる.
$ consul kv put foo bar Success! Data written to: foo $ consul kv get foo bar $ consul kv put foo zip Success! Data written to: foo $ consul kv get foo zip $ consul kv get -detailed foo CreateIndex 39 Flags 0 Key foo LockIndex 0 ModifyIndex 41 Session - Value zip $ consul kv put -cas -modify-index=123 foo bar Error! Did not write to foo: CAS failed $ consul kv put -cas -modify-index=41 foo bar Success! Data written to: foo $ consul kv put -cas -modify-index=41 foo bar Error! Did not write to foo: CAS failed $ consul kv get -detailed foo CreateIndex 39 Flags 0 Key foo LockIndex 0 ModifyIndex 46 Session - Value bar
KV Store Endpoints の詳細は公式ドキュメントに載っている.
また Consul KVS の値は Consul Web UI から確認することもできる.
Web UI
特に内容はなく,Consul Web UI を確認する.-ui
オプションを追加すると,http://localhost:8500/ui
にアクセスできるようになる.
$ consul agent -dev -ui -node machine
Next Steps
次は「Advanced Tracks」に進んだり,ドキュメントを読もう!という内容になっている.他コースもどんどん学んでいく.
まとめ
- HashiCorp プロダクトを学ぶなら「HashiCorp Learn Platform」を活用する
- 現在 Vault / Consul / Terraform / Nomad をサポートしている
- 今回は「Learn how to deploy a service mesh with HashiCorp Consul」の「Getting Started」を実施した
- Consul の基本機能を網羅的に学ぶことができた
- 興味のある HashiCorp プロダクトがあったらすぐに試してみると良いかと!