概述

官方网站https://www.consul.io/

架构

Consul - 图1

https://technologyconversations.files.wordpress.com/2015/09/etcd-registrator-confd2.png
通过这张架构图,可以看出来使用Consul实现应用外服务注册和发现主要依靠三个重要的组件:

  • Consul:注册中心的服务端,实现服务注册信息的存储,并提供注册和发现服务。
  • Registrator:一个开源的第三方服务管理器项目,它通过监听服务部署的Docker实例是否存活,来负责服务提供者的注册和销毁。
  • Consul Template:定时从注册中心服务端获取最新的服务提供者节点列表并刷新LB配置(比如Nginx的upstream),这样服务消费者就通过访问Nginx就可以获取最新的服务提供者信息。

    功能

  • 服务发现 /service discovery:通过 DNS 或 HTTP 的方式获取服务信息。

  • 健康检查/health checking:可以提供与给定服务相关联的任何数量的健康检查。防止服务转发到故障的服务上面
  • 键值对存储 /key/value storage:存储动态配置。
  • 多数据中心 multi-datacenter:无需复杂的配置,即可支持任意数量的区域。

    优势:

  • 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft。

  • 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。
  • 支持健康检查。 etcd 不提供此功能。
  • 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。
  • 官方提供 web 管理界面, etcd 无此功能。

    角色

    图片.png
    consu主要有server和client两种组件组成。每个数据中心官方建议需要3或5个server节点以保证数据安全,server只有一个实例是leader实例,就是主节点,主节点是自动选举产生的,主节点负责处理数据的写入处理,同时将数据同步至其他server节点。
    client负责跟server通信,处理转发服务注册、服务发现请求到server节点,client还负责服务的健康检查,client节点也可以部署多个实例,甚至每个微服务节点都部署一个client实例。

    工作原理

    image.png

  • 1、当 Producer 启动的时候,会向 Consul 发送一个 post 请求,告诉 Consul 自己的 IP 和 Port

  • 2、Consul 接收到 Producer 的注册后,每隔10s(默认)会向 Producer 发送一个健康检查的请求,检验Producer是否健康
  • 3、当 Consumer 发送 GET 方式请求 /api/address 到 Producer 时,会先从 Consul 中拿到一个存储服务 IP 和 Port 的临时表,从表中拿到 Producer 的 IP 和 Port 后再发送 GET 方式请求 /api/address
  • 4、该临时表每隔10s会更新,只包含有通过了健康检查的 Producer

    安装

    二进制安装

    下载地址https://www.consul.io/downloads.html
    image.png
    根据安装主机的系统版本和位数选择安装
    1. # wget https://releases.hashicorp.com/consul/1.6.1/consul_1.6.1_linux_amd64.zip
    2. # apt install unzip//没有unzip
    3. # unzip consul_1.6.1_linux_amd64.zip
    4. # cp ./consul /usr/local/bin/

查看安装版本

  1. # consul version
  2. Consul v1.6.1
  3. Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

docker安装

  1. $ sudo docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul agent -server -bootstrap-expect 2 -ui -bind=0.0.0.0 -client=0.0.0.0

查看第一个server节点的ip地址(注意:这种方式下容器重启后ip可能会发生改变)

  1. $ sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' consul1
  2. 172.18.0.2

启动第二

  1. $ sudo docker run --name consul2 -d -p 8501:8500 consul agent -server -bind=0.0.0.0 -client=0.0.0.0 -join 172.18.0.2
  2. db205eceabe9b5c6fc58c276d435ff2fa7d1cdcc2a59a5a27dd5ea6ccc35f92d

启动三

  1. $ sudo docker run --name consul3 -d -p 8502:8500 consul agent -server -bind=0.0.0.0 -client=0.0.0.0 -join 172.18.0.2
  2. 562f8530c242468cdfc4968057b0f11e85ae63f18e24ed8ba4e9e87d71499e71

指定 data 数据的创建方式

  1. docker run -d --name consul-server1 --restart=always -v /home/docker/consul/consul-server1-data:/consul/data -v /home/docker/consul/consul-server1-conf:/consul/config consul agent -data-dir /consul/data -config-dir /consul/config
  2. docker run -d --name consul-server2 --restart=always -v /home/docker/consul/consul-server2-data:/consul/data -v /home/docker/consul/consul-server2-conf:/consul/config consul agent -data-dir /consul/data -config-dir /consul/config
  3. docker run -d --name consul-server3 --restart=always -v /home/docker/consul/consul-server3-data:/consul/data -v /home/docker/consul/consul-server3-conf:/consul/config consul agent -data-dir /consul/data -config-dir /consul/config
  4. docker run -d --net=host --name consul-client --restart=always -p 8400:8400 -p 8500:8500 -p 8600:53/udp -v /home/docker/consul/consul-client-data:/consul/data -v /home/docker/consul/consul-client-conf:/consul/config consul agent -data-dir /consul/data -config-dir /consul/config

