阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

基于Docker的Consul集群实现服务发现

165次阅读
没有评论

共计 7239 个字符,预计需要花费 19 分钟才能阅读完成。

服务发现

其实简单说,服务发现就是解耦服务与 IP 地址之间的硬绑定关系,
以典型的集群为例,对于集群来说,是有多个节点的,这些节点对应多个 IP(或者同一个 IP 的不同端口号),集群中不同节点责任是不一样的。
比如说一个数据集群中,可以分为读节点或者写节点,写节点和读节点都是相对的,不是硬绑定的,某一个逻辑节点,随着故障转移及恢复,是可以变换身份的(写变读,读变写;主降从,从升主等等)
集群对外提供服务的时候,对于外界来说,集群中节点身份变换的时候需要对外透明,外界无需因为集群节点的身份变换而更改配置,这就需要一个解耦合的服务。

Consul,zookeeper 等中间件,就是做这个透明转换的,也就是服务发现。这里简单测试 consul 作为服务发现的实现。

Consul 是一种服务解耦解决方案(service mesh solution,纠结了好久不知道怎么翻译),提供具有服务发现,配置和分段功能的全功能控制系统(control plane)。
这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建完整的服务解耦。即便是用了谷歌翻译的情况下,这段翻译纠结了半天,不知道怎么翻译合适。

如下是按照自己对 consul 做服务发现的理解,简单整理的逻辑结构图,其原理还是比较容易理解的。

Consul is a service mesh solution providing a full featured control plane with service discovery, configuration, and segmentation functionality. Each of these features can be used individually as needed, or they can be used together to build a full service mesh. Consul requires a data plane and supports both a proxy and native integration model. Consul ships with a simple built-in proxy so that everything works out of the box, but also supports 3rd party proxy integrations such as Envoy. https://www.consul.io/intro/index.html

它提供如下几个关键功能:

服务发现:

Consul 的某些客户端可以提供一个服务,例如 api 或者 mysql,其它客户端可以使用 Consul 去发现这个服务的提供者。

使用 DNS 或者 HTTP,应用可以很容易的找到他们所依赖的服务。

健康检查:
Consul 客户端可以提供一些健康检查,这些健康检查可以关联到一个指定的服务(服务是否返回 200 OK),也可以关联到本地节点(内存使用率是否在 90% 以下)。

这些信息可以被一个操作员用来监控集群的健康状态,被服务发现组件路由时用来远离不健康的主机。

键值存储:
应用可以使用 Consul 提供的分层键值存储用于一些目的,包括动态配置、特征标记、协作、leader 选举等等。通过一个简单的 HTTP API 可以很容易的使用这个组件。
多数据中心:
Consul 对多数据中心有非常好的支持,这意味着 Consul 用户不必担心由于创建更多抽象层而产生的多个区域。

Consul 被设计为对 DevOps 群体和应用开发者友好,他非常适合现代的、可伸缩的基础设施。

本文基于 docker 来实现 consul 的服务发现配置,方法 consul agent 是通过 json 注册的模式实现服务注册,
其中 consul 的服务端是 3 节点的集群,客户点是 6 节点 3 主 3 从的 redis 服务器集群,consul 实现 redis 集群中读写服务注册于发现。
尽管 Redis cluster 有多 IP 方式驱动连接,这里仅仅为了测试“服务发现”的。
其实本来想测试 MySQL 单主模式的 MGR,实现读写分离的服务发现,但是 MySQL 有点太重了,机器配置不够,所以做了 Redis 的集群来测试服务发现

consul 服务端集群安装配置
作为服务发现的载体,consul 是可以使用单节点运行的,作为解析服务的载体,是一个非常重要的角色,集群化具有更强的抗灾性,因此更多的时候是以多节点集群的方式运行解析服务的这个载体。
这里使用三个节点作为 consul 的集群服务端来运行,三个 consul 的服务节点 IP 分别是:172.18.0.11,172.18.0.12,172.18.0.13,需要固定 IP

docker network create –subnet=172.18.0.11/16 mynetwork

docker run -itd –name consul01 –net mynetwork –ip 172.18.0.11 -v /usr/local/docker_file/consul01/:/usr/local/ CentOS 

docker run -itd –name consul02 –net mynetwork –ip 172.18.0.12 -v /usr/local/docker_file/consul02/:/usr/local/ centos 

docker run -itd –name consul03 –net mynetwork –ip 172.18.0.13 -v /usr/local/docker_file/consul03/:/usr/local/ centos 

分别在每个容器中创建 consul 服务(unzip consul_1.6.2_linux_amd64.zip 解压缩即可,非常简单)

三个容器节点的 server.json 节点配置文件如下,唯一的区别就是 bind_addr 指定为当前节点的 IP
如下是 172.18.0.11 节点的配置,不同节点仅需修改 bind_addr 为对应机器(容器)的 IP

