Consul系列:实战演练

实战演练

可以解决什么样的线上问题?

  • 问题A:在线服迁移、需要修改配置文件并重启服务生效。

  • 方案A:可直接使用consul服务自动注册+域名发现功能,使用内部域名替代ip,dns解析动态实时生效,维护不需要做任何变更。

  • 问题B:HA等服务在rs地址增删改后需要修改配置文件并重启服务,增加操作环节,生效时间长。

  • 方案B: 使用consul的服务自动注册发现+配置文件动态化管理,实现配置文件根据注册的服务自行调整,并进行例如重启服务等可执行操作,动态实时自动化 的运维管理。

  • 问题C:业务故障,需要手动处理。

  • 方案C: consul自带健康检查(check)及信息监控(watch)功能,可实现服务异常时做故障自愈及更多的自动化流程。

总结:consul除了上面列出的几个以外,例如监控、故障自愈、服务自动切换等等运维自动化都是可以实现的方向。

注册服务

域名服务相关依赖及部署

consul的DNS功能只支持了其内部的注册及解析,要想其他外部服务也可使用,需要将其作为一个本地dns代理使用,这样既可以不影响正常的dns解析,也可以访问 consul的dns解析。

Dnsmasq Setup

  • /etc/dnsmasq.d/10-consul
# Enable forward lookup of the 'consul' domain: 
 server=/consul/127.0.0.1#8600 
 #这里根据实际情况设置为你的本地consul DNS地址.
 
 /# Uncomment and modify as appropriate to enable reverse DNS lookups for 
 # common netblocks found in RFC 1918, 5735, and 6598: 
 #rev-server=0.0.0.0/8,127.0.0.1#8600 
 #rev-server=10.0.0.0/8,127.0.0.1#8600 
 #rev-server=100.64.0.0/10,127.0.0.1#8600 
 #rev-server=127.0.0.1/8,127.0.0.1#8600 
 #rev-server=169.254.0.0/16,127.0.0.1#8600 
 #rev-server=172.16.0.0/12,127.0.0.1#8600 
 #rev-server=192.168.0.0/16,127.0.0.1#8600 
 #rev-server=224.0.0.0/4,127.0.0.1#8600 
 #rev-server=240.0.0.0/4,127.0.0.1#8600
  • /etc/resolv.conf
# THIS FILE IS AUTOMATICALLY GENERATED BY PUPPET. 
 # DO NOT EDIT THIS FILE.
 
 domain i.example.net 
 nameserver 127.0.0.1 
 nameserver 42.186.69.116 
 nameserver 42.186.72.87

Testing

  • 直接向consul查询其中的一个服务域名是否已经存在。
root@localhost:~/consul/conf$ dig @localhost -p 8600 web.service.consul. A

; <<>> DiG 9.9.5-9+deb8u14-Debian <<>> @localhost -p 8600 web.service.consul. A ; (1 server found)
;; global options: +cmd
;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41515
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096 
;; QUESTION SECTION: ;web.service.consul. INA

;; ANSWER SECTION: 
web.service.consul. 0  IN A 10.120.184.243
web.service.consul. 0  IN A 10.120.184.216

;;  Query time: 1 msec
;;  SERVER: 127.0.0.1#8600(127.0.0.1)
;;  WHEN: Tue Aug 07 14:47:14 CST 2018
;;  MSG SIZE rcvd: 79
  • 使用默认的dns接口查询该服务域名,是否可以正常解析。
root@localhost:~/consul/conf$  dig @localhost -p 53 web.service.consul. A

; <<>> DiG 9.9.5-9+deb8u14-Debian <<>> @localhost -p 53 web.service.consul. A 
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58951
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096 
;; QUESTION SECTION: 
;web.service.consul. INA

;; ANSWER SECTION: 
web.service.consul. 0 IN A 10.120.184.243
web.service.consul. 0 IN A 10.120.184.216

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Aug 07 14:48:29 CST 2018 
;; MSG SIZE rcvd: 79

其他平台域名相关部署访问详见官网

域名服务自动注册测试

自定义check

root@localhost:~/consul/conf$  cat http.json 
{
    "service": {

        "name": "web",
        "tags": ["test web site"],
        "port": 8099,
        "check": {

            "id": "web",
            "name": "web on port 8099",
            "tcp": "localhost:8099",
            "interval": "10s",
            "timeout": "1s"
        }
    }
}