配置参数

官方参数说明地址:https://www.consul.io/docs/agent/options.html#command-line-options

  1. -server:定义agent运行在server模式,每个数据中心的Server建议在3~5个避免失败情况下数据的丢失
  2. -client:定义agent运行在client模式
  3. bootstrap-expect:server模式下,集群要求的最低数量,当低于这个数量,集群失效
  4. -bootstrap-expect:在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群
  5. -bind:节点的ip地址一般是0.0.0.0或云服务内网地址,用于被集群中的其他节点所访问
  6. -node:指定节点在集群中的唯一名称,默认为机器的hostname
  7. -config-dir:配置文件目录,里面所有以.json结尾的文件都会被加载
  8. data-dir:data存放的目录,consul数据同步机制,(该目录必须已存在)
  9. -serf-lan-bind绑定地址,用于内网集群通信,缺省使用 -bind 地址
  10. -serf-wan-bind绑定地址,用于跨机房通信,缺省使用 -bind 地址
  11. -advertise通告地址,通告给集群中其他节点,缺省使用 -bind 地址
  12. -advertise-wan通告地址,通告给其他机房的服务节点,缺省使用 -advertise 地址
  13. -join -retry-join加入集群的目标地址
  14. -join-wan -retry-join-wan跨机房邦联的目标地址
  15. -recursor上游DNS地址

开发模式

执行下面命令,启动开发模式,开发模式会快速启动一个单节点的Consul。但是需要注意的是开发模式不能数据持久化,因此,不能用于生产环境

  1. # consul agent -dev
  2. ==> Starting Consul agent...
  3. Version: 'v1.6.1'
  4. Node ID: '698f72ee-40fb-6676-18be-19ef509f4bdd'
  5. Node name: 'iZhp3f2wn461rak5gw97qmZ'
  6. Datacenter: 'dc1' (Segment: '<all>')
  7. Server: true (Bootstrap: false)
  8. Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
  9. Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
  10. Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
  • Node name:代理的唯一名称,默认是机器的hostname,可以通过-node标志自定义,例如:consul agent -dev -node myNode
  • Datacenter:数据中心,Consul支持多个数据中心,为了有效的工作,每个节点必须被配置且上报到数据中心,-datacenter标志用来设置数据中心,对于单一的DC配置,这个代理默认为dc1
  • Server:表示代理是以服务器还是客户端的模式来运行。
  • Client Addr:用于代理的客户端接口地址。
  • Cluster Addr:用于集群中的Consul代理之间通信的地址和端口集,改地址必须可供其它节点访问。

    集群搭建

    创建第一台设备
    consul agent -server -bootstrap-expect 1 -data-dir /data/consul -node=n1 -bind=0.0.0.0 -ui -config-dir /etc/consul.d -client 0.0.0.0 ```go

    consul agent -server -bootstrap-expect 1 -data-dir /data/consul -node=n1 -bind=0.0.0.0 -ui -config-dir /etc/consul.d -client 0.0.0.0

    BootstrapExpect is set to 1; this is the same as Bootstrap mode. bootstrap = true: do not enable unless necessary ==> Starting Consul agent…
    1. Version: 'v1.6.1'
    2. Node ID: '6ca0b149-a98c-d316-e7a3-85350ab7ca96'
    3. Node name: 'n1'
    4. Datacenter: 'dc1' (Segment: '<all>')
    5. Server: true (Bootstrap: true)
    6. Client Addr: [0.0.0.0] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600)
    7. Cluster Addr: 172.21.16.7 (LAN: 8301, WAN: 8302)
    8. Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false

==> Log data will now stream in as it occurs:

  1. 2019/09/18 22:24:52 [INFO] raft: Initial configuration (index=56): [{Suffrage:Voter ID:6ca0b149-a98c-d316-e7a3-85350ab7ca96 Address:172.21.16.7:8300}]
  2. 2019/09/18 22:24:52 [INFO] serf: EventMemberJoin: n1.dc1 172.21.16.7
  3. 2019/09/18 22:24:52 [INFO] serf: EventMemberJoin: n1 172.21.16.7
  4. 2019/09/18 22:24:52 [INFO] agent: Started DNS server 0.0.0.0:8600 (udp)
  5. 2019/09/18 22:24:52 [INFO] raft: Node at 172.21.16.7:8300 [Follower] entering Follower state (Leader: "")
  6. 2019/09/18 22:24:52 [WARN] serf: Failed to re-join any previously known node
  7. 2019/09/18 22:24:52 [WARN] serf: Failed to re-join any previously known node
  8. 2019/09/18 22:24:52 [INFO] consul: Adding LAN server n1 (Addr: tcp/172.21.16.7:8300) (DC: dc1)
  9. 2019/09/18 22:24:52 [INFO] consul: Handled member-join event for server "n1.dc1" in area "wan"
  10. 2019/09/18 22:24:52 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp)
  11. 2019/09/18 22:24:52 [INFO] agent: Started HTTP server on [::]:8500 (tcp)
  12. 2019/09/18 22:24:52 [INFO] agent: started state syncer

==> Consul agent running! 2019/09/18 22:24:59 [ERR] agent: failed to sync remote state: No cluster leader 2019/09/18 22:25:01 [WARN] raft: Heartbeat timeout from “” reached, starting election 2019/09/18 22:25:01 [INFO] raft: Node at 172.21.16.7:8300 [Candidate] entering Candidate state in term 7 2019/09/18 22:25:01 [INFO] raft: Election won. Tally: 1 2019/09/18 22:25:01 [INFO] raft: Node at 172.21.16.7:8300 [Leader] entering Leader state 2019/09/18 22:25:01 [INFO] consul: cluster leadership acquired 2019/09/18 22:25:01 [INFO] consul: New leader elected: n1 2019/09/18 22:25:03 [INFO] agent: Synced node info

  1. 加入机器
  2. 创建数据和配置目录
  3. ```shell
  4. $ sudo mkdir -p /data/consul
  5. $ sudo mkdir -p /etc/consul.d

