kakakakakku blog

Weekly Tech Blog: Keep on Learning!

HashiCorp 学習コンテンツ「HashiCorp Learn Platform」を活用して Consul を学ぶ

最近 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

learn.hashicorp.com

HashiCorp Learn 画面

基本的に動画を見ながら受講する.字幕機能はないけど,下部にスクリプトが載っているので困ることはないし,コマンドをコピーするときにも便利だった.英語も非常に聞き取りやすくなっている.

f:id:kakku22:20190322091804p:plain

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)

learn.hashicorp.com

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 ごとにバイナリも公開されている.

www.consul.io

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>

www.consul.io

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 と表現することができて,詳細は以下の公式ドキュメントに載っている.

www.consul.io

まず,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 と言う「サービス認可」の仕組みもある.以下のように websocat を 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 の詳細は公式ドキュメントに載っている.サービスメッシュを実装するときにより詳しく理解しておく必要がある.

www.consul.io

Consul Cluster

次に Vagrant を使って仮想環境を2台構築し,Consul Cluster を試す.以下にある Consul デモ用の Vagrantfile を起動すると n1n2 を起動できる.

今回は 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

n1n2 を 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 を指定し,自動化できる.詳細は公式ドキュメントに載っている.

www.consul.io

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 の詳細は公式ドキュメントに載っている.

www.consul.io

また Consul KVS の値は Consul Web UI から確認することもできる.

f:id:kakku22:20190322104653p:plain

Web UI

特に内容はなく,Consul Web UI を確認する.-ui オプションを追加すると,http://localhost:8500/ui にアクセスできるようになる.

$ consul agent -dev -ui -node machine

f:id:kakku22:20190322105757p:plain

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 プロダクトがあったらすぐに試してみると良いかと!