重载

consul reload

域名切换服务测试访问情况

多台agent节点开启一个web端口,并注册服务(有端口健康检查)。

模拟其中一个服务变更为另外一个域名并更新注册服务后,全部请求都到了其他可用节点。

root@localhost:~# watch "curl -s web.service.consul:8099/a"

image.png

image.png

模拟其中一个服务挂掉,会立即被server踢掉故障节点,请求到了另外一个可用节点。

image.png

image.png

配置文件动态管理

服务注册

#刷新注册服务信息
 consul reload --http-addr=10.120.169.72:8500

/#服务注册json简单样例 
root@localhost:~/consul/conf$ cat test.json 
{
    "service": {
        "name": "test",
        "tags": ["test service"],
        "port": 31030,
        "address": "10.120.169.723",
        "id": "test",
        "check": {
            "id": "api",
            "http": "http://123.58.169.72:31030",
            "interval": "3s"
        }
    }
}

watch 监控项配置

  • 方法一:命令行后台执行
consul watch -type=service -service=g10 -http-addr=10.120.169.72:8500 /home/push/consulbin/test.py
  • 方法二:配置文件加载。
root@localhost:~/consul/conf$ cat watch.json
{
    "watches": [{
        "type": "service",
        "service": "g10",
        "handler_type": "script",
        "args": ["python", "/home/push/consul/bin/watch.py"]
    }]
}

telmplate配置文件动态管理

  • 方法一:命令行操作
consul-template -consul-addr 127.0.0.1:8500 -template "/home/test/ha_test.ctmpl:/home/test/ha_test.conf:echo 'test'>a.lo g" -once
  • 方法二:嵌入watch结合使用.
#监控服务,自动生成ctmpl模版,并触发consul-template实现动态模版管理. 
root@localhost:~/consul/bin$ cat watch.py 
#!/usr/bin/python
#coding:utf8
import sys 
import json 
import os

a=json.loads(raw_input()) 
for k in a:
    for key in k: 
        print key
        print k[key]
        if key == "Service":
            print k[key]["Service"]
            print k[key]["Port"]
            print k[key]["Address"]
            log_format="log-format %si:%sp/ %ci/ %ft/ %hrl/ %r/ %ST/ %B/ %Tt" 
            ctmpl_content = """
global 
    daemon
    maxconn 30000 
    pidfile /home/push/var/run/haproxy/pid/%s_uq.pid
    stats socket /home/push/var/run/haproxy/sock/%s_uq.sock mode 644 
    log /dev/log local7 info

defaults
    mode http
    log global
    option httpclose 
    maxconn 30000 
    timeout connect 300s 
    timeout client 300s 
    timeout server 300s 
    balance roundrobin
listen {{.Name}} 
    option httplog 
    fullconn 30000
    bind *:30010
    %s
{{range service /"%s/"}}
    server {{.Name}}-uniqush {{.Address}}:{{.Port}} maxconn 30000 check inter 2000 addr {{.Address}} port {{.Port}}{{end}}"""%(k[k ey]["Service"], k[key]["Service"], log_format, k[key]["Service"])
            os.system("echo '''%s'''>>/home/push/consul/conf/%s.ctmpl"% (ctmpl_content, k[key]["Service"]))
            cmd = "/"/home/push/consul/conf/" + k[key]["Service"] + ".ctmpl:/home/push/consul/conf/" + k[key]["Service"] + ".conf" + ":echo test>a.log/"" + "-once"
            os.system("/usr/local/bin/consul-template -consul-addr 127.0.0.1:8500 -template %s &" % cmd)

template样例

{{range service "test"}} 
    {{.ID}}
    server {{.Name}}-uniqush {{.Address}}:{{.Port}} maxconn 30000 check inter 2000 addr {{.Address}} port {{.Port}}{{end}}

template语法

datacenters:在consul目录中查询所有的datacenters,{{datacenters}}

file:读取并输出本地磁盘上的文件,如果无法读取,则报错,{{file "/path/to/local/file"}} key:查询consul中该key的值,如果无法转换成一个类字符串的值,则会报错,{{key "service/redis/maxconns@east-aws"}} east-aws指定的是数据中心,{{key "service/redis/maxconns"}}