前台启动

  1. consul agent -server -bootstrap -ui -data-dir=/data/soft/consul_1.4/consul-data -bind=0.0.0.0 -client=0.0.0.0 -node=120.27.239.212
  2. consul agent -server -bind=192.168.xxx.134 -client=0.0.0.0 -bootstrap-expect=1 -data-dir=/usr/data/consul_data -node=server1

后台启动

  1. nohup consul agent -server -bind=192.168.xxx.134 -client=0.0.0.0 -bootstrap-expect=1 -data-dir=/usr/data/consul_data -node=server1 > /dev/null 2>&1 &

多数据中心搭建

关键在于要在每个数据中心选择一个边界节点,并配好-advertise-wan=参数,
再执行consul join -wan $other_wlan_ip

  1. -node 为节点取名
  2. -bind 绑定的IP
  3. -advertise-wan 通告自己的IP(外网IP),
  4. consul agent -server -bootstrap-expect 1 -node=qcloud -bind=10.0.1.86 -advertise-wan=10.0.1.86 -data-dir /tmp
  5. consul agent -server -bootstrap-expect 1 -node=aliyun -bind=10.0.1.87 -advertise-wan=10.0.1.87 -data-dir /tmp
  6. consul agent -server -bootstrap-expect 1 -node=aws -bind=10.0.1.88 -advertise-wan=10.0.1.88 -data-dir /tmp

docker-compose

创建 vim docker-compose.yaml

  1. version: '3'
  2. networks:
  3. consul_net:
  4. services:
  5. consul1:
  6. image: consul:latest
  7. container_name: consul1
  8. restart: always
  9. networks:
  10. - consul_net
  11. command: agent -server -client=0.0.0.0 -bootstrap-expect=3 -node=consul1
  12. consul2:
  13. image: consul:latest
  14. container_name: consul2
  15. networks:
  16. - consul_net
  17. restart: always
  18. command: agent -server -client=0.0.0.0 -retry-join=consul1 -node=consul2
  19. consul3:
  20. image: consul:latest
  21. container_name: consul3
  22. networks:
  23. - consul_net
  24. restart: always
  25. command: agent -server -client=0.0.0.0 -retry-join=consul1 -node=consul3
  26. consul4:
  27. image: consul:latest
  28. container_name: consul4
  29. networks:
  30. - consul_net
  31. restart: always
  32. ports:
  33. - 8500:8500
  34. command: agent -client=0.0.0.0 -retry-join=consul1 -ui -node=client1

执行命令 启动命令

  1. docker-compose -f docker-compose.yaml up -d

