本文共 9712 字,大约阅读时间需要 32 分钟。
提供服务发现功能的框架有很多,具体的选型和比较就不再介绍,这里主要介绍一下Consul。
consul是分布式的、高可用的、横向扩展的。提供的一些关键特性:
生产部署中,Consul安装在要注册服务的每个节点上。Consul有两种运行模式:客户端和服务器端,每个Consul数据中心必须至少有一个服务器,负责维护Consul状态,为了确保服务器故障,建议运行3-5台,性能和容错能力较好。客户端模式用来注册服务,运行状况检查并将查询转发到服务器的轻量级进程,客户端必须在Consul数据中心中运行服务的每个节点上运行,因为客户端是有关服务运行状况的真实来源。
###CentOS#### 使用 yum-config-manager 管理仓库sudo yum install -y yum-utils# 连接仓库sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo# 安装sudo yum -y install consul###Ubuntu#### 添加 GPG keycurl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -# 添加 仓库# 如果执行后提示 apt-add-repository: command not found# 可先安装: apt-get install software-properties-commonsudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"# 更新源以及安装 consulsudo apt-get update && sudo apt-get install consul
一个consul服务或者一个consul实例,官方文档成为Agent,多个Agent组成一个cluster datacenter。每个DC至少有一个server模式的agent运行。为了避免各种安全加密问题,可以使用-dev参数,开发模式运行。
$ consul agent -dev #安装完consul后启动代理$ consul members #查看数据成员方式一,通过gossip协议获取信息$ curl localhost:8500/v1/catalog/nodes #查看数据成员方式二,请求会转发到server上,8500端口也可以访问UI服务$ consul leave #停止代理
http://{你的ip}:8500
,会发现跳到了一个 UI 界面。注册服务有很多种方式:
$ consul catalog services #查询相关命令
$ mkdir ./consul.d #创建配置目录,默认在/etc/consul.d
$ echo '{ "service": { "name": "web", "tags": [ "rails" ], "port": 80 }}' > ./consul.d/web.json #创建服务配置文件
$ consul agent -dev -enable-script-checks -config-dir=./consul.d #重启代理#-enable-script-checks 可以开启配置文件检查,增强安全性,因为配置文件可以启用脚本,导致可能会引入一个远程执行漏洞$ curl localhost:8500/v1/catalog/service/service_name #查询服务$ curl localhost:8500/v1/health/service/web?passing #对运行状况良好的服务实例进行过滤查询
$ echo '{ "service": { "name": "web", "tags": [ "rails" ], "port": 80, "check": { "args": [ "curl", "localhost" ], "interval": "10s" } }}' > ./consul.d/web.json #为服务注册健康检查$ consul reload #重新加载
除了使用HTTP API直接提供服务IP地址之外,Consul还可以通过随每个服务实例在本地部署的Sidecar代理将服务彼此连接。这种部署类型(控制服务实例之间的网络流量的本地Sidecar代理)是服务网格。Consul Service Mesh 可以通过代理将多台服务器中的服务关联起来,使得其能够通过专用网络相互访问。
有时将Consul的服务网格功能称为Consul Connect功能,由于Sidecar代理控制着所有服务到服务的流量,因此他们可以收集有关它们的度量标准并将其导出到Prometheus等第三方聚合器。
$ socat -v tcp-l:8181,fork exec:"/bin/cat" #启动socat服务充当上游服务(socat是回显服务)
$ echo '{ "service": { "name": "socat", "port": 8181, "connect": { "sidecar_service": {} } }}' > ./consul.d/socat.json #注册一个服务#connect字段将注册一个sidecar代理来处理此后端服务实例的流量
$ consul reload
$ consul connect proxy -sidecar-for socat #consul内置L4代理,启动代理进程,并指定其对应的服务实例和代理注册
$ echo '{ "service": { "name": "web", "connect": { "sidecar_service": { "proxy": { "upstreams": [ { "destination_name": "socat", "local_bind_port": 9191 } ] } } } }}' > ./consul.d/web.json #注册一个web下游服务,与socat不同的是,connect字段不是空的,它指定了web对上游服务socat的依赖,以及代理侦听的端口,local_bind_port表示代理服务后,使用哪个端口作为代理端口的通信端口。
绑定的代理端口可能是以下几种情况:
$ consul reload
这将为服务注册一个sidecar代理,该代理web
将侦听端口9191
,如果我们运行的是真正的Web服务,它将在环回地址上与其代理通信。代理将加密其流量,并通过网络将其发送到socat服务的sidecar代理。Socat的代理将解密流量,并将其本地发送到端口8181上的环回地址上的socat。由于没有Web服务在运行,因此将通过在我们指定的端口上与其代理进行对话来假装为Web服务(9191)。
$ consul connect proxy -sidecar-for web #使用sidecar注册中的配置启用web代理
源 代理后-------------------------- --------------------------|8181 <-----------> 21000| <--------> |21001 <-----------> 9191|| Consul Connect | Sidecar | Consul Connect |-------------------------- --------------------------
至此我们在端口9191上可以连接socat服务并进行通信。
上面服务连接成功是因为我们在-dev开发模式下,ACL系统为“全部允许”。
$ consul intention create -deny web socat #创建一个意图拒绝web到socat的访问
$ consul intention delete web socat #删除意图
除了提供服务发现,运行状况检查和保护网络流量外,Consul还包含一个密钥值存储,可以使用它来动态配置应用程序,协调服务,管理领导者选举或充当Vault的数据后端。
$ consul kv put redis/config/minconns 1
$ consul kv put -flags=42 redis/config/users/admin abcd1234
$ consul kv get redis/config/minconns
$ consul kv get -detailed redis/config/users/admin #输出详细信息
$ consul kv get -recurse #输出所有密钥 k:v形式,字典序
$ consul kv delete redis/config/minconns
$ consul kv delete -recurse redis #删除所有redis开头的密钥
$ consul kv put foo bar #原有信息会被覆盖
当新的agent启动的时候,它们之间无感知,要将新代理添加到现有数据中心,需要为其提供数据中心中任何其他代理的IP地址,新的代理会加入数据中心,它们之间通过gossip协议通信。
可以通过虚拟机来模拟分布式环境。
下面是consul启动时一些参数介绍:
-server:以服务器模式启动
-bootstrp-expect:Consul服务器数据中心总共应该有多少台服务器
-node:节点名称
-bind:该代理将侦听其他领事成员进行通信的地址。
-data-dir:告诉consul代理它们应将状态存储在哪里
-config-dir:配置文件目录。默认/etc/consul.d
$ consul agent \ -server \ -bootstrap-expect=1 \ -node=agent-one \ -bind=192.168.1.206 \ -data-dir=/tmp/consul \ -config-dir=/etc/consul.d \ -grpc-port=8502 \ -https-port=8501 \ -client=0.0.0.0 \ #指定可访问consul的IP,如果写为固定IP,会发现其他IP都无法访问consul -hcl="connect {enabled=true}"
$ consul agent \ -node=agent-two \ -bind=192.168.1.204 \ -enable-script-checks=true \ #允许通过配置文件和http api注册的服务 -data-dir=/tmp/consul \ -config-dir=/etc/consul.d \ -retry-join=192.168.1.206 \ #这个字段可以后续不用在执行consul -grpc-port=8502 \ -https-port=8501 \ -hcl="connect {enabled=true}"
在两个节点分别运行上述命令后,两个代理仍然彼此不了解,各自组成自己的但节点数据中心。如果不想开多个远程的话,让他们在后台运行即可。
安全警告:在某些配置中启用脚本检查可能会引入一个远程执行漏洞,众所周知该漏洞是恶意软件所针对的。在生产中,我们强烈建议您-enable-local-script-checks
使用。
建议启动时把之前的data文件夹删除,consul会按历史数据去寻找曾经注册服务记录,如果服务不在了,还会一直报错找不到
在Consul服务器上运行命令 $ consul join 172.20.20.11。没有服务器,client无法运行,所有数据中心必须至少有一个在服务器模式下运行的代理,Consul才能正常运行。
提示:要加入数据中心,Consul代理只需要了解其他现有成员(可以是客户端或服务器)即可。加入数据中心后,代理会自动彼此闲聊以传播完整的成员资格信息。
在运行它的终端窗口中通过Ctrl-c或发出consul leave命令停止代理。
Consul connect 使用TLS提供服务到服务的连接授权和加密。应用程序可以在服务网格配置中使用sidecar代理来为入站和出站建立TLS连接,而根本不知道connect。connect支持异构代理部署:任何两个代理实现都可以通信,任何服务实例都可以运行任何代理实现。
该命令用于为Envoy代理生成引导配置,通过该配置,它执行一个外部Envoy 二进制文件,使Envoy进程在前台运行。
-proxy-id:代理服务ID
-envoy-binary:要执行特定Envoy二进制文件的完整路径。默认情况下$PATH将搜索envoy
-admin-bind:绑定envoy的管理HTTP API。默认值localhost:19000。envoy要求启用此功能。如果要在同一主机上运行多个不同的代理实例,这个选项在除了第一个实例之外的所有实例使用,确保他们不会绑定到同一端口。
$ consul connect envoy -sidecar-for db -admin-bind localhost:19001
-bootstrap:该命令将以json protobuf形式生成的引导程序配置输出到stdout,可以将其定向到文件,来启动Envoy。
-envoy-version:默认值1.16.0,这是必须的,以便可以生成正确配置
-sidecar-for:目标服务不必存在于本地代理。
为了使connect知道代理,您需要在服务定义中注册代理,就像您在Consul中注册其他任何服务一样。
要用做Connect代理,必须在其服务定义中将代理声明为代理类型,并提供有关其代表的服务的信息。要将服务生命为代理,服务定义必须包含以下字段:
最小示例:
{ "name": "redis-proxy", "kind": "connect-proxy", "proxy": { "destination_service_name": "redis" }, "port": 8181 //必须设置,以便connect服务可以发现连接的确切地址 //默认分配范围是21000——21255,通过agent启动时候指定-sidecar_min_port和-sidecar_max_port自定义自动分配的范围}
在注册了此服务后,所有在connect端点占用搜索“redis”的connect客户端都将找到此代理。
大多数connect代理都被部署为边车,这种情况下,如果要将代理作为sidecar部署在自己的服务注册定义中,还需要设置以下字段:
完整配置:
{ "name": "redis-proxy", "kind": "connect-proxy", "proxy": { "destination_service_name": "redis", "destination_service_id": "redis1", "local_service_address": "127.0.0.1", "local_service_port": 9090, "config": {}, "upstreams": [], "mesh_gateway": {}, "expose": {} }, "port": 8181}
{ "destination_type": "service", //指定用于查找要连接的实例的发现查询的类型。有效值为service或 prepared_query。默认为service "destination_name": "redis", "datacenter": "dc1", "local_bind_address": "127.0.0.1", //指定将本地侦听器绑定到的地址,以使应用程序与此上游建立出站连接。默认为127.0.0.1 "local_bind_port": 1234, //指定用于将本地侦听器绑定到的端口,以使应用程序与此上游建立出站连接。 "config": {}, "mesh_gateway": { //指定此代理的网状网关配置 "mode": "local" }},
为了减少sidecar代理所需要的样本数量,应用程序服务定义可以定义一个内联sidecar服务块,这是上面所诉的单独的完整代理注册的简化形式,
连接的代理通常被部署为sidecar,他与单个服务实例在同一节点上运行,或者在同一网络名称空间中作为单独的容器运行。
最小示例
{ "service": { "name": "web", "port": 8080, "connect": { "sidecar_service": {} } }}
除了正常注册web服务外,还将注册一个使用默认值的代理服务。等效于下列定义:
{ "service": { "name": "web", "port": 8080, }}{ "name": "web-sidecar-proxy", "port": 20000, "kind": "connect-proxy", "checks": [ { "Name": "Connect Sidecar Listening", "TCP": "127.0.0.1:20000", "Interval": "10s" }, { "name": "Connect Sidecar Aliasing web", "alias_service": "web" } ], "proxy": { "destination_service_name": "web", "destination_service_id": "web", "local_service_address": "127.0.0.1", "local_service_port": 8080, }}
覆盖示例
{ "name": "web", "port": 8080, "connect": { "sidecar_service": { "proxy": { "upstreams": [ { "destination_name": "db", "local_bind_port": 9191 } ], "config": { "handshake_timeout_ms": 1000 } } } }}

在运行consul之前,您应该确保可以访问一下绑定端口:
采用 | 默认端口 |
---|---|
DNS | 8600 |
HTTP | 8500 |
HTTPS | 8501(默认禁用) |
gRPC | 8502(默认禁用) |
LAN Serf | 8301 |
WAN Serf | 8302 |
服务器RPC地址 | 8300 |
Sidecar Proxy Min | 21000 |
Sidecar Proxy Max | 21255 |
转载地址:http://oimbz.baihongyu.com/