consul简介
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。
consul特点
1. 服务发现
Consul 允许服务实例(即服务的运行时实体)注册自己到 Consul 集群中。一旦注册,其他服务就
可以通过 Consul 使用 DNS 或者 HTTP 接口来查找并访问这些服务。这使得服务之间的交互变得简单
且透明,无需硬编码服务位置,增强了服务的弹性和灵活性。
2. 健康检查
Consul 支持定义健康检查规则,用于监控服务实例的健康状况。健康检查可以是与特定服务相关的
(例如,检查一个 web 服务器是否能正确返回 HTTP 200 OK 状态码)。如果检测到服务实例不再
健康,Consul 可以标记该实例为不可用,从而避免将请求路由到该实例上,提高了系统的可靠性。
3. KV 存储
Consul 提供了一个简单的 HTTP API 来访问其内置的键值存储功能。这可以被用来存储和分发服务
配置、特征标志、协调任务执行等。键值存储也可以用于选举集群中的领导者,或者用于服务间的数据
交换。这种灵活性使得 Consul 成为了一个多功能工具,在微服务架构中可以承担多种职责。
4. 安全服务通信
Consul 还支持生成和分发服务之间的 TLS 证书,促进服务之间建立相互认证的安全连接。此外,
Consul 引入了意图(Intentions)的概念,允许管理员定义哪些服务可以互相通信,从而增加了网络
层面的安全控制。
5. Web 管理界面
Consul 自带了一个直观的 Web 界面,这使得服务注册、健康检查、配置管理等功能更加易用。通过
这个界面,管理员可以实时查看服务的状态,监控集群的健康情况,并进行必要的配置调整。这对于
调试和日常运维来说是一个非常有用的工具。
Consul 角色
Server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网
与其它数据中心通讯。 每个数据中心的 Server 数量推荐为 3 个或是 5 个。
Client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群。
Consul的服务注册与发现流程
- 服务注册:服务实例启动时,其Agent会向Consul注册服务。注册时需要提供服务的名称、地址、端口和其他元数据信息。
- 健康检查:注册后,Consul会定期向该服务实例发送健康检查请求,以验证服务的可用性和健康状态。检查结果会被汇报给Consul Server,并在集群中同步更新。
- 服务发现:客户端应用程序通过向Consul查询服务注册表来发现可用的服务实例。Consul会返回包含所有符合查询条件的服务实例列表,应用程序可以根据需要选择其中的一个实例进行通信。
部署模式
- 单机部署:适用于小型环境和测试场景,将Consul的Agent和Server部署在同一节点上。
- 集群部署:适用于生产环境和大规模部署,通过部署多个Consul Server节点来提高系统的可用性和容错能力。
- 多数据中心部署:对于全球性的分布式系统,可以在不同地理位置部署多个Consul集群,并通过WAN(广域网)连接来实现多数据中心之间的服务发现和配置同步。
实验原理
在安装容器的服务器上面安装registrator容器,用于服务的发现和注册,将运行中的容器添加到consul注册中心。注册中心对服务进行健康检测,当发现有不运行的服务时会自动从注册中心移除,nginx利用自动同步模块从consul获取数据并自动生成upstream配置文件。
实验流程
-
准备环境:
在服务器上安装 Docker 和 Consul。启动 Consul 代理,确保各服务器之间能够相互通信。 -
安装 Registrator:
使用 Docker 启动 Registrator 容器,并配置其监听 Docker 事件并向 Consul 发送服务注册信息。 -
启动服务容器:
使用docker run
命令启动服务容器,并确保 Registrator 正确注册这些服务到 Consul。 -
配置 Nginx 自动同步模块:
- 配置 Nginx 使用自动同步模块从 Consul 获取服务信息,并自动生成
upstream
配置。 - 测试 Nginx 是否能够正确地根据 Consul 中的服务信息更新其配置。
- 配置 Nginx 使用自动同步模块从 Consul 获取服务信息,并自动生成
实验环境准备三台机器
192.168.157.131 主机名修改:consul-nginx-server
192.168.157.128 主机名修改:docker-01
192.168.157.134 主机名修改:docker-02
安装consul注册中心
单机与集群
集群--略
这里以单机部署为例
[root@consul-nginx-server ~]# mkdir /data/consul/{conf,data} -p
[root@consul-nginx-server ~]# wget https://releases.hashicorp.com/consul/1.13.1/consul_1.13.1_linux_amd64.zip
[root@consul-nginx-server ~]# unzip consul_1.13.1_linux_amd64.zip
[root@consul-nginx-server ~]# mv consul /data/consul/
生成consul加密的密钥串
[root@consul-nginx-server consul]# /data/consul/consul keygen
zFhxl6ETOsrIC7w/WynGoWYe74oUIU69SJl3dRaM4Wg=
创建配置文件
[root@consul-nginx-server consul]# cat /data/consul/conf/config.json
{
"bootstrap_expect": 1,
"client_addr": "0.0.0.0",
"bind_addr": "{{GetInterfaceIP \"ens33\"}}", #指定网卡
"datacenter": "webapp",
"data_dir": "/data/consul/data",
"pid_file": "/data/consul/consul.pid",
"domain": "consul",
"enable_script_checks": true,
"dns_config": {
"enable_truncate": true,
"only_passing": true
},
"disable_update_check": true,
"enable_syslog": true,
"encrypt": "zFhxl6ETOsrIC7w/WynGoWYe74oUIU69SJl3dRaM4Wg=", #指定刚刚生成的加密密钥
"leave_on_terminate": true,
"log_level": "INFO",
"rejoin_after_leave": true,
"server": true,
"start_join": [
"192.168.209.166" #ip地址修改为自己的
],
"ui": true #开启consul管理界面
}
启动consul
[root@consul-nginx-server consul]# nohup /data/consul/consul agent -server -config-dir /data/consul/conf > /data/consul/nohup_consul.log 2>&1 &
查看端口
[root@consul-nginx-server consul]# netstat -lntp | grep consul
tcp 0 0 192.168.157.131:8300 0.0.0.0:* LISTEN 1215/consul
tcp 0 0 192.168.157.131:8301 0.0.0.0:* LISTEN 1215/consul
tcp 0 0 192.168.157.131:8302 0.0.0.0:* LISTEN 1215/consul
tcp6 0 0 :::8500 :::* LISTEN 1215/consul
tcp6 0 0 :::8600 :::* LISTEN 1215/consul
端口解释
8300:集群节点;
8301:集群内部访问的端口;
8302:跨数据中心之间的通信;
8500:访问界面
http://192.168.157.131:8500/
consul安装完成
安装docker服务器
192.168.157.128 主机名修改:docker-01
192.168.157.134 主机名修改:docker-02
两台机器安装docker--略
Registrator 服务会检查应用服务容器的运行状态,进行自动注册和注销 docker 容器服务到服务注册中心Consul上。目前支持与 Consul、etcd 和 SkyDNS2等软件进行整合。
Registrator监控新建的Docker容器,并且检查判定这些容器提供的服务。Registrator在容器内发现的任务服务,都将被添加到一个服务注册端,比如Consul或etcd。
在要注册容器服务到etcd或consul中的主机安装docker
[root@docker-01 ~]# docker pull gliderlabs/registrator
[root@docker-02 ~]# docker pull gliderlabs/registrator
运行registrator容器
[root@docker-01 ~]# docker run -itd --name registrator --restart=always -v /var/run/docker.sock:/tmp/docker.sock --net host docker.io/gliderlabs/registrator --ip 192.168.157.128 consul://192.168.157.131:8500
[root@docker-02 ~]# docker run -itd --name registrator --restart=always -v /var/run/docker.sock:/tmp/docker.sock --net host docker.io/gliderlabs/registrator --ip 192.168.157.134 consul://192.168.157.131:8500
命令解释
Docker选项
-v /var/run/docker.sock:/tmp/docker.sock
#允许Registrator访问Docker API
--net=host
#帮助Registrator获取主机级的IP和主机名
与设置主机网络模式相比,另一个可选的方案是设置容器名字为宿主主机名(-h $HOSTNAME),并且使用下面Registrator的-ip选项。
Registrator选项
--ip "192.168.157.131
#强制设置注册服务使用的IP地址,默认使用宿主机IP
-cleanup=true
#清理悬挂服务,容器状态为非up状态时进行清理,默认情况下是删除容器时清理,停止时不清理
consul://192.168.157.131:8500
#注册后端consul服务注册地址
运行容器指定服务名称
服务名是你在服务发现查找中使用的。缺省情况下,服务名按下面的格式确定:
使用容器镜像的基础,如果镜像是gliderlabs/footbar
,服务名就是footbar
。如果镜像是redis
,服务名就是简单的redis
。
而且如果一个容器有多个暴露端口,它将各自追加内部暴露端口以区别。例如,一个镜像nginx
有两个暴露端口,80和443,将产生两个服务,分别命名nginx-80
和nginx-443
。
你可以使用标签或者环境变量,SERVICE_NAME
或者'SERVICE_x_NAME',其中x
是内部暴露端口,覆盖这些缺省名字。
docker run -itd -p 80:80 --name web01 \
-e "SERVICE_NAME=webservices" \
nginx
运行容器进行服务注册指定健康检查
通过设置环境变量指定健康检查为http
[root@docker-01 ~]# docker run -itd -p 80:80 --name web01 -e SERVICE_NAME=webapp -e SERVICE_80_CHECK_HTTP=/index.html -e SERVICE_80_CHECK_INTERVAL=10s -e SERVICE_TAGS=Web01-80 daocloud.io/library/nginx
[root@docker-02 ~]# docker run -itd -p 80:80 --name web02 -e SERVICE_NAME=webapp -e SERVICE_80_CHECK_HTTP=/index.html -e SERVICE_80_CHECK_INTERVAL=10s -e SERVICE_TAGS=Web02-80 daocloud.io/library/nginx
运行服务容器,通过设置环境变量指定健康检查为TCP
[root@docker-01 ~]# docker run -itd -p 18080:80 --name web02 -e SERVICE_NAME=webapp -e SERVICE_CHECK_TCP=192.168.157.128:18080 -e SERVICE_CHECK_INTERVAL=5s -e SERVICE_TAGS=Web01-18080 daocloud.io/library/nginx
[root@docker-02 ~]# docker run -itd -p 18080:80 --name web01 -e SERVICE_NAME=webapp -e SERVICE_CHECK_TCP=192.168.157.134:18080 -e SERVICE_CHECK_INTERVAL=5s -e SERVICE_TAGS=Web01-18080 daocloud.io/library/nginx
登录consul查看服务注册
http://192.168.157.131:8500/
动态同步配置信息到nginx反代
容器服务注册记录在services中
在nginx反代服务器上安装nginx_upsync_module动态同步模块,将在consul中的services中注册的服务,自动同步批量生成nginx配置文件。
webservices为consul中添加的服务名称
consul服务器上面安装nginx反向代理
并将nginx动态同步upsync_module模块上传到nginx服务器中
获取后端健康检查模块:https://github.com/xiaokai-wang/nginx_upstream_check_module
[root@consul-nginx-server ~]# tar xzvf nginx-upsync-module-2.1.3.tar.gz -C /usr/local/
[root@consul-nginx-server ~]# unzip -d /usr/local/ nginx_upstream_check_module-master.zip
[root@consul-nginx-server ~]# wget http://nginx.org/download/nginx-1.22.1.tar.gz
[root@consul-nginx-server ~]# tar xzvf nginx-1.22.1.tar.gz -C /usr/local/
[root@consul-nginx-server ~]# yum install pcre pcre-devel opessl openssl-devel zlib zlib-devel -y
[root@consul-nginx-server ~]# yum -y install gcc gcc-c++
[root@consul-nginx-server ~]# useradd nginx
[root@consul-nginx-server ~]# yum install -y patch
[root@consul-nginx-server ~]# cd /usr/local/nginx-1.22.1/
[root@consul-nginx-server nginx-1.22.1]# patch -p1 < ../nginx_upstream_check_module-master/check_1.20.1+.patch
[root@consul-nginx-server nginx-1.22.1]# ./configure --prefix=/usr/local/nginx --group=nginx --user=nginx --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/tmp/nginx/client_body --http-proxy-temp-path=/tmp/nginx/proxy --http-fastcgi-temp-path=/tmp/nginx/fastcgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre --with-http_realip_module --with-stream --add-module=../nginx_upstream_check_module-master --add-module=../nginx-upsync-module-2.1.3
[root@consul-nginx-server nginx-1.22.1]# make && make install
开始配置nginx从注册中心同步容器状态
[root@consul-nginx-server ~]# cd /etc/nginx/
[root@consul-nginx-server nginx]# vim nginx.conf
upstream webapp_server {
server 127.0.0.1:11111;
upsync 192.168.157.131:8500/v1/catalog/service/webapp
upsync_timeout=6m upsync_interval=500ms upsync_type=consul_services strong_dependency=off;
upsync_dump_path /etc/nginx/conf/upstream.conf;
include /etc/nginx/conf/upstream.conf;
check interval=3000 rise=2 fall=5 timeout=5000 type=http;
check_http_send "GET / HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 80;
server_name localhost;
#location / {
# root html;
# index index.html index.htm;
#}
location / {
proxy_pass http://webapp_server;
proxy_redirect default;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
}
location /status {
check_status;
}
[root@consul-nginx-server nginx]# mkdir /etc/nginx/conf/ -p #创建同步配置文件目录
[root@consul-nginx-server nginx]# touch /etc/nginx/conf/upstream.conf #创建不同的配置文件
[root@consul-nginx-server nginx]# mkdir -p /tmp/nginx/client_body
[root@consul-nginx-server nginx]# /usr/local/nginx/sbin/nginx
语法参数
server 127.0.0.1:11111;本机upsync工作虚拟端口
127.0.0.1:2379/v2/keys/upstreams/test, consul服务器同步路径
- upsync_interval=6m;每隔一段时间从consul/etcd中拉出服务器
- upsync_timeout=500ms,从consul/etcd请求中提取服务器超时。
- upsync_type=consul,从拉取服务器类型:consul,etcd。
- strong_dependency=off,每次在nginx启动或重新加载时,nginx是否从consul/etcd中拉出配置,on,拉取
off,不拉取配置
- upsync_dump_path /etc/nginx/conf/upstream.conf, 同步存储配置文件路径
- include /etc/nginx/conf/upstream.conf, 加载配置文件路径
测试访问 http://192.168.157.131/status
删除容器, 再启动容器,并向容器内的 index.html
文件追加了特定的内容
[root@docker-01 ~]# docker run -itd -p 80:80 --name web01 -e SERVICE_NAME=webapp -e SERVICE_80_CHECK_HTTP=/index.html -e SERVICE_80_CHECK_INTERVAL=10s -v /data/html:/usr/share/nginx/html -e SERVICE_TAGS=Web01-80 daocloud.io/library/nginx
[root@docker-01 ~]# echo web-01:128 >> /data/html/index.html
[root@docker-02 ~]# docker run -itd -p 80:80 --name web02 -e SERVICE_NAME=webapp -e SERVICE_80_CHECK_HTTP=/index.html -e SERVICE_80_CHECK_INTERVAL=10s -v /data/html:/usr/share/nginx/html -e SERVICE_TAGS=Web02-80 daocloud.io/library/nginx
[root@docker-02 ~]# echo web-02:134 >> /data/html/index.html
测试,刷新,可以看到页面变化