docker深入2-使用registrator和consul-template自动注册和变更服务
2016/6/23
一、示例 测试环境基于文档:docker深入2-熟悉v1.11和找不同.txt host-n35 host-n36 ----------------------------------------------------- conf consul-tempalte ---------------------------------------- webapp(container) ------ webapp(container) ---------------------------------------- registrator_35 ------ registrator_36 consul-node1 ------ consul-node2 ----------------------------------------------------- 二、配置 1、配置 consul 集群 调整防火墙: firewall-cmd --zone=public --add-port=8300-8302/tcp firewall-cmd --zone=public --add-port=8301-8302/udp firewall-cmd --zone=public --add-port=8400/tcp firewall-cmd --zone=public --add-port=8500/tcp firewall-cmd --zone=public --add-port=53/tcp firewall-cmd --zone=public --add-port=53/udp 持久: firewall-cmd --zone=public --add-port=2375/tcp --permanent firewall-cmd --zone=public --add-port=4000/tcp --permanent firewall-cmd --zone=public --add-port=8300-8302/tcp --permanent firewall-cmd --zone=public --add-port=8301-8302/udp --permanent firewall-cmd --zone=public --add-port=8400/tcp --permanent firewall-cmd --zone=public --add-port=8500/tcp --permanent firewall-cmd --zone=public --add-port=53/tcp --permanent firewall-cmd --zone=public --add-port=53/udp --permanent 注1:如下配置简化了 IP 映射的细节,直接使用 0.0.0.0 来提供服务。 注2:cunsul 的 service 要使用 dns 来提供域名解析,这样 registrator 才能顺利的注册服务到 consul 上来。 【n35】 docker run -d --restart=always -v /data/docker/consul:/data \ -p 8300:8300 \ -p 8301:8301 \ -p 8301:8301/udp \ -p 8302:8302 \ -p 8302:8302/udp \ -p 8400:8400 \ -p 8500:8500 \ -p 53:53 \ -p 53:53/udp \ --name=consul-node1 progrium/consul -server -advertise 10.111.222.35 -bootstrap-expect 2 【n36】 docker run -d --restart=always -v /data/docker/consul:/data \ -p 8300:8300 \ -p 8301:8301 \ -p 8301:8301/udp \ -p 8302:8302 \ -p 8302:8302/udp \ -p 8400:8400 \ -p 8500:8500 \ -p 53:53 \ -p 53:53/udp \ --name=consul-node2 progrium/consul -server -advertise 10.111.222.36 -join 10.111.222.35 【查看 n35 日志】 [Jack@n35 ~]$ docker logs -f consul-node1 2016/05/23 08:58:58 [INFO] serf: EventMemberJoin: 0db39e28b326 10.111.222.36 2016/05/23 08:58:58 [INFO] consul: adding server 0db39e28b326 (Addr: 10.111.222.36:8300) (DC: dc1) 2016/05/23 08:58:58 [INFO] consul: Attempting bootstrap with nodes: [10.111.222.35:8300 10.111.222.36:8300] 2016/05/23 08:58:58 [WARN] raft: Heartbeat timeout reached, starting election 2016/05/23 08:58:58 [INFO] raft: Node at 10.111.222.35:8300 [Candidate] entering Candidate state 2016/05/23 08:58:58 [WARN] raft: Remote peer 10.111.222.36:8300 does not have local node 10.111.222.35:8300 as a peer 2016/05/23 08:58:58 [INFO] raft: Election won. Tally: 2 2016/05/23 08:58:58 [INFO] raft: Node at 10.111.222.35:8300 [Leader] entering Leader state 2016/05/23 08:58:58 [INFO] consul: cluster leadership acquired 2016/05/23 08:58:58 [INFO] consul: New leader elected: be67d37cbf68 2016/05/23 08:58:58 [INFO] raft: pipelining replication to peer 10.111.222.36:8300 2016/05/23 08:58:58 [INFO] consul: member 'be67d37cbf68' joined, marking health alive 2016/05/23 08:58:58 [INFO] consul: member '0db39e28b326' joined, marking health alive 【查看 n36 日志】 [Jack@n36 ~]$ docker logs -f consul-node2 2016/05/23 08:58:58 [INFO] consul: adding server be67d37cbf68 (Addr: 10.111.222.35:8300) (DC: dc1) 2016/05/23 08:58:58 [INFO] consul: New leader elected: be67d37cbf68 2、配置 registrator 来注册 docker container 的信息到上述 consul 集群中。 【n35】 docker run -d --restart=always -v /var/run/docker.sock:/tmp/docker.sock --name registrator_35 gliderlabs/registrator consul://10.111.222.35:8500 【n36】 docker run -d --restart=always -v /var/run/docker.sock:/tmp/docker.sock --name registrator_36 gliderlabs/registrator consul://10.111.222.36:8500 【查看 n35 日志】 [Jack@n35 ~]$ docker logs -f registrator_35 2016/05/23 09:05:08 Starting registrator v7 ... 2016/05/23 09:05:08 Using consul adapter: consul://10.111.222.35:8500 2016/05/23 09:05:08 Connecting to backend (0/0) 2016/05/23 09:05:08 consul: current leader 10.111.222.35:8300 2016/05/23 09:05:08 Listening for Docker events ... 2016/05/23 09:05:08 Syncing services on 3 containers 2016/05/23 09:05:08 ignored: 205155915c61 no published ports 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:53 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:8300 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:53:udp 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:8302 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:8302:udp 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:8400 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:8500 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:8301:udp 2016/05/23 09:05:08 added: be67d37cbf68 205155915c61:consul-node1:8301 2016/05/23 09:05:08 added: 312c4fdb40d0 205155915c61:reg4work:5000 【查看 n36 日志】 [Jack@n36 ~]$ docker logs -f registrator_36 2016/05/23 09:05:23 Starting registrator v7 ... 2016/05/23 09:05:23 Using consul adapter: consul://10.111.222.36:8500 2016/05/23 09:05:23 Connecting to backend (0/0) 2016/05/23 09:05:23 consul: current leader 10.111.222.35:8300 2016/05/23 09:05:23 Listening for Docker events ... 2016/05/23 09:05:23 Syncing services on 2 containers 2016/05/23 09:05:23 ignored: 1f61c2d2bcf9 no published ports 2016/05/23 09:05:23 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:8302:udp 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:8500 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:8301 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:53:udp 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:8300 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:8301:udp 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:8302 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:53 2016/05/23 09:05:24 added: 0db39e28b326 1f61c2d2bcf9:consul-node2:8400 分别在 2 个 host 上启动 1 个 container,观察是否自动被注册到 consul 中: [Jack@n36 ~]$ docker run -d -P --name z001 training/webapp python app.py 66ef0c6ce19b6c33e13d772ada5504732c032046bb9cd2410ec48545111aa140 [Jack@n35 ~]$ docker run -d -P --name z002 training/webapp python app.py 7fde646e0c29370ff1375f4692f4dc64c14eda490997d736cb2cc2a0712ce039 再次查看日志: 【查看 n35 日志】 2016/05/23 09:09:11 added: 7fde646e0c29 205155915c61:z002:5000 【查看 n36 日志】 2016/05/23 09:08:38 added: 66ef0c6ce19b 1f61c2d2bcf9:z001:5000 通过 API 来查看 webapp 的内容: [Jack@n36 ~]$ curl -s 10.111.222.35:8500/v1/catalog/service/webapp |python -mjson.tool [ { "Address": "10.111.222.36", "Node": "0db39e28b326", "ServiceAddress": "", "ServiceID": "1f61c2d2bcf9:z001:5000", "ServiceName": "webapp", "ServicePort": 32774, "ServiceTags": null }, { "Address": "10.111.222.35", "Node": "be67d37cbf68", "ServiceAddress": "", "ServiceID": "205155915c61:z002:5000", "ServiceName": "webapp", "ServicePort": 32768, "ServiceTags": null } ] 3、使用 consul-template 目的:在一台测试机上安装 consul-template 来从 consul 获取数据,更新本地的某个配置文件。 从下述页面选择一个版本: https://releases.hashicorp.com/consul-template/ 注3:将 n36 充当测试机。 [root@n36 ~] curl https://releases.hashicorp.com/consul-template/0.14.0/consul-template_0.14.0_linux_amd64.zip -o consul-template.zip && unzip consul-template.zip && mv ./consul-template /usr/bin/ 生成一个简易的模版来测试: [Jack@n36 ~]$ echo -e '{{range service "webapp"}}\nserver ``.`Address`:``.`Port``end`' > /tmp/consul.ctmpl [Jack@n36 ~]$ cat /tmp/consul.ctmpl {{range service "webapp"}} server ``.`Address`:``.`Port``end` 启动 consul-template 来看看模版生成的内容是啥: [Jack@n36 ~]$ consul-template -consul 10.111.222.35:8500 -template "/tmp/consul.ctmpl:/tmp/consul.result" -once 结果如下: [Jack@n36 ~]$ cat /tmp/consul.result server 10.111.222.36:32774 server 10.111.222.35:32768 如上所示,符合预期。 测试请求是否正常: [Jack@n36 ~]$ curl 10.111.222.36:32774 Hello world![Jack@n36 ~]$ [Jack@n36 ~]$ curl 10.111.222.35:32768 Hello world![Jack@n36 ~]$ [Jack@n36 ~]$ 4、移除 webapp 后观察变化 [Jack@n35 ~]$ docker rm -f z002 z002 【查看 n35 日志】 [Jack@n35 ~]$ docker logs -f registrator_35 2016/05/23 09:53:23 removed: 7fde646e0c29 205155915c61:z002:5000 [Jack@n35 ~]$ docker logs -f consul-node1 2016/05/23 09:53:23 [INFO] agent: Deregistered service '205155915c61:z002:5000' 符合预期。 三、疑惑 Q1、consul 服务注意事项? A: -bootstrap-expect 3:表明需要有3个节点,才能启动集群。 -bootstrap:单个节点使用这个标记来立即启动服务,而不是用来等待集群的创建。 -advertise:来申明 consul 使用哪个 IP 来提供服务。 -join:指定第一个 consul 服务的 IP 来加入集群。 使用 dig 来获取信息: [root@n36 ~]# yum install bind-utils -y [Jack@n36 ~]$ curl -s 10.111.222.36:8500/v1/catalog/service/webapp |python -mjson.tool [ { "Address": "10.111.222.36", "Node": "8b716e39cc09", "ServiceAddress": "", "ServiceID": "6402f685c105:z001:5000", "ServiceName": "webapp", "ServicePort": 32770, "ServiceTags": null }, { "Address": "10.111.222.36", "Node": "8b716e39cc09", "ServiceAddress": "", "ServiceID": "6402f685c105:z002:5000", "ServiceName": "webapp", "ServicePort": 32771, "ServiceTags": null }, { "Address": "10.111.222.36", "Node": "8b716e39cc09", "ServiceAddress": "", "ServiceID": "6402f685c105:z003:5000", "ServiceName": "webapp", "ServicePort": 32772, "ServiceTags": null } ] [Jack@n36 ~]$ dig @10.111.222.36 webapp.service.consul SRV ; <<>> DiG 9.9.4-RedHat-9.9.4-29.el7_2.3 <<>> @10.111.222.36 webapp.service.consul SRV ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22230 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 3 ;; QUESTION SECTION: ;webapp.service.consul. IN SRV ;; ANSWER SECTION: webapp.service.consul. 0 IN SRV 1 1 32772 8b716e39cc09.node.dc1.consul. webapp.service.consul. 0 IN SRV 1 1 32770 8b716e39cc09.node.dc1.consul. webapp.service.consul. 0 IN SRV 1 1 32771 8b716e39cc09.node.dc1.consul. ;; ADDITIONAL SECTION: 8b716e39cc09.node.dc1.consul. 0 IN A 10.111.222.36 8b716e39cc09.node.dc1.consul. 0 IN A 10.111.222.36 8b716e39cc09.node.dc1.consul. 0 IN A 10.111.222.36 ;; Query time: 2 msec ;; SERVER: 10.111.222.36#53(10.111.222.36) ;; WHEN: Thu Jun 02 16:30:43 CST 2016 ;; MSG SIZE rcvd: 378 Q2、registrator 服务注意事项? A:在 overlay 网络下,配置 consul 集群时,DNS 端口使用哪个 IP 来提供服务? registrator 是否能检测到服务并注册成功呢? 笔者了解到以下2个方面需要注意: 1、配置 consul 时,指定了映射 53 端口到外部的IP,这个 ip 应该如何选择需要琢磨下。 2、配置 registrator 时,可以指定 docker 参数 --net,也可以指定 registrator 的参数 -internal,用途需要琢磨下。 Docker Options --net=host recommended Helps Registrator get host-level IP and hostname Registrator Options -internal Use exposed ports instead of published ports Q3、consul-template 服务注意事项? A: -consul 指定 consul 服务的IP:PORT。 -template 指定 输入模版:输出模版:命令。 -once 表明 在命令行运行一次就退出。 -dry 表明 将结果输出到控制台,并不写入磁盘文件,且命令也不启动。 Q4、如果只有一台服务器,如何体验? A:以【n36】为例: 1)启动一个 consul 服务 [Jack@n36 ~]$ docker run -d --restart=always -v /data/docker/consul-test:/data \ -p 8300:8300 \ -p 8301:8301 \ -p 8301:8301/udp \ -p 8302:8302 \ -p 8302:8302/udp \ -p 8400:8400 \ -p 8500:8500 \ -p 53:53 \ -p 53:53/udp \ --name=consul-test progrium/consul -server -advertise 10.111.222.36 -bootstrap 2)启动一个 registrator 服务 [Jack@n36 ~]$ docker run -d --restart=always -v /var/run/docker.sock:/tmp/docker.sock --name registrator_36 gliderlabs/registrator consul://10.111.222.36:8500 3)启动 docker 容器,registrator 将自动注册容器信息到 consul 中。 [Jack@n36 ~]$ docker run -d -P --name z001 training/webapp python app.py [Jack@n36 ~]$ docker run -d -P --name z002 training/webapp python app.py [Jack@n36 ~]$ docker run -d -P --name z003 training/webapp python app.py 4)查看 consul 中注册的内容 [Jack@n36 ~]$ curl -s 10.111.222.36:8500/v1/catalog/service/webapp |python -mjson.tool 5)查看 consul-template 生成的结果 [Jack@n36 ~]$ consul-template -consul 10.111.222.36:8500 -template "/tmp/consul.ctmpl:/tmp/consul.result" -once 6)应用到 haproxy 上 [root@n36 ~]# yum install haproxy [root@n36 ~]# cp -a /etc/haproxy/haproxy.cfg{,.ctmpl} 调整 haproxy 模版: [root@n36 ~]# vim /etc/haproxy/haproxy.cfg.ctmpl (略) backend app balance roundrobin {{range service "webapp"}} server app-``.`Port` ``.`Address`:``.`Port` check`end` 生成配置并重启服务: [root@n36 ~]# consul-template -consul 10.111.222.36:8500 -template "/etc/haproxy/haproxy.cfg.ctmpl:/etc/haproxy/haproxy.cfg:systemctl reload haproxy.service" -once 验证配置: [root@n36 ~]# cat /etc/haproxy/haproxy.cfg (略) backend app balance roundrobin server app-32774 10.111.222.36:32774 check server app-32775 10.111.222.36:32775 check server app-32776 10.111.222.36:32776 check 检查 haproxy 服务的状态 [root@n36 ~]# systemctl status haproxy.service 符合预期。 注:如果 status 显示 haproxy 绑定端口失败,权限异常等问题,导致启动服务失败,则要先考虑是否启用了 selinux,很简单,按照如下操作调整设置即可验证是否受其影响。 临时关闭:setenforce 0 查看状态:sestatus Q5、突然发现执行大部分 docker 指令时,要等待很久才会有结果,系统的资源占用并不高,似乎是 docker 服务比较卡顿,这是为何? A:请检查 docker 服务是否存在异常,提供一个实例如下所述。 执行命令: [Jack@n36 ~]$ docker network ls 发现等待了半天才有回应。 使用 strace 查看: [root@n36 ~]# time strace -p `ps -ef |grep 'docker network' |grep -v grep |awk '{print $2}'` Process 14169 attached futex(0x21ec290, FUTEX_WAIT, 0, NULL) = 0 epoll_wait(5, {}, 128, 0) = 0 select(0, NULL, NULL, NULL, {0, 100}) = 0 (Timeout) futex(0xc820030e90, FUTEX_WAKE, 1) = 1 futex(0x21ec290, FUTEX_WAIT, 0, NULL+++ exited with 0 +++ real 1m11.029s user 0m0.021s sys 0m0.026s 果然等待了很久。 检查服务状态和系统日志: [root@n36 ~]# systemctl status docker.service -l [root@n36 ~]# tail -f /var/log/message 发现有节点连接失败的情况,继续查看 docker 服务的配置: [root@n36 ~]# cat /lib/systemd/system/docker.service |grep daemon ExecStart=/usr/bin/docker daemon -H tcp://10.111.222.35:2375 -H unix:///var/run/docker.sock --cluster-store=consul://10.111.222.35:8500 --cluster-advertise=em2:2375 --insecure-registry 10.111.222.35:5000 consul 和 registry 服务所指向的节点 10.111.222.35 已经因为异常而下线,而 docker 服务在启动后不断的尝试连接到该节点的服务上。 尝试修正上述节点带来的影响后,重启服务。 [root@n36 ~]# systemctl daemon-reload [root@n36 ~]# systemctl restart docker 再次执行 docker 指令,无异常。 ZYXW、参考 1、consul https://hub.docker.com/r/progrium/consul/ https://blog.coding.net/blog/intro-consul?type=hot http://blog.csdn.net/viewcode/article/details/45915179 2、registrator http://gliderlabs.com/registrator/latest/user/run/ 3、consul-template https://github.com/hashicorp/consul-template https://releases.hashicorp.com/consul-template/ https://jlordiales.me/2015/04/01/consul-template/ http://sirile.github.io/2015/07/28/scaling-with-discovery-on-docker-swarm-with-consul-registrator-and-haproxy-with-prometheus-monitoring-and-elk-log-aggregation.html 4、haproxy http://serverfault.com/questions/654599/weird-interaction-with-systemctl-with-haproxy-on-centos-7