分布式服务发现与注册中心 Consul

分布式服务发现与注册中心 Consul

github地址:
  • https://github.com/consul/consul

基础概念

什么是注册中心

随着微服务理论发展的成熟,越来越多互联网公司采用微服务架构来支持业务发展。各个微服务之间都需要通过注册中心来实现自动化的注册和发现。

注册中心主要有三种角色:

  • 服务提供者(RPC Server):在启动时,向 Registry 注册自身服务,并向 Registry 定期发送心跳汇报存活状态。
  • 服务消费者(RPC Client):在启动时,向 Registry 订阅服务,把 Registry 返回的服务节点列表缓存在本地内存中,并与 RPC Sever 建立连接。
  • 服务注册中心(Registry):用于保存 RPC Server 的注册信息,当 RPC Server 节点发生变更时,Registry 会同步变更,RPC Client 感知后会刷新本地 内存中缓存的服务节点列表。

最后,RPC Client 从本地缓存的服务节点列表中,基于负载均衡算法选择一台 RPC Sever 发起调用。 目前常见的注册中心有Consul、ETCD、Zookeeper、Eureka、Nacos等。

什么是Consul

Consul是HashiCorp公司推出的开源工具,Consul由Go语言开发,部署起来非常容易,只需要极少的可执行程序和配置文件,具有绿色、轻量级的特点。Consul是分布式的、高可用的、 可横向扩展的用于实现分布式系统的服务发现与配置。

Consul特点

  • 服务发现(Service Discovery):Consul提供了通过DNS或者HTTP接口的方式来注册服务和发现服务。一些外部的服务通过Consul很容易的找到它所依赖的服务。
  • 健康检查(Health Checking):Consul的Client可以提供任意数量的健康检查,既可以与给定的服务相关联(“webserver是否返回200 OK”),也可以与本地节点相关联(“内存利用率是否低于90%”)。操作员可以使用这些信息来监视集群的健康状况,服务发现组件可以使用这些信息将流量从不健康的主机路由出去。
  • Key/Value存储:应用程序可以根据自己的需要使用Consul提供的Key/Value存储。 Consul提供了简单易用的HTTP接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。
  • 安全服务通信:Consul可以为服务生成和分发TLS证书,以建立相互的TLS连接。意图可用于定义允许哪些服务通信。服务分割可以很容易地进行管理,其目的是可以实时更改的,而不是使用复杂的网络拓扑和静态防火墙规则。
  • 多数据中心:Consul支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。

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提供服务的节点都会运行一个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的使用场景

Consul的应用场景包括服务发现、服务隔离、服务配置:

  • 服务发现场景中consul作为注册中心,服务地址被注册到consul中以后,可以使用consul提供的dns、http接口查询,consul支持health check。
  • 服务隔离场景中consul支持以服务为单位设置访问策略,能同时支持经典的平台和新兴的平台,支持tls证书分发,service-to-service加密。
  • 服务配置场景中consul提供key-value数据存储功能,并且能将变动迅速地通知出去,借助Consul可以实现配置共享,需要读取配置的服务可以从Consul中读取到准确的配置信息。
  • Consul可以帮助系统管理者更清晰的了解复杂系统内部的系统架构,运维人员可以将Consul看成一种监控软件,也可以看成一种资产(资源)管理系统。

安装部署

参考文档:https://developer.hashicorp.com/consul/downloads?host=www.consul.io[1]

yum部署

安装软件包

$ yum install -y yum-utils
$ yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
$ yum -y install consul

启动服务

$ systemctl start consul
$ systemctl enable consul

二进制部署

下载

$ mkdir consul
$ cd consul/
$ wget https://releases.hashicorp.com/consul/1.13.2/consul_1.13.2_linux_amd64.zip
$ lsconsul_1.13.2_darwin_amd64.zip

解压安装

$ unzip consul_1.13.2_linux_amd64.zip 
Archive:  consul_1.13.2_linux_amd64.zip  inflating: consul                  
lsconsul  consul_1.13.2_linux_amd64.zip
$ mv consul /usr/local/bin/
$ consul version
Consul v1.13.2Revision 0e046bbbBuild Date 2022-09-20T20:30:07ZProtocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

启动服务测试 使用单节点模式启动测试

$ consul agent -dev -ui -client 0.0.0.0

添加启动脚本

$ 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
$ mkdir -p /usr/local/consul/
$ cat /usr/local/consul/start.sh
#!/bin/bash
/usr/local/bin/consul agent -dev -ui -client 0.0.0.0
$ chmod u+x /usr/local/consul/start.sh 

启动服务

$ systemctl daemon-reload 
$ systemctl start consul
$ 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"

启动服务,查看集群成员

$ systemctl start consul
$ consul members 
Node     Address              Status  Type    Build   Protocol  DC     Partition  Segment
test-consul  192.168.10.100:8301  alive   server  1.13.2  2         my-dc-1  default    <all>

集群模式

主机规划

主机名IP角色
k8s-master192.168.10.10server
k8s-work1192.168.10.11server
k8s-work2192.168.10.12server
test-consul192.168.10.100clinet

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"

启动服务并加入集群