key_or_default:查询consul中该key的值,如果key不存在,则使用指定的值代替,{{key_or_default "service/redis/maxconns@east-aws" "5"}} 

ls:在consul中查询给定前缀的key的顶级域值,{{range ls "service/redis@east-aws"}} {{.Key}} {{.Value}}{{end}} 

node:查询consul目录中的单个node,如果不指定node,则是当前agent的,{{node "node1"}} 

nodes:查询consul目录中的所有nodes,你也可以指定datacenter,{{nodes "@east-aws"}}

service:查询consul中匹配的service组,{{service "release.web@east-aws"}}或者{{service "web"}},也可以返回一组HealthService服务{{range ser vice "web@datacenter"}} server {{.Name}} {{.Address}}:{{.Port}}{{end}},默认值返回健康的服务,如果你想返回所有服务,则{{service "web" "any "}}

services:查询consul目录中的所有services,{{services}},也可以指定datacenter:{{services "@east-aws"}} 

tree:查询consul中给定前缀的所有K/V值,{{range tree "service/redis@east-aws"}} {{.Key}} {{.Value}}{{end}}

精细化的权限控制(ACL)

首先我们需要在leader节点上去请求获取一个Bootstrap Token,用这个token为基础生成management token配置给给其他节点,开启ACl功能。

请求:curl --request PUT http://127.0.0.1:8500/v1/acl/bootstrap

返回:{"ID":"5616a0e6-19df-0d47-8250-fe6d1d58c8fc"}

ACL配置

  • 首先在所有的server节点增加acl配置(需要注意的是,所有的server都需要配置并重启consule生效。例如只配置单个server,会无效)
#server节点增加一个json结尾的acl文件 
root@localhost:~/consul/conf$ cat acl_consul.json 
{
    "acl_master_token": "5616a0e6-19df-0d47-8250-fe6d1d58c8fc",#自定义一个token, 无太多要求 
    "acl_datacenter": "dc1",    #需要做acl的数据中心 
    "acl_default_policy": "deny",   #开启acl, 默认都被deny 
    "acl_down_policy": "deny"#  在无法从acl_datacenter 或 leader 节点读取 token 的策略的情况下, 应用向下策略, deny 限制所有操作。
}
  • 重启所有的consul server将配置生效。

  • 查看,会发现所有的server节点的ui等权限都已经被deny。

image.png
  • 获取一个初始的agent token(这里我基本给了所有权限)
请求: curl -H "X-Consul-Token: secret" -X PUT -d '{"Name": "dc1", "Type": "management"}' http://127.0.0.1:8500/v1/acl/create?token =5616a0e6-19df-0d47-8250-fe6d1d58c8fc

返回(不同节点返回的会不一样):{"ID":"df9aec62-96c3-4cb6-3f38-899d79e24112"}

获取agent token后进行acl权限(acl_token对应不同权限)配置,并重启所有配置过的consule服务,将修改生效。

root@localhost:~/consul/conf$ cat acl_consul.json 
{
    "acl_master_token":"d9f1928e-1f84-407c-ab50-9579de563df5", "acl_datacenter":"dc1",
    "acl_default_policy":"deny",
    "acl_down_policy":"deny", "acl_token":"df9aec62-96c3-4cb6-3f38-899d79e24112"
}
  • 查看,初始的acl策略,通过配置文件配置生成获取。
image.png
  • 通过bootstrap获取的acl token。
image.png

ACL策略控制

  • 创建一个新的acl控制,期望完成自己期望的一些权限控制。
image.png
  • 新建后会提供一个对应权限的token值,将该值配置到对应的consul节点的acl token参数,重启consul服务,即可实现自定义的权限控制。
#更新配置文件token参数值,如下client角色其中一个节点配置 
root@localhost:~/consul/conf$ cat /home/test/consul/conf/acl_consul.json 
{
    "acl_datacenter":"dc1",
    "acl_token":"ab351531-84d5-7286-515e-2731ee4a66f5"
}

测试

  • 测试1:根据之前的acl权限设置,符合acl的控制,只允许读,不允许写入。
root@localhost:~/consul/conf$ curl -X PUT -d 'test' http://10.170.17.28:8500/v1/kv/web
rpc error making call: rpc error making call: Permission denied 