/usr/local/server.json
{
    “datacenter”: “dc1”,
    “data_dir”: “/usr/local/”,
    “log_level”: “INFO”,
    “server”: true,
    “bootstrap_expect”: 3,
    “bind_addr”: “172.18.0.11”,
    “client_addr”: “0.0.0.0”,
    “start_join”: [“172.18.0.11″,”172.18.0.12″,”172.18.0.13”],
    “ui”:true
}

依次登录三个容器中,以 server 模式启动 consul 服务
./consul agent -server -config-dir=/usr/local > /usr/local/consul.log &
由于配置文件中制定了集群的 IP 列表,因此无需显式加入集群(cluster join),正常情况下,启动三个节点后,会自动组成一个集群,并且自动选举出来一个 leader。
consul 集群服务的状态
./consul members –http-addr 172.18.0.11:8500
./consul operator raft list-peers -http-addr=172.18.0.12:8500

consul 客户端安装配置

容器客户端节点安装,6 个节点 IP 分别是:172.18.0.21,172.18.0.22,172.18.0.23,172.18.0.24,172.18.0.25,172.18.0.26
docker run -itd –name redis01 –net mynetwork –ip 172.18.0.21 -v /usr/local/docker_file/redis01/:/usr/local/ centos 
docker run -itd –name redis02 –net mynetwork –ip 172.18.0.22 -v /usr/local/docker_file/redis02/:/usr/local/ centos 
docker run -itd –name redis03 –net mynetwork –ip 172.18.0.23 -v /usr/local/docker_file/redis03/:/usr/local/ centos 
docker run -itd –name redis04 –net mynetwork –ip 172.18.0.24 -v /usr/local/docker_file/redis04/:/usr/local/ centos 
docker run -itd –name redis05 –net mynetwork –ip 172.18.0.25 -v /usr/local/docker_file/redis05/:/usr/local/ centos 
docker run -itd –name redis06 –net mynetwork –ip 172.18.0.26 -v /usr/local/docker_file/redis06/:/usr/local/ centos

 
6 个 client 节点的配置以及服务定义,服务探测脚本如下
如下是 172.18.0.21 节点的配置,不同节点仅需修改 bind_addr 为对应机器(容器)的 IP

client.json
{
  "data_dir": "usr/local/consuldata",
  "enable_script_checks": true,
  "bind_addr": "172.18.0.21",
  "retry_join": ["172.18.0.11","172.18.0.12","172.18.0.13"],
  "retry_interval": "30s",
  "rejoin_after_leave": true,
  "start_join": ["172.18.0.11","172.18.0.12","172.18.0.13"]
}
分别启动三个 client 节点的 consul 服务,以 client 的模式运行,启动后,正常情况下会自动加入到 consul 的服务端集群中。
./consul agent -config-dir=/usr/local/consuldata > /usr/local/consuldata/consul.log &
./consul members –http-addr 172.18.0.11:8500
基于 Docker 的 Consul 集群实现服务发现
 
 

consul 客户端代理服务注册

6 个容器节点依次安装 redis,做成一个集群(步骤略),这里的 consul 客户端代理的是一个 3 中 3 从的 Redis 集群,这里不列出来 Redis 集群的安装。
Redis 集群安装参考 https://www.cnblogs.com/wy123/p/12012848.html,还是非常方便的,在本地(容器节点)一键创建 6 个节点 3 主 3 从的集群。
其中主节点是 172.18.0.21,172.18.0.22,172.18.0.23,从节点是 172.18.0.24,172.18.0.25,172.18.0.26

基于 Docker 的 Consul 集群实现服务发现

这里是使用 w-master-redis-8888.service.consul 名字作为三个 redis 集群节点的服务代理。
172.18.0.21 节点上的 redis-master-8888.json(172.18.0.22,172.18.0.23,172.18.0.24,172.18.0.25,172.18.0.26 类同,仅需修改 address)

{
  "services": 
  [
    {
      "name": "w-master-redis-8888",
      "tags": ["master"],
      "address": "172.18.0.21",
      "port": 8888,
      "checks": [
        {"args":["sh","-c","/usr/local/consuldata/check_redis_master.sh 172.18.0.21 8888 ******"],
         "Shell":"/bin/bash",
         "interval": "15s"
        }
      ]
    }
  ]
}

redis-slave-8888.json 

{
  "services": 
  [
    {
      "name": "r-slave-redis-8888",
      "tags": ["master"],
      "address": "172.18.0.21",
      "port": 8888,
      "checks": [
        {"args":["sh","-c","/usr/local/consuldata/check_redis_slave.sh 172.18.0.21 8888 ******"],
         "Shell":"/bin/bash",
         "interval": "15s"
        }
      ]
    }
  ]
}

