Consulハンズオン 操作手順

本記事は、July Tech Festa 2015で実施するConsulハンズオンの操作手順書です。
(2015/07/27追記: 設定内容に一部誤りがあったため修正しました)

Consulハンズオン概要
--------------

### ハンズオンの範囲

今回のハンズオンでは以下の機能について紹介します

- 前半: 基本操作編
  - インストール、起動
  - 複数Nodeでのクラスタ形成
  - Serviceの管理とヘルスチェック
  - KVS(Key Value Store)機能
  - DNS機能
- 後半: 応用編
  - Consul Watch
  - Consul Event
  - Consul exec

### 前提環境

今回は一人一台ずつ仮想マシンを用意しました。

- OS: CentOS 7.1 (minimal)
  - 別途 wget, unzip, bind-utils, epel-release, jq をyumで導入済みです


Consulハンズオン: 基本操作編
----------------------------

### インストール

Consulのインストールは非常に簡単です。
バイナリファイルを一つダウンロードして解凍すれば完了です。

今回は合わせてデータを置くディレクトリや設定ファイルを置くディレクトリも作成しておきます。

```
$ wget https://dl.bintray.com/mitchellh/consul/0.5.2_linux_amd64.zip
$ sudo unzip 0.5.2_linux_amd64.zip -d /usr/local/bin
$ sudo mkdir /opt/consul
$ sudo chown $(whoami) /opt/consul
$ sudo mkdir /etc/consul.d
```

### 起動

consul agentコマンドを実行することでサービスが起動します。
起動時に指定するオプションは色々とありますが、まずは1台だけのクラスタを作ってみましょう。

```
$ consul agent -server -bootstrap-expect 1 -data-dir /opt/consul/data >> /tmp/consul.log &
```

起動したら、Consulに対してクラスタ内にいるメンバーを問い合わせてみましょう。

```
$ consul members
```

### 他のNodeへのJoin

次はもっと大きなクラスタを作ってみましょう。
今稼動しているConsulを一度停止し、ハンズオン参加者全員で一つのクラスタを形成します。
今回は、講師側で用意したLeader Nodeに、皆さんがClientとして参加してもらいます。

以前のクラスタのデータが残っている場合、新しいクラスタに参加すると様々なエラーが出るため注意が必要です
先ほど作成した1台だけのクラスタの時のデータは先に消しておきましょう。

```
$ consul leave             # (現在のクラスタから離脱)
$ rm -rf /opt/consul/data  # (異なるクラスタに参加する前に以前のクラスタのデータを削除) 
$ consul agent -data-dir /opt/consul/data -join leader.jtf.cloudconductor.jp >> /tmp/consul.log &
```

起動したらあらためて、Consulに対してクラスタ内にいるメンバーを問い合わせてみましょう。

```
$ consul members
```

### Configファイルの利用

起動時のオプションが増えると、都度指定するのは面倒です。
もちろんConsulもConfigファイルから設定を読み込んで起動することができます。

```
$ consul leave
$ sudo vi /etc/consul.d/client.json
{
  "data_dir": "/opt/consul/data",
  "start_join": ["leader.jtf.cloudconductor.jp"]
}
$ consul agent -config-dir /etc/consul.d >> /tmp/consul.log &
```

### Web-UIの利用

ConsulにはWeb-UIも用意されています。
Web-UIに必要なファイルは同梱されていないので、利用する場合は別途ダウンロードが必要です。
Web-UIを外部に公開するノードにだけ導入されていればクラスタ内の全ノードの情報が確認できます。

それではWeb-UIを有効にしてみましょう。

```
$ wget https://dl.bintray.com/mitchellh/consul/0.5.2_web_ui.zip
$ unzip 0.5.2_web_ui.zip -d /opt/consul
$ sudo vi /etc/consul.d/web_ui.json
{
  "ui_dir": "/opt/consul/dist",
  "addresses": { "http": "0.0.0.0" }
}
$ consul leave
$ consul agent -config-dir /etc/consul.d >> /tmp/consul.log &
```

標準設定の場合、http://(ホスト名):8500/ui/ でWeb-UIにアクセスすることができます。
(HTTP APIと同じポートで利用できます)

### Serviceの管理とヘルスチェック

ConsulではNodeだけでなく、各Node上で稼動するServiceについても管理することができます。
Configファイルにサービスの情報とヘルスチェックの条件を記載することで、起動時にサービスの登録が行えます。
もしくはHTTP API経由で動的に登録することもできます。

```
$ cat <<EOF | sudo tee /etc/consul.d/services.json > /dev/null
{
  "services": [{
      "id": "sshd-$(hostname)",
      "name": "sshd",
      "tags" : [],
      "checks": [{
        "script": "pgrep sshd",
        "interval": "10s"
      }]
  }]
}
EOF
$ consul reload
```

登録されたServiceの状態は、Web-UIから確認することができます。

- http://(ホスト名):8500/ui/

もしくはHTTP API経由でも確認できます。

```
$ curl -s http://localhost:8500/v1/catalog/services | jq .
$ curl -s http://localhost:8500/v1/catalog/service/sshd | jq .
```

### KVS (Key Value Store)

Consulは、KVSの機能も提供しています。
KVSとは、Keyとそれに対応するValueを管理するシンプルなデータストアです。
RDBのようなテーブル構造やRelationは持たず、一般的にスケールアウトが容易です。

