背景/概要
Consulを使う機会が出てきたのでメモ。「Prometheusから利用できそうだね」くらいを理解のゴールとして設ける。
この記事でやれることはconsulの入門とdnsでサーバのIPを引けるようになるまで。dnsは別で立ててますが閉じた検証にしたいのでとりあえずdnsmasqを入れて代用してます。
Consulとは
インフラ上のサービス設定とサービスディスカバリのためのツール。Consul自体は複数のコンポーネントがあるが全体としてサービスディスカバリのツールって認識で良さそう。
HashiCorpが公開していて実装言語はGolangとなっている。主な機能としては以下
- サービス・ディスカバリとオーケストレーション
- ヘルスチェック
- キーバリュー・ストア
- 耐障害性
ざっくりアーキテクチャは以下のような感じ。
(Hashicorp が提供しているデータセンタ管理ツール群 ATLAS の一部で、クラスタリングと分散KVS、オーケストレーションの基礎となる機能をいくつか提供してくれるとあるがメイン機能がどれなのかとても迷いそうなアーキテクチャ図だなと感じた。。)
公式のはこっち
サービス・ディスカバリってなんだっけ
サービス・ディスカバリ(Service Discovery)とは、日本語では「サービスの発見」や「検出」という意味あいで使われる。サービスディスカバリの機能はConsulを通してどのサーバでどのようなサービスが動作しているかやIPやポートをリアルタイムで知ることができる機能
Consulノードはサービス状況に変化が発生すると、「Consulサーバ」に対してデータを送信します。consulサーバは受け取ったデータとkvsに保存し情報を知りたい側のクライアントがhttpやcliを使ってサーバの検出を行います。
Consul が使うポート
機能 | TCP/UDP | ポート | 説明 |
---|---|---|---|
Server | RPC | TCP | 8300|Server が他の Agent からRPCのリクエストを受け付ける |
Serf LAN | TCP & UDP | 8301 | LAN用のゴシッププロトコル。全 Agent 同士が使う |
Serf WAN | TCP & UDP | 8302 | WAN用のゴシッププロトコル。Server 同士が使う |
CLI RPC | TCP | 8400 | consulコマンド実行時にローカルの Agent との通信に使われる |
HTTP API | TCP | 8500 | Client が HTTP リクエストを受け付ける |
DNS | TCP & UDP | 8600 | Agent が DNSクエリを受け付ける |
障害検知
Consul node がヘルスチェックを実施する、検出済みのサービスに対する障害発生を検出する。監視間隔や対象は、ノードが主体的に対象ホスト内部から監視
HTTP または DNS インターフェース、Web UI で確認できるといった仕組み。
ざっくり触る
スタンドアロン構成で動かしてみます。
install
公式に方法があるのでそのままやってみます。
$ sudo yum install -y yum-utils $ sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo $ sudo yum -y install consul [root@master ~]# consul version Consul v1.10.1 Revision db839f18b Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
usage
多機能が売りというだけあってhelpだけでも盛りだくさん機能が伺えます。とりあえずagentぐらいが見れれば良さそう。
[root@master etc]# consul --help Usage: consul [--version] [--help] <command> [<args>] Available commands are: acl Interact with Consul's ACLs agent Runs a Consul agent catalog Interact with the catalog config Interact with Consul's Centralized Configurations connect Interact with Consul Connect debug Records a debugging archive for operators event Fire a new event exec Executes a command on Consul nodes force-leave Forces a member of the cluster to enter the "left" state info Provides debugging information for operators. intention Interact with Connect service intentions join Tell Consul agent to join cluster keygen Generates a new encryption key keyring Manages gossip layer encryption keys kv Interact with the key-value store leave Gracefully leaves the Consul cluster and shuts down lock Execute a command holding a lock login Login to Consul using an auth method logout Destroy a Consul token created with login maint Controls node or service maintenance mode members Lists the members of a Consul cluster monitor Stream logs from a Consul agent operator Provides cluster-level tools for Consul operators reload Triggers the agent to reload configuration files rtt Estimates network round trip time between nodes services Interact with services snapshot Saves, restores and inspects snapshots of Consul server state tls Builtin helpers for creating CAs and certificates validate Validate config files/directories version Prints the Consul version watch Watch for changes in Consul
起動
bindとclientあたりはよしなに。(consul は基本ローカルアドレスからのアクセスしか受け付けませんのでその辺は注意)
$ consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul --bind 192.168.1.15 --client=0.0.0.0
これで準備は完了。consulコマンドでmembersやらを打つことで自信が参加していることを確認可能となります。サーバ側の準備ができたので次はクライアントをここへ参加させます。
$ consul agent -data-dir /tmp/consul -bind <IPアドレス> -join <ConsulサーバのIPアドレス>
正常に通信ができると、自動的にクラスタが構成されます。「consul members」コマンドを実行すると、次のように複数のホスト情報が確認できます。
[root@master ~]# consul members Node Address Status Type Build Protocol DC Segment master 192.168.1.15:8301 alive server 1.10.1 2 dc1 <all> slave 192.168.1.207:8301 alive client 1.10.1 2 dc1 <default>
httpでjsonを取ることとかもできる。APIとかアプリケーションからsdしたいケースだとこっちになるんでしょうか。
curl -s http://192.168.39.5:8500/v1/kv/hello/?recurse | jq '.' [ { "Value": "b3BlbiB0aGUgbmV4dA==", "Flags": 0, "Key": "hello/key2", "ModifyIndex": 16, "CreateIndex": 16 }, { "Value": "aGVsbG8sIHdvcmxkIQ==", "Flags": 0, "Key": "hello/key", "ModifyIndex": 14, "CreateIndex": 14 } ]
dnsで引けるようにする
consulにはDNSクエリを受け付ける機能もあるので以下のようにメンバーを引くことができる。ただポート指定したりDNSサーバを指定したりと面倒なのでdnsmasqを導入することでそのような手間を解決することもできる。
$ dig @localhost -p 8600 master.node.consul
dnsmasqをセットアップする。resolve.confも自サーバを向くように修正しておく
$ yum -y install dnsmasq $ echo "server=/consul/127.0.0.1#8600" >> /etc/dnsmasq.conf $ echo "strict-order" >> /etc/dnsmasq.conf
このように設定しておけばdnsの指定をしなくてもdigで自宅内のサーバのIPを引けるようになる。
;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;slave.node.consul. IN A ;; ANSWER SECTION: slave.node.consul. 0 IN A 192.168.1.207 ;; ADDITIONAL SECTION: slave.node.consul. 0 IN TXT "consul-network-segment=" ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: 土 7月 17 09:04:12 EDT 2021 ;; MSG SIZE rcvd: 98
サービスを使ってみる
サービスを使うことでサーバをグルーピングして死活監視などを行うことができます。prometheusとかで監視する際にはこの設定は必須になりそうなやつですね。以下のように監視対象のサーバにファイルを作成します。概要としてはchecksで書いた内容を監視しつつserviceに名前を登録するという感じです。適当に80でhttp通信を可能な状態にしておきます。
{ "service": { "name": "web", "tags": [ "rails" ], "port": 80, "check": { "args": [ "curl", "localhost" ], "interval": "10s" } } }
上記を設定した上で以下のようにconsulを起動します。"-config-dir", "-enable-script-checks"がポイントです。
consul agent -data-dir /tmp/consul -bind 192.168.1.207 -join 192.168.1.15 -config-dir /etc/consul.d -enable-script-checks=true
こんな感じで起動することでhttp:80の通信が可能なサーバは以下のようにdnsの名前引きで引くことが可能となります。このレコードを使うことで例えばLBのバックエンドを動的に決めたりすることが可能だったりprometheusとしてはwebというサービスでグルーピングして監視が可能になったりします。とても便利!
;; ANSWER SECTION: web.service.consul. 0 IN A 192.168.1.15 web.service.consul. 0 IN A 192.168.1.207
KVS機能
kvs機能もconsulは持っている。これのユースケースとしてはconsulサーバにkvを登録しておけばconsulクライアント側がこの値をみにいく。ここの値に例えばミドルウェアとかで有効な値を設定しておくことでユーザが設定値をpostするとミドルウェアが動いているサーバがその値を元にサービスを再起動したりみたいなことが可能となる。
# post $ curl -X PUT http://localhost:8500/v1/kv/$(hostname)/test -d "test_data" true # get(base64でエンコードされているのでデータをみるには以下の作業が必要) $ curl -s http://localhost:8500/v1/kv/$(hostname)/test | jq .[].Value | tr -d '"' | base64 -d test_data
メンテナンスを試す
バックエンドのサービスのうち1台だけをメンテモードにしてLBから切り離すみたいなことも可能。(LBを経由しないラウンドロビンをクライアントで実装してるみたいな場合はきちんとレコード以外を見るみたいなことを自分で実装する必要があるっぽいのでそこは注意。memd-perlとかそのあたりは怪しい。)
[root@master tmp]# consul maint [root@master tmp]# dig web.service.consul ;; ANSWER SECTION: web.service.consul. 0 IN A 192.168.1.207 web.service.consul. 0 IN A 192.168.1.15 # この状態でmasterサーバをメンテモードに入れてみると以下のようにレコードから削除される [root@master tmp]# consul maint -enable Node maintenance is now enabled [root@master tmp]# dig web.service.consul web.service.consul. 0 IN A 192.168.1.207
感想/これから
とりあえずしばらくはお家のサーバには全て適用してみようかなと思います。DNSの登録とかが自動でされるのはとても便利ですね〜。sd機能があるのでprometheusからも簡単に監視が導入できそうなのでそれにいずれ挑戦しようと思います。
おまけ
consul-tempateとconsul-alertsという関連サービスもあったりする。
ざっくりcousul-templateにも触れてみる
ハンズオン
# 監視対象テンプレートファイルを作成する $ cat nginx.ctmpl {{ key "master/test" }} # データをconsulへ投入する $ curl -X PUT http://localhost:8500/v1/kv/test -d "test_data3" # この状態でconsul-templateを起動する。 # -templateは"templateファイル":コピー先のパス: "コピー後に実行したいコマンド" $ ./consul-template -consul-addr localhost:8500 -template "./nginx.ctmpl:/etc/test.conf:pwd"
この状態でkeyを更新したりすると自動的にファイルが更新され指定したコマンドが実行される。pwdにしてるが運用ケースとかだとgraceful restartとかになるんだと思う。こりゃ便利。