查看结果

  1. # docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. c8c8c9d6c1d2 consul:latest "docker-entrypoint.s…" 53 seconds ago Up 50 seconds 8300-8302/tcp, 8301-8302/udp, 8600/tcp, 8600/udp, 0.0.0.0:8500->8500/tcp consul4
  4. 69d2bfd8205f consul:latest "docker-entrypoint.s…" 53 seconds ago Up 49 seconds 8300-8302/tcp, 8500/tcp, 8301-8302/udp, 8600/tcp, 8600/udp consul1
  5. c554365d219f consul:latest "docker-entrypoint.s…" 53 seconds ago Up 51 seconds 8300-8302/tcp, 8500/tcp, 8301-8302/udp, 8600/tcp, 8600/udp consul2
  6. d01718f626f7 consul:latest "docker-entrypoint.s…" 53 seconds ago Up 51 seconds 8300-8302/tcp, 8500/tcp, 8301-8302/udp, 8600/tcp, 8600/udp consul3

操作命令

查看命令

  1. consul
  2. Usage: consul [--version] [--help] <command> [<args>]
  3. Available commands are:
  4. acl Interact with Consul's ACLs
  5. agent Runs a Consul agent
  6. catalog Interact with the catalog
  7. config Interact with Consul's Centralized Configurations
  8. connect Interact with Consul Connect
  9. debug Records a debugging archive for operators
  10. event Fire a new event
  11. exec Executes a command on Consul nodes
  12. force-leave Forces a member of the cluster to enter the "left" state
  13. info Provides debugging information for operators.
  14. intention Interact with Connect service intentions
  15. join Tell Consul agent to join cluster
  16. keygen Generates a new encryption key
  17. keyring Manages gossip layer encryption keys
  18. kv Interact with the key-value store
  19. leave Gracefully leaves the Consul cluster and shuts down
  20. lock Execute a command holding a lock
  21. login Login to Consul using an auth method
  22. logout Destroy a Consul token created with login
  23. maint Controls node or service maintenance mode
  24. members Lists the members of a Consul cluster
  25. monitor Stream logs from a Consul agent
  26. operator Provides cluster-level tools for Consul operators
  27. reload Triggers the agent to reload configuration files
  28. rtt Estimates network round trip time between nodes
  29. services Interact with services
  30. snapshot Saves, restores and inspects snapshots of Consul server state
  31. tls Builtin helpers for creating CAs and certificates
  32. validate Validate config files/directories
  33. version Prints the Consul version
  34. watch Watch for changes in Consul

在consul命令中,无论server还是client都叫做agent,通过命令参数区分,我们运行的是server还是client。

集群成员(Members)

  1. # consul members
  2. Node Address Status Type Build Protocol DC Segment
  3. iZhp3f2wn461rak5gw97qmZ 127.0.0.1:8301 alive server 1.6.1 2 dc1 <all>

通过http方式查看

  1. # curl localhost:8500/v1/catalog/nodes
  2. [
  3. {
  4. "ID": "a3343a5f-5290-4b53-1bdf-6b17c8ced3ac",
  5. "Node": "JD",
  6. "Address": "127.0.0.1",
  7. "Datacenter": "dc1",
  8. "TaggedAddresses": {
  9. "lan": "127.0.0.1",
  10. "lan_ipv4": "127.0.0.1",
  11. "wan": "127.0.0.1",
  12. "wan_ipv4": "127.0.0.1"
  13. },
  14. "Meta": {
  15. "consul-network-segment": ""
  16. },
  17. "CreateIndex": 10,
  18. "ModifyIndex": 11
  19. }
  20. ]

通过DNS 查看

  1. # dig @127.0.0.1 -p 8600 JD.node.consul
  2. ; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 8600 JD.node.consul
  3. ; (1 server found)
  4. ;; global options: +cmd
  5. ;; Got answer:
  6. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35600
  7. ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
  8. ;; WARNING: recursion requested but not available
  9. ;; OPT PSEUDOSECTION:
  10. ; EDNS: version: 0, flags:; udp: 4096
  11. ;; QUESTION SECTION:
  12. ;JD.node.consul. IN A
  13. ;; ANSWER SECTION:
  14. JD.node.consul. 0 IN A 127.0.0.1
  15. ;; ADDITIONAL SECTION:
  16. JD.node.consul. 0 IN TXT "consul-network-segment="
  17. ;; Query time: 0 msec
  18. ;; SERVER: 127.0.0.1#8600(127.0.0.1)
  19. ;; WHEN: Fri Mar 20 14:22:00 CST 2020
  20. ;; MSG SIZE rcvd: 95

停止服务

  1. $ consul leave
  2. Graceful leave complete

历史日志

