2017-01-14
WildFly Swarm+Consul(+Dnsmasq)でService Discovery
WildFly Swarmには、Service Discoveryのための仕組みとしてTopologyがありますが、その実装手段としていくつかの
方法を提供しています。
Topology
今回は、Consulを試してみようかなと思います。
Topology using Hashicorp Consul
Consul?
Consulというのは、HashiCoprの提供するService Discoveryの仕組みです。
Consul
Introduction To Consul
主に以下のような機能を持ちます。
- Service Discovery
- Health Check
- KVS
Consul自体はAgentとして各サーバーで動作させるものですが、動作タイプにServerとClientがあり、通常は
Serverは(データセンターあたり)3台または5台での構成を推奨しています。
Bootstrapping a Datacenter
ConsulにはDNSの機能もあり、名前解決を行うことができます。
DNS Interface
とはいえ、ConsulのDNSは8600ポートで提供されるので、他のDNS製品と合わせて通常の名前解決の仕組みに乗せる例がこちらに記載されています。
DNS Forwarding
今回は、このドキュメントに習いDnsmasqを使ってみたいと思います。
Dnsmasq - network services for small networks.
WildFly Swarm+Consul
続いて、WildFly SwarmとConsulの統合機能について。
Topology using Hashicorp Consul
Consulは、NodeまたはServiceで名前解決を行うことができます。
DNS Interface
WildFly SwarmのConsul向けの統合機能を使うと、WildFly Swarmの起動時にConsul Agentに対してServiceとして
自分自身を登録してくれるようになります。
お題
で、今回はWildFly SwarmとConsulを使って、こんなお題で試してみようと思います。
- Consul Agent(Server)3台でServer構成
- Consul Agent(Client)2台に、WildFly Swarmで作ったサンプルJAX-RSアプリケーションを載せてService構成
- Consul Agent(Client)にDnsmasqをインストールし、curlでService名を解決してアクセス
つまり、こんな(クラスタ)構成です。
ConsulとWildFly Swarmについては、以下の条件で。
- Consul Agent(Server) … 172.17.0.2 〜172.17.0.4(ホスト名:consulserver1 〜 consulserver3)
- Consul Agent(Client - WildFly Swarm) … 172.17.0.5 〜 172.17.0.6(ホスト名:consulswarmclient1 〜 consulswarmclient2)
- Consul Agent(Client - curl) … 172.17.0.1(ホスト名:consulcurlclient)
Consulのインストール
全Serverで行うので、共通的に1度紹介。
Consulのダウンロードページから、Consulをダウンロードします。
Download Consul
もしくは、wgetなどで。
$ wget https://releases.hashicorp.com/consul/0.7.2/consul_0.7.2_linux_amd64.zip
展開します。
$ unzip consul_0.7.2_linux_amd64.zip Archive: consul_0.7.2_linux_amd64.zip inflating: consul
「consul」というファイルが現れるので、このファイルを起動オプションを付けて実行します。
$ ./consul agent option...
また、Consul Agentの起動に必須となるのはData Directory(-data-dirで指定)なので、こちらは
今回はとりあえずカレントディレクトリに「data」というディレクトリを作って、こちらを指定
するものとします。
$ ./consul agent -data-dir=data option...
オプションについては、Agentの種類で異なるので都度紹介します。
では、だいぶ前置きが長くなりましたがはじめていきましょう。
Consul Agent(Server)のクラスタ構成
では、まずConsul Agent(Server)を起動して、クラスタを構成します。
各サーバーで微妙にオプションが違うので、全部記載。
## consulserver1(Leader) $ ./consul agent -server -data-dir=data -client=172.17.0.2 -bootstrap-expect=1 -ui ## consulserver2 $ ./consul agent -server -data-dir=data -join=172.17.0.2 -client=172.17.0.3 -ui ## consulserver3 $ ./consul agent -server -data-dir=data -join=172.17.0.2 -client=172.17.0.4 -ui
オプションを説明します。
- agent … Agentとして起動することを表します
- -server … Serverとして起動することを表します
- -data-dir … Consulが内部で状態保存に使用するData Directoryを指定します
- -client … Clientから使用する際のIPアドレスを指定します(デフォルトは127.0.0.1となっているため、外部から接続できません)
- -ui … 付けておくと、ConsouのWebインターフェースを見ることができます
- -join … クラスタに参加する先のIPアドレスを指定します(最初のNode以外に付けています)
- -bootstrap-expect … Consulが起動した際に、期待するConsulインスタンスの数。これを下回っているとリーダーを選出できません。今回は1に設定しています。
「-client」でバインドしたIPアドレスで公開されるのは、HTTP、HTTPS、DNS、RPCなので、他のサーバーから
Webインターフェースを見る時に困ったりすると思います。DNSは、ローカルにConsul Agentを動かして
いることが多そうな気がするので、そんなに困らないかも…?
この状態で、今回の構成であれば「http://172.17.0.2:8500/ui/」にアクセスすると、Consulの状態を
確認することができます。
※1度、左の「consul」と書かれたラベルをクリックすると、左に登録してあるNodeが展開されます
デフォルトは画面上部の「SERVICES」が選ばれた状態となっているので、「NODES」を選ぶと登録してある
Nodeの一覧が見れます。
3つのNodeがいることが確認できます。
また、consulのコマンドで確認してもOKです。
$ ./consul members -rpc-addr=172.17.0.2:8400 Node Address Status Type Build Protocol DC consulserver1 172.17.0.2:8301 alive server 0.7.2 2 dc1 consulserver2 172.17.0.3:8301 alive server 0.7.2 2 dc1 consulserver3 172.17.0.4:8301 alive server 0.7.2 2 dc1
Consul Agent(Client - WildFly Swarm)をクラスタに参加させる
続いて、WildFly Swarmを含めたConsul Agentをクラスタに参加させます。
まずは、Agentの起動。
## consulswarmclient1 $ ./consul agent -data-dir=data -join=172.17.0.2 ## consulswarmclient2 $ ./consul agent -data-dir=data -join=172.17.0.2
今回は、UIは外部から見れなくてもいいかなと思ったので、「-client」と「-ui」は付けていません。
ちなみに、この時点ではUI上の「SERVICES」には変化がありませんが、
「NODES」には起動したNodeが追加されます。
続いて、WildFly Swarmのアプリケーションを作成しましょう。
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.littlewings</groupId> <artifactId>consul-integration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <scala.major.version>2.12</scala.major.version> <scala.version>${scala.major.version}.1</scala.version> <scala.maven.plugin.version>3.2.2</scala.maven.plugin.version> <failOnMissingWebXml>false</failOnMissingWebXml> <wildfly.swarm.version>2017.1.1</wildfly.swarm.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.wildfly.swarm</groupId> <artifactId>bom</artifactId> <version>${wildfly.swarm.version}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>${scala.version}</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.wildfly.swarm</groupId> <artifactId>jaxrs</artifactId> </dependency> <dependency> <groupId>org.wildfly.swarm</groupId> <artifactId>topology-consul</artifactId> </dependency> </dependencies> <build> <finalName>consul-integration</finalName> <plugins> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>${scala.maven.plugin.version}</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> <configuration> <scalaVersion>${scala.version}</scalaVersion> <args> <arg>-Xlint</arg> <arg>-unchecked</arg> <arg>-deprecation</arg> <arg>-feature</arg> </args> <recompileMode>incremental</recompileMode> </configuration> </plugin> <plugin> <groupId>org.wildfly.swarm</groupId> <artifactId>wildfly-swarm-plugin</artifactId> <version>${wildfly.swarm.version}</version> <configuration> <mainClass>org.littlewings.wildflyswarm.consul.App</mainClass> </configuration> <executions> <execution> <goals> <goal>package</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
特徴的なのは、「topology-consul」への依存関係を加えたことですね。
<dependency> <groupId>org.wildfly.swarm</groupId> <artifactId>topology-consul</artifactId> </dependency>
個人的には珍しくmainクラスを指定しています。
<configuration> <mainClass>org.littlewings.wildflyswarm.consul.App</mainClass> </configuration>
テスト用のJAX-RSリソースクラス。単純にホスト名を返す実装とします。
src/main/scala/org/littlewings/wildflyswarm/consul/HostNameResource.scala
package org.littlewings.wildflyswarm.consul import java.net.InetAddress import javax.ws.rs.core.MediaType import javax.ws.rs.{GET, Path, Produces} @Path("hostname") class HostNameResource { @GET @Produces(Array(MediaType.TEXT_PLAIN)) def get: String = InetAddress.getLocalHost.getHostName }
続いて、mainクラス。
src/main/scala/org/littlewings/wildflyswarm/consul/App.scala
package org.littlewings.wildflyswarm.consul import org.jboss.shrinkwrap.api.ShrinkWrap import org.jboss.shrinkwrap.api.spec.WebArchive import org.wildfly.swarm.Swarm import org.wildfly.swarm.jaxrs.JAXRSArchive import org.wildfly.swarm.topology.TopologyArchive object App { def main(args: Array[String]): Unit = { val swarm = new Swarm(args: _*) val deployment = ShrinkWrap.create(classOf[JAXRSArchive]) //deployment.as(classOf[TopologyArchive]).advertise() // AdvertiseがWARの名前になる deployment.as(classOf[TopologyArchive]).advertise("swarm") deployment.addResource(classOf[HostNameResource]) swarm.start().deploy(deployment) } }
WildFly SwarmのTopologyのドキュメントに沿って、TopologyArchive#advertiseすればいいのですが、ここでの
advertiseの値がConsulでのService名になります。
ふつうに実行してしまうと、内部のWARの名前ってこんなことになって
2017-01-14 12:37:26,160 INFO [org.jboss.as.server] (main) WFLYSRV0010: Deployed "c166ab56-4056-475a-a81a-a8d0cf63e12a.war" (runtime-name : "c166ab56-4056-475a-a81a-a8d0cf63e12a.war")
指定するにはとても困るので、今回はService名を「swarm」としました。
あとはパッケージングします。
$ mvn package
で、起動。
## consulswarmclient1 $ java -Dswarm.bind.address=172.17.0.5 -jar /path/to/consul-integration-swarm.jar ## consulswarmclient2 $ java -Dswarm.bind.address=172.17.0.6 -jar /path/to/consul-integration-swarm.jar
なんで「-Dswarm.bind.address」を付けたかは、あとで説明します。
Webインターフェース上の「SERVICES」では、登録されたWildFly SwarmのServiceを見ることができます。
左に、「swarm」というサービスが増えていますね。これが、TopologyArchive#advertiseで指定した名前です。
あと、よーく見ると右上部の「TAGS」に「http」が増えていますね。こちらもWildFly Swarmが登録したものですが、
名前使われます。
とりあえず、簡単に動作確認。
$ curl http://172.17.0.5:8080/hostname consulswarmclient1 $ curl http://172.17.0.6:8080/hostname consulswarmclient2
OKですね。
Consul Agent(Client - curl)をクラスタに参加させる
起動したWildFly SwarmのConsulを使った確認に移る前に、先にcurlを使って確認する側のConsul Agentを起動しておきます。
※これは書き手の都合上です
$ ./consul agent -data-dir=data -join=172.17.0.2
これで、Consulクラスタのひととおりのメンバーが揃いました。
動作確認など
ここからは、Consul Agent(Client - curl)側から確認してみます。
digで動作確認
さて、名前解決の動作確認をしてみましょう。
Consulでは、NodeとServiceの名前解決を行うことができます。
DNS Interface
Nodeの名前解決を行う場合の書式は
<node>.node[.datacenter].<domain>
で、Serviceの名前解決を行う場合の書式は
[tag.]<service>.service[.datacenter].<domain>
となります。
まずはNode名から。ConsulのNode名はデフォルトはホスト名ですが、「-node」オプションで任意の名前に変更することもできます。
digで確認。digの向き先は、ローカルで動いているConsul AgentのDNSポート(8600)となります。bindでアドレスを変えたりしている
場合は、その内容に合わせてください。
Nodeについては、「Node名」.node.consulで確認することができます。Datacenter名を入れてもいいのですが、今回は省略します。
## consulserver1 $ dig @localhost -p 8600 consulserver1.node.consul ANY ; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> @localhost -p 8600 consulserver1.node.consul ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41638 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;consulserver1.node.consul. IN ANY ;; ANSWER SECTION: consulserver1.node.consul. 0 IN A 172.17.0.2 ;; Query time: 60 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jan 14 21:43:24 JST 2017 ;; MSG SIZE rcvd: 59 ## consulswarmclient1 $ dig @localhost -p 8600 consulswarmclient1.node.consul ANY ; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> @localhost -p 8600 consulswarmclient1.node.consul ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54267 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;consulswarmclient1.node.consul. IN ANY ;; ANSWER SECTION: consulswarmclient1.node.consul. 0 IN A 172.17.0.5 ;; Query time: 5 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jan 14 21:43:38 JST 2017 ;; MSG SIZE rcvd: 64 ## consulcurlclient $ dig @localhost -p 8600 consulcurlclient.node.consul ANY ; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> @localhost -p 8600 consulcurlclient.node.consul ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2666 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;consulcurlclient.node.consul. IN ANY ;; ANSWER SECTION: consulcurlclient.node.consul. 0 IN A 172.17.0.1 ;; Query time: 1 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jan 14 21:44:39 JST 2017 ;; MSG SIZE rcvd: 62
続いてServiceで確認。「swarm」というServiceが登録されているので、こちらを使います。
Serviceの場合は、「Service名」.service.consul、もしくは「タグ名」.「Service名」.service.consulとなります。
## タグを入れない場合 $ dig @localhost -p 8600 swarm.service.consul ANY ; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> @localhost -p 8600 swarm.service.consul ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23476 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;swarm.service.consul. IN ANY ;; ANSWER SECTION: swarm.service.consul. 0 IN A 172.17.0.5 swarm.service.consul. 0 IN A 172.17.0.6 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jan 14 21:45:38 JST 2017 ;; MSG SIZE rcvd: 70 ## タグを入れた場合 $ dig @localhost -p 8600 http.swarm.service.consul ANY ; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> @localhost -p 8600 http.swarm.service.consul ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11862 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;http.swarm.service.consul. IN ANY ;; ANSWER SECTION: http.swarm.service.consul. 0 IN A 172.17.0.6 http.swarm.service.consul. 0 IN A 172.17.0.5 ;; Query time: 18 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jan 14 21:46:46 JST 2017 ;; MSG SIZE rcvd: 75
名前解決できていますね。
HTTP APIで確認
登録されているServiceやNodeなどを、HTTP APIで見ることもできます。
HTTP API
ここから、Serviceを登録したりすることも可能です。
今回は、NodeおよびServiceの一覧を見てみましょう。
Node一覧。
$ curl http://localhost:8500/v1/agent/members [{"Name":"consulswarmclient1","Addr":"172.17.0.5","Port":8301,"Tags":{"build":"0.7.2:'a9afa0c","dc":"dc1","role":"node","vsn":"2","vsn_max":"3","vsn_min":"2"},"Status":1,"ProtocolMin":1,"ProtocolMax":5,"ProtocolCur":2,"DelegateMin":2,"DelegateMax":4,"DelegateCur":4},{"Name":"consulserver2","Addr":"172.17.0.3","Port":8301,"Tags":{"build":"0.7.2:'a9afa0c","dc":"dc1","port":"8300","role":"consul","vsn":"2","vsn_max":"3","vsn_min":"2"},"Status":1,"ProtocolMin":1,"ProtocolMax":5,"ProtocolCur":2,"DelegateMin":2,"DelegateMax":4,"DelegateCur":4},{"Name":"consulserver1","Addr":"172.17.0.2","Port":8301,"Tags":{"bootstrap":"1","build":"0.7.2:'a9afa0c","dc":"dc1","port":"8300","role":"consul","vsn":"2","vsn_max":"3","vsn_min":"2"},"Status":1,"ProtocolMin":1,"ProtocolMax":5,"ProtocolCur":2,"DelegateMin":2,"DelegateMax":4,"DelegateCur":4},{"Name":"consulswarmclient2","Addr":"172.17.0.6","Port":8301,"Tags":{"build":"0.7.2:'a9afa0c","dc":"dc1","role":"node","vsn":"2","vsn_max":"3","vsn_min":"2"},"Status":1,"ProtocolMin":1,"ProtocolMax":5,"ProtocolCur":2,"DelegateMin":2,"DelegateMax":4,"DelegateCur":4},{"Name":"consulcurlclient","Addr":"172.17.0.1","Port":8301,"Tags":{"build":"0.7.2:'a9afa0c","dc":"dc1","role":"node","vsn":"2","vsn_max":"3","vsn_min":"2"},"Status":1,"ProtocolMin":1,"ProtocolMax":5,"ProtocolCur":2,"DelegateMin":2,"DelegateMax":4,"DelegateCur":4},{"Name":"consulserver3","Addr":"172.17.0.4","Port":8301,"Tags":{"build":"0.7.2:'a9afa0c","dc":"dc1","port":"8300","role":"consul","vsn":"2","vsn_max":"3","vsn_min":"2"},"Status":1,"ProtocolMin":1,"ProtocolMax":5,"ProtocolCur":2,"DelegateMin":2,"DelegateMax":4,"DelegateCur":4}]
Service一覧。ただ、ServiceはローカルのAgentが管理しているものしか見えないみたいなので、こちらのコマンドはWildFly Swarmを
動かしているホストで実行しました。
$ curl http://localhost:8500/v1/agent/services {"swarm:172.17.0.6:8080":{"ID":"swarm:172.17.0.6:8080","Service":"swarm","Tags":["http"],"Address":"172.17.0.6","Port":8080,"EnableTagOverride":false,"CreateIndex":0,"ModifyIndex":0}}
地味にportとか分かっているみたいです。
Consul Command(CLI)
HTTP API以外にも、consul実行ファイルに対してコマンドを実行することもできます。
Consul Command(CLI)
とりあえず、Node一覧を見てみましょう。
$ ./consul members Node Address Status Type Build Protocol DC consulcurlclient 172.17.0.1:8301 alive client 0.7.2 2 dc1 consulserver1 172.17.0.2:8301 alive server 0.7.2 2 dc1 consulserver2 172.17.0.3:8301 alive server 0.7.2 2 dc1 consulserver3 172.17.0.4:8301 alive server 0.7.2 2 dc1 consulswarmclient1 172.17.0.5:8301 alive client 0.7.2 2 dc1 consulswarmclient2 172.17.0.6:8301 alive client 0.7.2 2 dc1
Dnsmasqをインストールしてcurlで動作確認
名前解決できたりNodeやServiceの一覧が見れたのはいいのですが、このままだとcurlで名前解決ができません。
ここは、ドキュメントに習ってDnsmasqを使ってConsulでの名前解決を統合してみます。
DNS Forwarding
Dnsmasqインストール。
$ sudo apt-get install dnsmasq
ドキュメントに習い、Dnsmasqの設定をしていきます。
$ sudo vim /etc/dnsmasq.conf
dnsmasq.confの最後に、「consul」で終わるエントリはローカルのDNSサーバー(Consul)に解決するようにします。
server=/consul/127.0.0.1#8600
設定したら、Dnsmasqを再起動します。
$ sudo service dnsmasq restart
確認。Serviceで確認するので、今回は「swarm.service.consul」でアクセスします。「http.swarm.service.consul」でもOKです。
$ curl http://swarm.service.consul:8080/hostname consulswarmclient2 $ curl http://swarm.service.consul:8080/hostname consulswarmclient1 $ curl http://swarm.service.consul:8080/hostname consulswarmclient1 $ curl http://swarm.service.consul:8080/hostname consulswarmclient2
ちょっと不規則気味ですが、WildFly Swarmが動作しているServerに振り分けられていることがわかります。
また、メンバー(この場合はWildFly Swarmのアプリケーション)を停止したりすると、切り離されます。
$ curl http://swarm.service.consul:8080/hostname consulswarmclient1 $ curl http://swarm.service.consul:8080/hostname consulswarmclient1
もちろん、再度クラスタに参加させればまた名前解決されるメンバーに復帰します。
動作確認としてはOKそうですね。
オマケ
「swarm.bind.address」について
WildFly Swarmのアプリケーションを起動する時に、わざわざ「-Dswarm.bind.address」を指定していました。
## consulswarmclient1 $ java -Dswarm.bind.address=172.17.0.5 -jar /path/to/consul-integration-swarm.jar ## consulswarmclient2 $ java -Dswarm.bind.address=172.17.0.6 -jar /path/to/consul-integration-swarm.jar
これ、なんで付けてたかというと、何も付けずに起動すると名前解決の結果がこうなるからです。
## タグなし $ dig @localhost -p 8600 swarm.service.consul ANY ; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> @localhost -p 8600 swarm.service.consul ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51890 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;swarm.service.consul. IN ANY ;; ANSWER SECTION: swarm.service.consul. 0 IN AAAA :: ;; Query time: 1 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jan 14 22:25:03 JST 2017 ;; MSG SIZE rcvd: 66 ## タグあり $ dig @localhost -p 8600 http.swarm.service.consul ANY ; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> @localhost -p 8600 http.swarm.service.consul ANY ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53860 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;http.swarm.service.consul. IN ANY ;; ANSWER SECTION: http.swarm.service.consul. 0 IN AAAA :: ;; Query time: 1 msec ;; SERVER: 127.0.0.1#8600(127.0.0.1) ;; WHEN: Sat Jan 14 22:25:05 JST 2017 ;; MSG SIZE rcvd: 71
ひとつしか返ってきませんが…?
;; ANSWER SECTION: swarm.service.consul. 0 IN AAAA :: ;; ANSWER SECTION: http.swarm.service.consul. 0 IN AAAA ::
ただ、Consulの「swarm」Service上は確かに2つ登録されています。
これ、WildFly SwarmのConsul統合部分の起動時のログを見ていたらピンとくるんですけど、こんなのが出力されます。
2017-01-14 13:24:35,447 INFO [org.wildfly.swarm.topology.consul.runtime.Advertiser] (MSC service thread 1-7) Registered service swarm:0:0:0:0:0:0:0:0:8080
「-Dswarm.bind.address」を指定すると、こうなります。
2017-01-14 13:27:17,940 INFO [org.wildfly.swarm.topology.consul.runtime.Advertiser] (MSC service thread 1-7) Registered service swarm:172.17.0.5:8080
つまり、何も指定しないとローカルアドレスが登録されるということで…。
WildFly Swarmは、どこのConsulにアクセスしている?
これはConsulTopologyFractionを見ると分かります。
https://github.com/wildfly-swarm/wildfly-swarm/blob/2017.1.1/fractions/topology-consul/src/main/java/org/wildfly/swarm/topology/consul/ConsulTopologyFraction.java#L100
デフォルトでは、「http://localhost:8500」にアクセスしに行こうとします。つまり、ローカルにConsul Agentがいることが前提に
なっていますね。
static { URL tmp = null; try { tmp = new URL("http://localhost:8500"); } catch (MalformedURLException e) { throw new RuntimeException(e); } DEFAULT_URL = tmp; }
もちろん、ConsulTopologyFractionを使用すればカスタマイズはできそうです。
アクセス先が切り替わらない
実はこの構成ですが、ほとんどDockerでやっています。で、Docker内(Ubuntuイメージ)でDnsmasqをインストールして確認して
みたのですが、ひとつのホストにアクセスし続けていてけっこう困りました。
どうもこれが原因っぽいです。
Consul DNS round robin works for host but not for containers - General - Docker Forums
今回は、curlとDnsmasqはホスト側にインストールして実行しました。
「/etc/resolv.conf」について
「/etc/resolv.conf」ファイルは、今回編集しませんでした。
/etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8) # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN nameserver 127.0.0.1 search localdomain
nameserverが他に登録されている場合は、ローカルのnameserverを先頭に持ってくるようにしましょう。
場合によっては、「/etc/dnsmasq.conf 」ファイルに「strict-order」を書いた方がいい時もあるようです。
【Consul】dnsmasqで名前解決を行う方法を試してみた | Pocketstudio.jp log3
まとめ
WildFly SwarmのConsul統合機能を使って、Service Discovery、名前解決の仕組みとして使ってみました。
ほとんどConsulについての調べ物が多かった気がするのですが、とりあえず確認したいところまで動かせたので
満足です。
名前解決できるのはいいのですが、DNSという関係上、ポートはDNSに頼っている限りは解決できないなぁとちょっと
思いましたが、そのあたりはまあ、と…。
今回作成したコード(WildFly Swarmアプリケーションのみ)は、こちらに置いています。
https://github.com/kazuhira-r/wildfly-swarm-scala-examples/tree/master/consul-integration
- 60 http://www.google.com
- 58 https://www.google.co.jp/
- 5 http://search.yahoo.co.jp/
- 5 https://t.co/DbwRXeIOvY
- 4 https://www.google.com/
- 3 https://www.google.co.jp
- 1 http://webcache.googleusercontent.com/search?q=cache:Cyo64_9TJ1kJ:d.hatena.ne.jp/Kazuhira/20140107/1389108413+&cd=1&hl=ja&ct=clnk&gl=jp
- 1 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwiEhMad6MHRAhWKTLwKHZnEC14QFggaMAA&url=http://d.hatena.ne.jp/Kazuhira/20140223/1393144924&usg=AFQjCNEduBsQ63G4WFFn1X1aVjQoOO7G4w&bvm=bv.144224172,d.dGc
- 1 https://www.google.com.tr/
- 1 https://www.google.com.tw/