关于 Consul 的安装:https://www.consul.io/docs/install/index.html
关于 Consul-Template 的安装:https://github.com/hashicorp/consul-template#installation
关于 Consul 集群搭建:https://book-consul-guide.vnzmi.com/06_setup_cluster.html
Consul 的 C/S 架构,Consul Agent 安装后可以作为 Client,也可以作为 Server,所谓什么 Raft 算法的作用在于多个 Server 集群选取 master,使用的话不需要关注这些细节。
启动 Consul 测试使用两台,一台作为 Server,一台作为 Client。
在 Server 端,运行:
1 consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=s1 -bind=192.168.221.192 -ui-dir ./consul_ui/ -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0
启动过程中,可以看到如下输出:
1 2 3 4 5 6 7 2018/02/27 10:06:07 [ERR] agent: failed to sync remote state: No cluster leader 2018/02/27 10:06:08 [WARN] raft: Heartbeat timeout from "" reached, starting election 2018/02/27 10:06:08 [INFO] raft: Node at 192.168.221.192:8300 [Candidate] entering Candidate state in term 10 2018/02/27 10:06:08 [INFO] raft: Election won. Tally: 1 2018/02/27 10:06:08 [INFO] raft: Node at 192.168.221.192:8300 [Leader] entering Leader state 2018/02/27 10:06:08 [INFO] consul: cluster leadership acquired 2018/02/27 10:06:08 [INFO] consul: New leader elected: s1
开始时没有 consul leader,随后可以看到通过 raft 算法选举了 leader,在此只有一个 server 节点,所以这台 server 就成为了 leader。
在 Client 端,运行:
1 consul agent -data-dir /tmp/consul -node=c1 -bind=192.168.221.193 -config-dir=/etc/consul.d/ -join 192.168.221.192
在此需要先在 Server 端执行,因为 Client 的 -join
参数制定后找不到 Server 会报错。
执行后再 Server 端看到,已经加入了 Client。
1 2 3 4 [root@localhost ~]# consul members Node Address Status Type Build Protocol DC Segment s1 192.168.221.192:8301 alive server 1.0.6 2 dc1 <all> c1 192.168.221.193:8301 alive client 1.0.6 2 dc1 <default>
注册服务 在此我们注册三个服务,分别为两个 tomcat 和一个 nginx。
启动 consul 时,在启动命令里指定了配置文件目录为 /etc/consul.d
,所以在此目录下通过配置文件注册 service.
建立 tomcat.json
注册 tomcat 服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 { "services" : [ { "id" : "tomcat_1" , "name" : "tomcat" , "tags" : [ "primary" ] , "address" : "192.168.221.193" , "port" : 8110 , "checks" : [ { "http" : "http://192.168.221.193:8110" , "interval" : "10s" , "timeout" : "1s" , "method" : "GET" } ] } , { "id" : "tomcat_2" , "name" : "tomcat" , "tags" : [ "secondary" ] , "address" : "192.168.221.193" , "port" : 8111 , "checks" : [ { "http" : "http://192.168.221.193:8111" , "interval" : "10s" , "timeout" : "1s" , "method" : "GET" } ] } ] }
若 name 重名,则 id 必须唯一,tags 标签指定方便管理。
建立 nginx.json
注册 nginx 服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { "service" : { "id" : "nginx" , "name" : "nginx" , "tags" : [ "primary" ] , "address" : "192.168.221.193" , "port" : 80 , "checks" : [ { "http" : "http://192.168.221.193:80" , "interval" : "10s" , "timeout" : "1s" , "method" : "GET" } ] } }
定义好配置文件后来更新服务:
随后可以看到 consul 的输出显示该 Agent 将载入配置定义并注册到服务目录:
1 2 3 4 5 6 2018/02/27 12:51:53 [INFO] agent: Synced service "nginx" 2018/02/27 12:51:53 [INFO] agent: Synced service "tomcat_1" 2018/02/27 12:51:53 [INFO] agent: Synced service "tomcat_2" 2018/02/27 12:51:57 [INFO] agent: Synced check "service:nginx" 2018/02/27 12:51:59 [INFO] agent: Synced check "service:tomcat_2" 2018/02/27 12:52:02 [INFO] agent: Synced check "service:tomcat_1"
配置更新 来看目的:实时监测 tomcat 的健康状态,并实施更新 Nginx 代理配置文件。
这里需要用到 consul-template。
建立 nginx.conf.ctmpl
文件,写入模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; {{service "tomcat" "passing" }} {{$name : = .Name}} upstream {{$name }} { {{range $service}} server {{.Address }} : {{.Port }} ; {{end }} session_sticky; check interval=3000 rise=2 fall=5 timeout=1000 type=http; check_http_send "HEAD / HTTP/1.0\r\n\r\n"; check_http_expect_alive http_2xx http_3xx; } server { listen 80; server_name localhost; location / { root html; index index.html index.htm; proxy_pass http://srm; client_max_body_size 50m; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
这里只载入了 tomcat 服务,如果要把所有服务载入,可以遍历服务添加代理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... {{range services}} {{$name : = .Name}} {{$service : = service .Name}} upstream {{$name }} { {{range $service}} server {{.Address }} : {{.Port }} ; {{end }} session_sticky; check interval=3000 rise=2 fall=5 timeout=1000 type=http; check_http_send "HEAD / HTTP/1.0\r\n\r\n"; check_http_expect_alive http_2xx http_3xx; } {{end }} ... {{range services}} {{$name : = .Name}} location / {{$name }} { proxy_pass http:// {{$name }} ; } {{end }}
模板语法是 golang 的模板语法,和其它后端模板语法很像。
{{service "tomcat" "passing"}}
这部分采用的是 tomcat 服务,passing 表示只采用健康的 service。
随后执行:
1 consul-template -consul-addr 192.168.221.192:8500 -template="nginx.conf.ctmpl:/usr/local/nginx/conf/nginx.conf:/usr/local/nginx/sbin/nginx -s reload" -once
将会生成 nginx.conf
配置文件至 nginx 配置文件目录,并会执行 nginx -s reload
进行重载。
上述命令只能生成一次,官方推荐的做法是写入一个配置文件中。
建立 nginx.hcl
文件,内容如下:
1 2 3 4 5 6 7 8 9 consul { address = "192.168.221.192:8500" } template { source = "nginx.conf.ctmpl" destination = "/usr/local/nginx/conf/nginx.conf" command = "/usr/local/nginx/sbin/nginx -s reload" }
然后执行 consul-template -config nginx.hcl
,就可以运行为一个服务。
当两个 tomcat 正常时,可以看到配置文件如下:
手动把一个 tomcat 关闭,可以看到 consul 的输出中报失败:
而此时的 nginx 配置文件已经被更新,可以看到内容如下:
至此就完成了目的,注册服务 –> 服务健康检查 –> 实时更新服务配置。
后记 这个使用姿势是很奇葩的使用姿势,正确的使用姿势应该配合 DNS 查询 API 和 HTTP API 等去做更进一步的集成,在 DNS 查询层级做负载均衡和高可用的配置处理。服务的注册现在是手动注册,结合 Docker 可以使用 Registrator,不适用 Docker 就要写脚本去检测服务并注册了。
因而题为“半自动化”,这个半应该再加个半,为”半半自动化”为宜。w(゚Д゚)w
参考 -EOF-