consul monitor显示最近历史日志,默认显示的日志级别为info可以根据-log-level进行设置

  • -log-level: debug,还有"debug","info", "warn", "error"

服务注册

创建目录,默认推荐目录文件名称是consul.d

  1. # mkdir /etc/consul.d
  2. cd /etc/consul.d

注册服务

  1. /etc/consul.d# echo '{"service":
  2. > {"name": "web",
  3. > "tags": ["rails"],
  4. > "port": 80
  5. > }
  6. > }' > ./consul.d/web.json
  7. -bash: ./consul.d/web.json: No such file or directory
  8. root@JD:/etc/consul.d# echo '{"service":
  9. {"name": "web",
  10. "tags": ["rails"],
  11. "port": 80
  12. }
  13. }' > web.json

在配置中启用脚本检查可能会引入远程执行漏洞,这是已知的恶意软件的目标。在生产环境中,我们强烈建议使用-enable-local-script-check。重新启动服务

  1. # consul agent -dev -enable-script-checks -config-dir=/etc/consul.d

通过dns 查看服务

  1. # dig @127.0.0.1 -p 8600 web.service.consul
  2. ; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 8600 web.service.consul
  3. ; (1 server found)
  4. ;; global options: +cmd
  5. ;; Got answer:
  6. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31116
  7. ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
  8. ;; WARNING: recursion requested but not available
  9. ;; OPT PSEUDOSECTION:
  10. ; EDNS: version: 0, flags:; udp: 4096
  11. ;; QUESTION SECTION:
  12. ;web.service.consul. IN A
  13. ;; ANSWER SECTION:
  14. web.service.consul. 0 IN A 127.0.0.1
  15. ;; Query time: 0 msec
  16. ;; SERVER: 127.0.0.1#8600(127.0.0.1)
  17. ;; WHEN: Fri Mar 20 14:37:46 CST 2020
  18. ;; MSG SIZE rcvd: 63

http 查看服务

  1. $ curl http://localhost:8500/v1/catalog/service/web

查看所有可用的服务

  1. curl 'http://localhost:8500/v1/health/service/web?passing'

重新刷新注册信息

  1. $ consul reload
  2. Configuration reload triggered

查看新服务

  1. # dig @127.0.0.1 -p 8600 web.service.consul
  2. ; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 8600 web.service.consul
  3. ; (1 server found)
  4. ;; global options: +cmd
  5. ;; Got answer:
  6. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20451
  7. ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
  8. ;; WARNING: recursion requested but not available
  9. ;; OPT PSEUDOSECTION:
  10. ; EDNS: version: 0, flags:; udp: 4096
  11. ;; QUESTION SECTION:
  12. ;web.service.consul. IN A
  13. ;; ANSWER SECTION:
  14. web.service.consul. 0 IN A 127.0.0.1
  15. ;; Query time: 0 msec
  16. ;; SERVER: 127.0.0.1#8600(127.0.0.1)
  17. ;; WHEN: Fri Mar 20 14:47:50 CST 2020
  18. ;; MSG SIZE rcvd: 63

数据存储

存储

  1. $ consul kv put redis/config/minconns 1
  2. Success! Data written to: redis/config/minconns
  3. $ consul kv put redis/config/maxconns 25
  4. Success! Data written to: redis/config/maxconns
  5. $ consul kv put -flags=42 redis/config/users/admin abcd1234
  6. Success! Data written to: redis/config/users/admin

获取数据

  1. # consul kv get -detailed redis/config/users/admin
  2. CreateIndex 164
  3. Flags 42
  4. Key redis/config/users/admin
  5. LockIndex 0
  6. ModifyIndex 164
  7. Session -
  8. Value abcd1234

获取所有的数据

  1. # consul kv get -recurse
  2. redis/config/maxconns:25
  3. redis/config/minconns:1
  4. redis/config/users/admin:abcd1234

删除数据

  1. # consul kv delete redis/config/minconns
  2. Success! Deleted key: redis/config/minconns

删除所有已redis前缀的数据

  1. # consul kv delete -recurse redis
  2. Success! Deleted keys with prefix: redis

修改数据

  1. # consul kv put foo bar
  2. Success! Data written to: foo
  3. # consul kv get foo
  4. bar
  5. # consul kv put foo zip
  6. Success! Data written to: foo
  7. # consul kv get foo
  8. zip

UI

http://localhost:8500/ui

参考

https://learn.hashicorp.com/consul/getting-started/install
https://www.jianshu.com/p/067154800683
consul 整合多个数据节点
https://book-consul-guide.vnzmi.com/
使用Consul做服务发现的若干姿势
http://lhyd.top/?p=139151