Consulが提供するKVSでは、データの原本をLeaderが持ち、クラスタ内の各Serverにそのデータが同期されています。
Leader Nodeに障害が発生しても、過半数のServer Nodeが残っていれば自動的に新たなLeaderをServerから選出するため、ユーザが意識することなく冗長化が可能です。

KVSの利用には特別な設定は必要ありません。
Web-UI、またはHTTP API経由で操作できます。

- http://(ホスト名):8500/ui/

```
$ curl -X PUT http://localhost:8500/v1/kv/$(hostname)/test -d "test_data"
$ curl -s http://localhost:8500/v1/kv/$(hostname)/test | jq .[].Value | tr -d '"' | base64 -d
```

### DNS

Consulは、DNSの機能も提供しています。
クラスタ内の特定Nodeを、<node_name>.node.dc1.consul といった名前で名前解決できます。
またそれだけではなく、特定Serviceを提供するNode群のIPアドレスも、<service_name>.service.dc1.consulといった名前で取得できます。
基本的には.consulの名前解決を行うための内部DNSとして動作しますが、設定によって外部への再帰問い合わせも行わせることが可能です。

標準設定の状態で、TCP 8600でDNSサービスが稼動するようになっています。
外部への再帰問い合わせが必要な場合は以下の設定を追加します。

```
$ sudo vi /etc/consul.d/dns.json
{
  "recursors": ["8.8.8.8", "8.8.4.4"] 
}
$ consul leave
$ consul agent -config-dir /etc/consul.d >> /tmp/consul.log &
```

それでは実際に問い合わせを行ってみましょう。

```
$ dig @127.0.0.1 -p 8600 $(hostname).node.dc1.consul
$ dig @127.0.0.1 -p 8600 sshd.service.dc1.consul
```

Consulハンズオン: 応用編
------------------------

### Consul Watchを用いた自律的な運用

Consul Watchは、クラスタ内のNode, Service, KVSなどの状態が変化したことを検出し、その時に自動的に何らかの処理を行わせることができる機能です。
これをうまく活用すれば、新たなNodeがクラスタに参加した際に、自動的に監視サーバへの登録処理を行うといった自律的な運用が可能になります。

今回はシンプルな例として、sshdのServiceが稼動しているNodeの情報を/etc/hostsに同期してみましょう。
sshdが稼動しているNodeが増減すると、自動的に/etc/hostsが更新されるようにします。
(ConsulのDNS機能を使えば/etc/hostsを使う必要は無いですが、例として。)

```
$ sudo vi /etc/consul.d/watch_nodes.json
{
  "watches": [{
      "type": "service",
      "service": "sshd",
      "handler": "/bin/bash -e /opt/consul/update_hosts.sh"
  }]
}
$ sudo chmod a+w /etc/hosts
$ sudo cp -a /etc/hosts /etc/hosts.org
$ sudo vi /opt/consul/update_hosts.sh
#!/bin/sh
cp /etc/hosts.org /etc/hosts 
curl -s localhost:8500/v1/catalog/service/sshd | jq .[] | jq '.Address + "  " + .Node' | tr -d '"' >> /etc/hosts
$ consul reload
```

### Consul Eventを用いたイベントの発行

Consul Watchはクラスタ内の状態の変化を検出して、自動的に何らかの処理を行う機能でした。
しかし運用作業の中には環境の変化に合わせて自動で実行するものだけでなく、ユーザが任意のタイミングで行うものもあります。
Consul EventをConsul Watchと組み合わせて使うと、ユーザが特定のイベントを発行した際に、そのイベントに紐つけた処理を自動で実行することが可能になります。

今回は例として、restartイベント受信時にcrondをrestartするwatchを登録してみましょう。
(対象がcrondなのは、もし失敗しても特に影響が出ないサービスだったからというだけです)

```
$ sudo vi /etc/consul.d/watch_restart.json
{
  "watches": [{
      "type": "event",
      "name": "restart",
      "handler": "sudo systemctl restart crond"
  }]
}
$ consul reload
```

restartイベントに対するWatchが登録できたら、今度は実際にイベントを発行してみましょう。
注意点として、特に条件をつけずにeventを発行した場合、全てのNodeで対応するwatchのhandlerが実行されます。
オプションを指定することで、eventに対応するhandlerを実行するNodeを限定することができます。
オプションには、-node, -service, -tagがあります。

```
$ consul event -name restart -node $(hostname)
```

cronのログを確認すると、再起動したことによるログが数行追加されていると思います。

```
$ less /var/log/cron
```

### Consul execによる任意のコマンド実行

管理対象のNodeが増えると、一つ一つのNodeにSSH接続して管理を行うのは大変です。
consul execを使うと、クラスタ内のNodeに対して任意のコマンドを実行し、その出力を得ることができます。

例えば以下のコマンドを実行すると、各Nodeに導入されているopensslのバージョンが確認できます。

```
$ consul exec openssl version
```

また更新が必要な場合も、全ノードに一度に行えます。

```
$ consul exec sudo yum -y update openssl
```

一方で、任意のコマンドを遠隔から実行できるのはセキュリティ上問題になる場合もあります。
その場合はConfigで、consul execの実行を無効にすることもできます。

```
$ sudo vi /etc/consul.d/disable_exec.json
{
  "disable_remote_exec": true
}
```

また、Consulが持つACLの機能で許可されたTokenを持つ場合のみ実行を許可することもできます。
(今回のハンズオンではACLの詳細については省略します)


以上でハンズオンを終わります。