root@localhost:~/consul/conf$ curl -X GET -d 'test' http://10.170.17.28:8500/v1/kv/web
[{"LockIndex":0,"Key":"web","Flags":0,"Value":"dGVzdA==","CreateIndex":96048,"ModifyIndex":96234}] 
  • 测试2:修改权限允许读写,立即生效。
image.png
#立即生效。
root@localhost:~/consul/conf$ curl -X PUT -d 'test' http://10.170.17.28:8500/v1/kv/web 
true
  • 测试3:限定某个token的权限的某个service不可访问,DNS都无法解析。
image.png

image.png

ACL权限恢复

发现UI等因为token无法访问时,可以通过acl默认token设置来恢复访问。

image.png

多数据中心实现

  • 加入其他数据中心。
#可命令行等指定另外数据中心的一个server节点。 
consul join -wan 其他数据中心的server节点

#也可以配置文件
retry_join_wan":[ "dc2-server-1", ... "dc2-server-N" ]
image.png
  • 命令行参数
image.png

脏数据数据清理

根据service状态查询

判断servicesf是否是passing状态。返回[],则是failing,非空即为passing状态。

#service
cur http://127.0.0.1:8500/v1/health/service/服务名?passing 

#node
cur http://127.0.0.1:8500/v1/health/node/节点名?passing 

Removing Servers

  • 服务实例只能在注册的Agent上进行注销!
curl -X PUT http://server_ip:8500/v1/agent/service/deregister/服务名
image.png
  • 删除的方式可以是如上的api方式,也可以是删除json文件,并重载的方式即可。

Removing Nodes

  • In general, if you are ever adding and removing nodes simultaneously, it is better to first add the new nodes and then remove the old nodes.

  • 尝试过api删除无效、但是在新的节点进行替换node名是可行的,需要重启consul服务重新注册到servers生效。

auto removing servies

  • crontab + shell
#/usr/bin/python 
 #coding:utf-8
 
 import requests 
 import json 
 import sys 
 import time 
 import gpost
 
 check_url = "http://127.0.0.1:8500/v1/agent/services"
 
 result = json.loads(requests.get(check_url).content)
 
 def msg_send(msg): 
  msg = msg
  gpost.blackhole(data={'type':'push_consul_check'},msg=msg) 
 
 def check_galaxy(groupCode):
  .......
 
 for ServerName in result.keys(): 
  try:
  #查询本节点上点所有service,如果是failing状态,则值为[]。
  services_info = requests.get("http://127.0.0.1:8500/v1/health/service/%s?passing"%ServerName).content 
  if services_info == "[]":
  msg = "Service %s will be delete after 8h."%ServerName 
  #从galaxy查询该服务是否真的已下线,否者进行delete操作 
  check_galaxy(ServerName)
  msg_send(msg)
  time.sleep(28800)
  delete_url = "http://127.0.0.1:8500/v1/agent/service/deregister/%s"%ServerName 
  delete_cmd=requests.put(delete_url)
  if delete_cmd.status_code == 200:
  msg = " %s deletc ok."%ServerName
  msg_send(msg) 
  else:
  msg = "Service %s delete fail,please check!" 
  msg_send(msg)
  sys.exit(1)
  except Exception, e: 
  gpost.blackhole(data={'type':'push_consul_check'},msg=e)

更多文章:
Consul系列:让服务Running in anywhere
Consul系列:业务系统微服务化实践
Consul系列:基于Consul的自动化应用实践
Consul系列:实战演练
Consul系列:什么是Consul?
Consul系列:Consul实现详解
Consul系列:Consul Server部署及用法介绍
Consul系列:Consul Agent部署
Consul系列:Consul Agent用法介绍(一)
Consul系列:Consul Agent用法介绍(二)
Consul系列:Consul Agent用法介绍(三)
Consul系列:Consul Agent用法介绍(四)
Consul系列:Consul Agent用法介绍(五)
Consul系列:Consul API用法介绍
Consul系列:Consul Registrator介绍
Consul系列:Consul Connect介绍
Consul系列:Consul集群运维指引
Consul系列:Consul监控介绍
Consul系列:模版渲染与ACL控制

版权声明:
作者:玉兰
链接:https://www.techfm.club/p/50124.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>