随着微服务理论发展的成熟,越来越多互联网公司采用微服务架构来支持业务发展。各个微服务之间都需要通过注册中心来实现自动化的注册和发现。
注册中心主要有三种角色:
最后,RPC Client 从本地缓存的服务节点列表中,基于负载均衡算法选择一台 RPC Sever 发起调用。
目前常见的注册中心有Consul、ETCD、Zookeeper、Eureka、Nacos等。
Consul是HashiCorp公司推出的开源工具,Consul由Go语言开发,部署起来非常容易,只需要极少的可执行程序和配置文件,具有绿色、轻量级的特点。Consul是分布式的、高可用的、 可横向扩展的用于实现分布式系统的服务发现与配置。
Agent:是在 Consul 集群的每个成员上长期运行的守护进程,通过命令 consul agent 启动运行。由于所有节点都必须运行一个 Agent,因此 Agent 可以分为 client 或 Server。所有的 Agent 都可以运行DNS或HTTP接口,并负责运行监测和保持服务同步
Client:是将所有RPC转发到 Server 的 Agent。Client 是相对无状态的,Client 唯一执行的后台活动是加入 LAN gossip 池。这只有最小的资源开销,且只消耗少量的网络带宽
Server:是一个有一组扩展功能的 Agent,这些功能包括参与 Raft 选举、维护集群状态、响应RPC查询、与其他数据中心交互 WAN gossip 和转发查询给 leader 或远程的数据中心
Datacenter:是一个私有的、低延迟和高带宽的网络环境。这不包括通过公网的通信,但就目的而言,单个 EC2 中的多个可用区域被视为数据中心的一部分
Consensus:一致性。Consul 使用 Consensus 协议(具体由 Raft 算法实现)来提供一致性(由 CAP 定义),表明 leader 选举和事务的顺序达成一致
Gossip:Consul 使用 Gossip 协议来管理成员资格并向集群广播消息。Serf 提供了完整的 Gossip 协议,可用于多种目的,而 Consul 建立在 Serf 之上。
Gossip 涉及节点到节点的随机通信,主要是通过UDP。Gossip 协议也被称为 Epidemic 协议(流行病协议)
LAN Gossip:指包含所有位于同一局域网或数据中心的节点的 LAN gossip 池
WAN Gossip:指仅包含 Server 的 WAN gossip 池。这些 Server 主要分布在不同的数据中心,通常通过Internet或者广域网进行通信
RPC:远程过程调用。一种 请求/响应 机制,允许 Client 向 Server 发起请求
每个为Consul提供服务的节点都会运行一个Consul Agent进程。运行代理不需要发现其他服务或获取/设置密钥/值数据。Agent负责对节点上的服务以及节点本身进行健康检查。
Consul Agent 分为两种模式, Server 和 Client模式,一般部署模型是 Server + Client的模式(当然也可以纯Server), Server 具有Client的全部功能, 但是由于Server负责存储数据,并且强一致性模型的缘故, Server数是有限的(3-5个Server节点,Client可以无限扩展的)。
Agent与一个或多个Consul Server对话。Consul Server是存储和复制数据的地方。Server本身会选出一个Leader。虽然Consul可以用一台Server来运作,但建议使用3到5台,以避免故障情况导致数据丢失。建议每个数据中心采用Consul服务器集群。
Server Agent维护着一个目录(Catalog),这个目录(Catalog)是由Agent提交的信息汇总形成的。目录维护着集群的高层视图,包括哪些服务可用,哪些节点运行这些服务,健康信息等。
需要发现其他服务或节点的基础结构组件可以查询任何Consul Server或任何Consul Agent。Agent将查询自动转发到Server。
Agent会自动将查询转发给Server Agent。 每个数据中心都运行一个Consul Server集群。当有跨数据中心的服务发现或配置请求时,本地Consul Server将请求转发到远程数据中心并返回结果。
Consul的应用场景包括服务发现、服务隔离、服务配置:
参考文档:https://developer.hashicorp.com/consul/downloads?host=www.consul.io
安装软件包
[root@tiaoban ~]# yum install -y yum-utils
[root@tiaoban ~]# yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
[root@tiaoban ~]# yum -y install consul
启动服务
[root@tiaoban ~]# systemctl start consul
[root@tiaoban ~]# systemctl enable consul
下载
[root@tiaoban ~]# mkdir consul
[root@tiaoban ~]# cd consul/
[root@tiaoban consul]# wget https://releases.hashicorp.com/consul/1.13.2/consul_1.13.2_linux_amd64.zip
[root@tiaoban consul]# ls
consul_1.13.2_darwin_amd64.zip
解压安装
[root@tiaoban consul]# unzip consul_1.13.2_linux_amd64.zip
Archive: consul_1.13.2_linux_amd64.zip
inflating: consul
[root@tiaoban consul]# ls
consul consul_1.13.2_linux_amd64.zip
[root@tiaoban consul]# mv consul /usr/local/bin/
[root@tiaoban consul]# consul version
Consul v1.13.2
Revision 0e046bbb
Build Date 2022-09-20T20:30:07Z
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
启动服务测试
使用单节点模式启动测试
[root@tiaoban consul]# consul agent -dev -ui -client 0.0.0.0
添加启动脚本
[root@tiaoban ~]# cat /usr/lib/systemd/system/consul.service
[Unit]
Description=consul
After=network.target
[Service]
ExecStart=/usr/local/consul/start.sh
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target
[root@tiaoban ~]# mkdir -p /usr/local/consul/
[root@tiaoban ~]# cat /usr/local/consul/start.sh
#!/bin/bash
/usr/local/bin/consul agent -dev -ui -client 0.0.0.0
[root@tiaoban ~]# chmod u+x /usr/local/consul/start.sh
启动服务
[root@tiaoban ~]# systemctl daemon-reload
[root@tiaoban ~]# systemctl start consul
[root@tiaoban ~]# systemctl enable consul
以下操作以yum方式安装consul配置为例,配置文件路径
/etc/consul.d/consul.hcl
修改配置文件
# 指明数据中心的名字
datacenter = "my-dc-1"
# 存储状态的数据目录
data_dir = "/opt/consul"
# web ui
ui_config{
enabled = true
}
# 节点是个Server
server = true
# 绑定的一个地址,用于节点之间通信的地址
bind_addr = "192.168.10.100"
# 期望提供的Server节点数目
bootstrap_expect=1
# Client接口绑定到的地址
client_addr = "0.0.0.0"
启动服务,查看集群成员
[root@tiaoban consul.d]# systemctl start consul
[root@tiaoban consul.d]# consul members
Node Address Status Type Build Protocol DC Partition Segment
tiaoban 192.168.10.100:8301 alive server 1.13.2 2 my-dc-1 default <all>
主机规划
主机名 | IP | 角色 |
---|---|---|
k8s-master | 192.168.10.10 | server |
k8s-work1 | 192.168.10.11 | server |
k8s-work2 | 192.168.10.12 | server |
tiaoban | 192.168.10.100 | clinet |
server端配置
# 指明数据中心的名字
datacenter = "my-dc-1"
# 存储状态的数据目录
data_dir = "/opt/consul"
# web ui
ui_config{
enabled = true
}
# 节点是个Server
server = true
# 绑定的一个地址,用于节点之间通信的地址。此处以192.168.10.10为例,其他两个更换ip即可。
bind_addr = "192.168.10.10"
# 期望提供的Server节点数目
bootstrap_expect=3
# Client接口绑定到的地址
client_addr = "0.0.0.0"
client配置
# 指明数据中心的名字
datacenter = "my-dc-1"
# 存储状态的数据目录
data_dir = "/opt/consul"
# web ui
ui_config{
enabled = true
}
# 节点是个Server
server = false
# 绑定的一个地址,用于节点之间通信的地址
bind_addr = "192.168.10.100"
# Client接口绑定到的地址
client_addr = "0.0.0.0"
启动服务并加入集群
# 所有机器执行
[root@k8s-master consul.d]# systemctl restart consul
# 除了k8s-master以外的其他机器执行
[root@k8s-tiaoban consul.d]# consul join 192.168.10.10
Successfully joined cluster by contacting 1 nodes.
[root@k8s-master ~]# consul catalog services
consul
traefik
traefik-tcp
consul services deregister -id=:service-id
// :service-id 为用户服务Id
[root@k8s-master ~]# consul members
Node Address Status Type Build Protocol DC Partition Segment
k8s-master 192.168.10.10:8301 alive server 1.13.3 2 my-dc-1 default <all>
k8s-work1 192.168.10.11:8301 alive server 1.13.3 2 my-dc-1 default <all>
k8s-work2 192.168.10.12:8301 alive server 1.13.3 2 my-dc-1 default <all>
tiaoban 192.168.10.100:8301 alive client 1.13.2 2 my-dc-1 default <default>
[root@k8s-master ~]# consul operator raft list-peers
Node ID Address State Voter RaftProtocol
k8s-work1 322a522a-dcf5-3727-052e-0f2d65406f8d 192.168.10.11:8300 follower true 3
k8s-master 5db3c09a-f94d-b53f-6c9f-694beb64c1aa 192.168.10.10:8300 leader true 3
k8s-work2 d0e4a609-f029-cd91-1d61-63c3403b82b3 192.168.10.12:8300 follower false 3
新增json配置文件
[root@k8s-master consul.d]# cat /etc/consul.d/kube-apiserver.json
{
"service": {
"name": "traefik-tcp",
"tags": [
"k8s","traefik"
],
"address": "192.168.10.10",
"port": 9100
}
}
重启服务
[root@k8s-master consul.d]# systemctl restart consul
web界面查看
注册一个name为traefik的服务
[root@k8s-master consul.d]# curl -X PUT -d '{"name": "traefik","address": "192.168.10.10","port": 80,"tags": ["k8s"]}' http://192.168.10.10:8500/v1/agent/service/register
注册带健康检查的服务
curl -X PUT -d '{"name": "traefik-metrics","address": "192.168.10.10","port": 80,"tags": ["k8s"],"checks":[{"http":"http://192.168.10.10:9100/metrics","interval":"5s"}]}' http://192.168.10.10:8500/v1/agent/service/register
打开管理页面查看已注册的服务
除了采用配置文件或者HTTP API方式注册服务外,consul也支持使用sdk包注册查询服务,目前主流的开发语法均已支持,详情参考文档:
https://developer.hashicorp.com/consul/api-docs/libraries-and-sdks
查看服务列表
[root@k8s-master ~]# curl -s http://192.168.10.10:8500/v1/catalog/services | jq
{
"consul": [],
"traefik": [
"k8s"
],
"traefik-tcp": [
"k8s",
"traefik"
]
}
查看服务详细信息
[root@k8s-master ~]# curl -s http://192.168.10.10:8500/v1/catalog/service/traefik | jq
[
{
"ID": "eda0ef7f-ca12-bbca-c84e-f88cc3664cd1",
"Node": "tiaoban",
"Address": "192.168.10.100",
"Datacenter": "my-dc-1",
"TaggedAddresses": {
"lan": "192.168.10.100",
"lan_ipv4": "192.168.10.100",
"wan": "192.168.10.100",
"wan_ipv4": "192.168.10.100"
},
"NodeMeta": {
"consul-network-segment": ""
},
"ServiceKind": "",
"ServiceID": "traefik",
"ServiceName": "traefik",
"ServiceTags": [
"k8s"
],
"ServiceAddress": "192.168.10.10",
"ServiceTaggedAddresses": {
"lan_ipv4": {
"Address": "192.168.10.10",
"Port": 80
},
"wan_ipv4": {
"Address": "192.168.10.10",
"Port": 80
}
},
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {},
"ServicePort": 80,
"ServiceSocketPath": "",
"ServiceEnableTagOverride": false,
"ServiceProxy": {
"Mode": "",
"MeshGateway": {},
"Expose": {}
},
"ServiceConnect": {},
"CreateIndex": 12,
"ModifyIndex": 12
}
]
健康检查
[root@k8s-master ~]# curl -s http://192.168.10.10:8500/v1/health/service/traefik?passing | jq
[
{
"Node": {
"ID": "eda0ef7f-ca12-bbca-c84e-f88cc3664cd1",
"Node": "tiaoban",
"Address": "192.168.10.100",
"Datacenter": "my-dc-1",
"TaggedAddresses": {
"lan": "192.168.10.100",
"lan_ipv4": "192.168.10.100",
"wan": "192.168.10.100",
"wan_ipv4": "192.168.10.100"
},
"Meta": {
"consul-network-segment": ""
},
"CreateIndex": 9,
"ModifyIndex": 11
},
"Service": {
"ID": "traefik",
"Service": "traefik",
"Tags": [
"k8s"
],
"Address": "192.168.10.10",
"TaggedAddresses": {
"lan_ipv4": {
"Address": "192.168.10.10",
"Port": 80
},
"wan_ipv4": {
"Address": "192.168.10.10",
"Port": 80
}
},
"Meta": null,
"Port": 80,
"Weights": {
"Passing": 1,
"Warning": 1
},
"EnableTagOverride": false,
"Proxy": {
"Mode": "",
"MeshGateway": {},
"Expose": {}
},
"Connect": {},
"PeerName": "",
"CreateIndex": 12,
"ModifyIndex": 12
},
"Checks": [
{
"Node": "tiaoban",
"CheckID": "serfHealth",
"Name": "Serf Health Status",
"Status": "passing",
"Notes": "",
"Output": "Agent alive and reachable",
"ServiceID": "",
"ServiceName": "",
"ServiceTags": [],
"Type": "",
"Interval": "",
"Timeout": "",
"ExposedPort": 0,
"Definition": {},
"CreateIndex": 9,
"ModifyIndex": 9
}
]
}
]
删除注册的服务
[root@k8s-master consul.d]# curl -X PUT http://192.168.10.10:8500/v1/agent/service/deregister/traefik
DNS接口是Consul中主要的查询接口之一,另一个是HTTP接口, HTTP接口查询请查阅,Consul默认在8600端口监听DNS查询。
参考文档:https://developer.hashicorp.com/consul/docs/discovery/dns
要使用DNS接口, 有几种方法可以实现:
一是使用指定的DNS解析库, 然后指向Consul;
二是把Consul设置为节点的DNS服务器, 并且提供recursors配置项, 这样非Consul的查询也能被解析;
最后一种方法是从已有的DNS服务器上把所有consul.为域名的请求转发到consul agent上。
节点查找
查找节点的地址信息,查找格式:.node[.datacenter].。如果datacenter不指定,默认为当前集群查询。
[root@k8s-master ~]# dig @192.168.10.10 -p 8600 tiaoban.node.consul ANY
; <<>> DiG 9.11.26-RedHat-9.11.26-6.el8 <<>> @192.168.10.10 -p 8600 tiaoban.node.consul ANY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25684
;; 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:
;tiaoban.node.consul. IN ANY
;; ANSWER SECTION:
tiaoban.node.consul. 0 IN A 192.168.10.100
tiaoban.node.consul. 0 IN TXT "consul-network-segment="
;; Query time: 14 msec
;; SERVER: 192.168.10.10#8600(192.168.10.10)
;; WHEN: 一 10月 31 10:51:10 CST 2022
;; MSG SIZE rcvd: 100
服务查找
查询服务提供者。服务查询支持两种查找方法:标准和严格RFC 2782。
标准查找格式:[tag.].service[.datacenter].。Tag是可选的,而且与节点查找一样,数据中心也是可选。如果没有提供Tag,就不会有过滤,如果没有数据中心,就会选择默认的数据中心。
[root@k8s-master ~]# dig @192.168.10.10 -p 8600 traefik.service.consul SRV
; <<>> DiG 9.11.26-RedHat-9.11.26-6.el8 <<>> @192.168.10.10 -p 8600 traefik.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28200
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;traefik.service.consul. IN SRV
;; ANSWER SECTION:
traefik.service.consul. 0 IN SRV 1 1 80 c0a80a0a.addr.my-dc-1.consul.
;; ADDITIONAL SECTION:
c0a80a0a.addr.my-dc-1.consul. 0 IN A 192.168.10.10
tiaoban.node.my-dc-1.consul. 0 IN TXT "consul-network-segment="
;; Query time: 13 msec
;; SERVER: 192.168.10.10#8600(192.168.10.10)
;; WHEN: 一 10月 31 10:53:30 CST 2022
;; MSG SIZE rcvd: 164
RFC2782 查找 格式:..service[.datacenter][.domain]根据RFC 2782, SRV请求都应该在service和protocol前使用(_)作为前缀。避免发生DNS冲突。Protocol可以是service任何一个tag,如果service没有tag,使用tcp作为protocol。如果一旦设置了tcp,那么查询时将不会执行任何标签过滤。
# 查询tag为k8s的注册服务traefik信息。
[root@k8s-master ~]# dig @192.168.10.10 -p 8600 _traefik._k8s.service.consul SRV
; <<>> DiG 9.11.26-RedHat-9.11.26-6.el8 <<>> @192.168.10.10 -p 8600 _traefik._k8s.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43270
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_traefik._k8s.service.consul. IN SRV
;; ANSWER SECTION:
_traefik._k8s.service.consul. 0 IN SRV 1 1 80 c0a80a0a.addr.my-dc-1.consul.
;; ADDITIONAL SECTION:
c0a80a0a.addr.my-dc-1.consul. 0 IN A 192.168.10.10
tiaoban.node.my-dc-1.consul. 0 IN TXT "consul-network-segment="
;; Query time: 1 msec
;; SERVER: 192.168.10.10#8600(192.168.10.10)
;; WHEN: 一 10月 31 10:57:05 CST 2022
;; MSG SIZE rcvd: 170
consul kv 是consul的核心功能,并随consul agent一起安装。consul kv允许用户存储索引对象,尽管其主要用途是存储配置参数和元数据。
consul kv 数据存储在server上,可以由任何agent(client或server)访问。consul允许在所有server之间自动复制数据,如果发生故障,拥有一定数量的server将减少数据丢失的风险。
数据存储位于server上的数据目录中,为确保在完全中断的情况下不会丢失数据,可以使用 consul snapshot 命令备份数据。还可以通过 consul kv 子命令、HTTP API 和 Consul UI 访问kv存储。
命令行创建kv
[root@k8s-master consul.d]# consul kv put key1 value1
Success! Data written to: key1
查看kv
# 查看所有key value数据
[root@k8s-master consul.d]# consul kv get --recurse
key1:value1
key2:value2
# 查看指定key value数据
[root@k8s-master consul.d]# consul kv get key2
value2
更新kv
[root@k8s-master consul.d]# consul kv put key2 v2
Success! Data written to: key2
删除kv
[root@k8s-master consul.d]# consul kv delete key2
Success! Deleted key: key2
web界面创建kv
web界面查看kv
# 设置kv
[root@k8s-master consul.d]# curl -X PUT -d 'value3' http://192.168.10.10:8500/v1/kv/key3
true
# 查看kv
[root@k8s-master consul.d]# curl -s http://192.168.10.10:8500/v1/kv/key3 | jq
[
{
"LockIndex": 0,
"Key": "key3",
"Flags": 0,
"Value": "dmFsdWUz",
"CreateIndex": 611,
"ModifyIndex": 611
}
]
# base64解码查看内容
[root@k8s-master consul.d]# echo "dmFsdWUz" | base64 -d
value3
# 删除kv
[root@k8s-master consul.d]# curl -X DELETE http://192.168.10.10:8500/v1/kv/key3
通过ACLS 来确保安全的访问 UI, API, CLI, servie 通信,Agent通信。如果想要确保数据中心安全,就需要配置ACLS。ACL核心原理是,将规则分组为策略, 然后一个或多个策略于令牌关联。
修改consul配置文件,新增如下内容
# acl访问控制
acl = {
enabled = true
default_policy = "deny" # 默认拒绝所有操作
enable_token_persistence = true # 持久化到磁盘,重启时重新加载
}
重启consul服务
[root@k8s-master consul.d]# systemctl restart consul
生成token
[root@k8s-master consul.d]# consul acl bootstrap
AccessorID: 16a37577-f243-94fb-8770-35489870025c
SecretID: 54a3e3fd-ea07-85a8-67e3-33107a958977
Description: Bootstrap Token (Global Management)
Local: false
Create Time: 2022-10-27 22:56:07.654230262 +0800 CST
Policies:
00000000-0000-0000-0000-000000000001 - global-management
web页面访问验证
api接口访问验证
# 直接获取kv提示权限拒绝
[root@k8s-master consul.d]# curl -s http://192.168.10.10:8500/v1/kv/key3
rpc error making call: Permission denied: token with AccessorID '00000000-0000-0000-0000-000000000002' lacks permission 'key:read' on "key3"[root@k8s-master consul.d]#
# 请求头添加token访问
[root@k8s-master consul.d]# curl -s -H "X-Consul-Token:54a3e3fd-ea07-85a8-67e3-33107a958977" http://192.168.10.10:8500/v1/kv/key3 | jq
[
{
"LockIndex": 0,
"Key": "key3",
"Flags": 0,
"Value": "dmFsdWUz",
"CreateIndex": 611,
"ModifyIndex": 611
}
]
微信公众号同步更新,欢迎关注微信公众号第一时间获取最近文章。
崔亮的博客-专注devops自动化运维,传播优秀it运维技术文章。更多原创运维开发相关文章,欢迎访问https://www.cuiliangblog.cn