# 所有机器执行
$ systemctl restart consul
# 除了k8s-master以外的其他机器执行
$ consul join 192.168.10.10
Successfully joined cluster by contacting 1 nodes.

Consul 常用CLI

查看服务列表

$ consul catalog services
consul
traefik
traefik-tcp

注销服务

$ consul services deregister -id=:service-id
// :service-id 为用户服务Id

查看节点成员

$ 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>
test-consul     192.168.10.100:8301  alive   client  1.13.2  2         my-dc-1  default    <default>

查看server节点信息

$ 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

Consul常用HTTP API

服务查询

  • /agent/services:该端点返回在本地代理程序中注册的所有服务;
  • /agent/service/{service_id}:返回在本地代理上注册的单个服务实例的完整服务定义;
  • /agent/health/service/name/{service_name} :通过名称检索注册的服务状态(设置了健康检查的服务);
  • /agent/health/service/id/{service_id}:通过id检索注册的服务状态(设置了健康检查的服务);
  • /health/service/{service_name}?passing:通过健康检查的服务(包含未设置check的service)

服务注册

  • /agent/service/register:注册服务;

服务删除

  • /agent/service/deregister/{service_id}:注销服务;
  • /agent/service/maintenance/{service_id}:该端点将给定的服务置于“维护模式”,在维护模式下,该服务将被标记为不可用,并且不会出现在DNS或API查询中;

服务注册

配置文件

新增json配置文件

$ cat /etc/consul.d/kube-apiserver.json 
{    
	"service": {
  		"name": "traefik-tcp",        
  		"tags": [
      			"k8s","traefik"        
      ],        
      "address": "192.168.10.10",        
      "port": 9100    
      }
}

重启服务

$ systemctl restart consul

web界面查看

HTTP API

注册一个name为traefik的服务

$  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

打开管理页面查看已注册的服务

SDK

除了采用配置文件或者HTTP API方式注册服务外,consul也支持使用sdk包注册查询服务,目前主流的开发语法均已支持,详情参考文档:https://developer.hashicorp.com/consul/api-docs/libraries-and-sdks[2]

服务查询

HTTP API

查看服务列表

$ curl -s http://192.168.10.10:8500/v1/catalog/services | jq

查看服务详细信息

$ curl -s http://192.168.10.10:8500/v1/catalog/service/traefik | jq

健康检查

$ curl -s http://192.168.10.10:8500/v1/health/service/traefik?passing | jq

删除注册的服务

$ curl -X PUT http://192.168.10.10:8500/v1/agent/service/deregister/traefik

DNS解析

DNS接口是Consul中主要的查询接口之一,另一个是HTTP接口, HTTP接口查询请查阅,Consul默认在8600端口监听DNS查询。

参考文档:https://developer.hashicorp.com/consul/docs/discovery/dns[3]

要使用DNS接口, 有几种方法可以实现:

一是使用指定的DNS解析库, 然后指向Consul;

二是把Consul设置为节点的DNS服务器, 并且提供recursors配置项, 这样非Consul的查询也能被解析;

最后一种方法是从已有的DNS服务器上把所有consul.为域名的请求转发到consul agent上。

**节点查找:**查找节点的地址信息,查找格式:.node[.datacenter].。如果datacenter不指定,默认为当前集群查询。

$ 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: 一 1031 10:51:10 CST 2022
;; MSG SIZE  rcvd: 100

**服务查找:**查询服务提供者。服务查询支持两种查找方法:标准和严格RFC 2782。

标准查找格式:[tag.].service[.datacenter].。Tag是可选的,而且与节点查找一样,数据中心也是可选。如果没有提供Tag,就不会有过滤,如果没有数据中心,就会选择默认的数据中心。

$ 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: 一 1031 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信息。
$ 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: 一 1031 10:57:05 CST 2022
;; MSG SIZE  rcvd: 170

配置kv

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

$ consul kv put key1 value1
Success! Data written to: key1

查看kv

# 查看所有key value数据
$ consul kv get --recurse 
key1:value1
key2:value2
# 查看指定key value数据
$ consul kv get key2
value2

更新kv

$ consul kv put key2 v2
Success! Data written to: key2

删除kv

$ consul kv delete key2
Success! Deleted key: key2

HTTP API

# 设置kv
$ curl -X PUT -d 'value3' http://192.168.10.10:8500/v1/kv/key3
true
# 查看kv
$ 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解码查看内容
$ echo "dmFsdWUz" | base64 -d
value3
# 删除kv
$ curl -X DELETE http://192.168.10.10:8500/v1/kv/key3

访问控制

通过ACLS 来确保安全的访问 UI, API, CLI, servie 通信,Agent通信。如果想要确保数据中心安全,就需要配置ACLS。ACL核心原理是,将规则分组为策略, 然后一个或多个策略于令牌关联。

启用ACL

修改consul配置文件,新增如下内容

# acl访问控制
acl = {
  enabled = true
  default_policy = "deny" # 默认拒绝所有操作
  enable_token_persistence = true # 持久化到磁盘,重启时重新加载
}

重启consul服务

$ systemctl restart consul

生成token

$ 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

api接口访问验证

# 直接获取kv提示权限拒绝
$  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访问
$  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
  }
]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值