Consul client 节点的 Redis 主节点(写节点)服务检查脚本 check_redis_master.sh
以下脚本来源于 https://www.cnblogs.com/gomysql/p/8010552.html,做了简单的修改,在节点的身份判断逻辑上需要加强。

#!/bin/bash
host=$1
myport=$2
auth=$3
if [! -n "$auth" ]
then
auth='\"\"'
fi
comm="/usr/local/redis_instance/redis8888/bin/redis-cli -h $host -p $myport -a $auth " 
role=`echo 'INFO Replication'|$comm |grep -Ec 'role:master'`
echo 'INFO Replication'|$comm
if [$role -ne 1 ]
then
    exit 2
fi

Consul client 节点的 Redis 从节点服务检查脚本 check_redis_slave.sh

#!/bin/bash
host=$1
myport=$2
auth=$3
if [! -n "$auth" ]
then
auth='\"\"'
fi
comm="/usr/local/redis_instance/redis8888/bin/redis-cli -h $host -p $myport -a $auth "
role=`echo 'INFO Replication'|$comm |grep -Ec 'role:slave'`
echo $role
echo 'INFO Replication'|$comm


if [$role -ne 1 ]
then
    exit 2
fi

 

Consul 服务发现

redis 集群配置成功后,重新加载代理服务,consul reload,一切正常的话,consul 服务端就可以解析配置的服务了。
如下注册了两个服务,分别是 r -slave-redis-8888,w-master-redis-8888,分别代表 Redis 集群的读写节点。

基于 Docker 的 Consul 集群实现服务发现

可以看到,成功地解析了 w-master-redis-8888.service.consul 这个服务,映射到 172.18.0.21,172.18.0.22,172.18.0.23 三个节点。
需要注意的是,这三个节点都是写节点,这里仅仅是为了实现服务发现(尽管 redis 有多 IP 的驱动支持)
基于 Docker 的 Consul 集群实现服务发现

r-slave-redis-8888.service.consul 服务的解析,指向了三个从节点,172.18.0.24,172.18.0.25,172.18.0.26

基于 Docker 的 Consul 集群实现服务发现

故障转移之后的服务发现: 模拟主节点故障,对 172.18.0.21 节点手动故障转移,现在 172.18.0.21 与 172.18.0.24 角色交换

基于 Docker 的 Consul 集群实现服务发现

Redis 集群故障转以后的服务发现解析结果 对于 w -master-redis-8888.service.consul 这个服务,成功解析到 172.18.0.24,172.18.0.22,172.18.0.23 三个主节点
基于 Docker 的 Consul 集群实现服务发现

Redis 集群故障转以后的服务发现解析结果 对于 w -master-redis-8888.service.consul 这个服务,成功解析到 172.18.0.24,172.18.0.22,172.18.0.23 三个主节点
基于 Docker 的 Consul 集群实现服务发现

遇到的问题:
1,cosnul 服务端集群的时候,clustercenter 一开始自定义了一个名称 myconsule_datacenter, 导致 client 节点死活加不进来, 按照默认的 dc1 就没有问题
目前还不理解这个 datacenter 的命名规则是什么?
2,容器节点中的 shell 脚本要授予可执行权限 chmod +x check_XXX.sh
3,其他异常问题,一定要看日志,搜索一下基本上都有结果。
以下纯粹是 Redis 集群的问题,与 Consul 没有直接关系,仅作为本测试中遇到的问题。
4,容器节点的 Redis 集群时,需要移除 bind_ip 的 127.0.0.1 节点,直接配置 docker 创建容器时候的 IP,创建集群的时候会一致等待,waiting for the cluster to join
这一点 redis-cli –cluster 做的很扯淡,明明找不到节点,还要死等,不人为终止的话,他会一直 waiting
5,Redis 集群时候,因为主从都是相对的,需要相互识别对方,主从节点都要指定“masterauth”和“requirepass”,且密码一致,否则执行 cluster  failover 提示成功,但故障转移不成功
6,遇到一个灵异的问题(之前单机多实例的时候也遇到过),在启动容器上的 Redis 服务的时候,如果使用绝对路径启动,在创建集群的时候会出现从节点无法添加到集群中去的情况,停止服务,以相对路径方式重启之后就没有这个问题

总的来说 consul 这个中间件使用起来还算是比较简单,配置也很清爽,不像某些中间件令人作呕的配置结构(mycat???)
这里没有配置多数据中心模式,仅配置了单数据中心模式,作为一款服务发现的中间件,是完全没有问题的,尤其是作为 MySQL 集群不支持多 IP 连接驱动的数据库连接。

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-21发表,共计7239字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中