一:Kong的集群方案

Kong支持集群方案,可以加入多个Kong节点来保障服务的高可用性以及提高负载的能力,如下面官方图所示,多个kong组成的集群需要使用共享数据库,以保证集群数据的一致性。

【2】微服务架构-kong的集群化部署_第1张图片

(1)集群状态

检查集群的状态

$kong cluster reachability

检查群集的成员

$kong cluster members

(2)集群配置

集群配置包含以下几项

  • cluster_listen         用于与群集中其他节点之间通信的地址和端口。

默认值: 0.0.0.0:7946

  • cluster_listen_rpc     此节点用于与群集通信的地址和端口。。

默认值: 127.0.0.1:7373

  • cluster_advertise      指定向外广播的ip

默认值:none

  • cluster_encrypt_key    Base64编码的16字节密钥用于加密集群流量。

默认值:none

  • cluster_ttl_on_failure     集群健康检查的间隔

默认值: 3600

  • cluster_profile         集群间Ping和超时的时序配置文件。local , lan , wan 。

默认值: wan


二:节点间的发现

节点之间的发现采用的gossip协议,当Kong节点启动后,会将自己的IP信息加入到node列表,广播给任何其他的Kong节点,当另一个Kong节点启动后,会去读取数据库中的node列表,并将自己的信息加入到列表中。

三:容器方式部署集群

集群是为了保证服务的高可用性和提高服务的支撑能力,必然是要部署在多台独立服务器上。那么要使用容器部署,就必须要实现宿主机间的容器网络互通。


下面以rancher为例,在rancher上部署Kong集群。再分享一下部署的时候出现的一些问题。

docker-compose:

kong-database:
  p_w_picpath: postgres:9.4
  ports:
  - 5432:5432/tcp
  environment:
  - POSTGRES_USER=kong
  - POSTGRES_DB=kong
  labels:
    io.rancher.container.hostname_override: container_name
    io.rancher.container.pull_p_w_picpath: always
kong:
  p_w_picpath: kong
  links:
  -  kong-database:kong-database
  environment:
  - KONG_DATABASE=postgres
  - KONG_CASSANDRA_CONTACT_POINTS=kong-database
  - KONG_PG_HOST=kong-database
  ports:
  - 8000:8000/tcp
  - 8443:8443/tcp
  - 8001:8001/tcp
  - 7946:7946/tcp
  - 7946:7946/udp
  - 7373:7373/tcp
  labels:
    io.rancher.container.hostname_override: container_name
    io.rancher.container.start_once: true

rancher-compose:

.catalog:
  kong:
  scale: 3 
  kong-database:
  scale: 1

部署成功后,集群由1个数据库,三个kong容器,貌似没问题

【2】微服务架构-kong的集群化部署_第2张图片

然而,当通过sehll进入到容器内部,使用kong cluster reachability发现集群只有一个成员。

并且发现,节点是带着172.17.0.5这个地址,显然节点向外宣告了这个地址。

【2】微服务架构-kong的集群化部署_第3张图片

这是为什么呢?


因为我们知道Rancher的默认manage网络是10.42段的地址,能够跨宿主机实现容器互通。为什么会宣告172的地址呢?

【2】微服务架构-kong的集群化部署_第4张图片

我们用ip a命令查看,发现,原来eth0下面有两个ip,172和10.42的ip。

一个是docker0的默认的172段地址不能跨主机通信,一个是rancher的manage的10.42网络的地址。

【2】微服务架构-kong的集群化部署_第5张图片


显然!!!如果要想让集群节点之间成功通信,那么必须要使节点向外宣告的ip为10.42的地址才行


这就要用到上面配置中的cluster_advertise参数。

默认情况下

cluster_listen= 0.0.0.0:7946

cluster_advertise=NONE

在***、nat等情况下,网卡拥有多个IP地址,0.0.0.0就导致无法向外宣告正确的IP

这时就需要使用cluster_advertise:10.42.60.14:7946来指定广播的ip,

【2】微服务架构-kong的集群化部署_第6张图片

在后面修改的过程中发现,/usr/local/kong/kong.conf文件是不存在于镜像中的,而是kong进程启动的时候生成的。


后来发现是通过/usr/local/share/lua/5.1/kong/templates/kong_defaults.lua这个配置模板来生成的的配置文件,即使预先写好的配置文件,也会在kong进程启动后被替换掉。


所以只能修改配置文件的模板,/usr/local/share/lua/5.1/kong/templates/kong_defaults.lua将里面的

cluster_advertise = NONE替换成cluster_advertise = container_ip:7946


而container_ip是容器启动后才知道,但是当容器启动后,在进去容器,修改配置文件,重启进程也不太现实。


所以就需要我们在容器启动后,自动将IP信息配置到配置文件中,然后再启动容器。

梳理一下流程应该是

1:容器启动-->2:读取容器IP-->3:修改配置文件模板-->4:自动创建配置文件-->5:启动kong



利用官方kong镜像,重新打一下镜像

Dockerfile

FROM kong

#精简镜像缺少命令,copy ip命令
COPY ./ip /bin/

#在启动脚本中,查出容器ip
RUN sed -i "4i export RANCHER_IP=\`/bin/ip a|grep 10.42|sed 's/ //g'|awk -F'[t/]' '{print \$2}'\`" /docker-entrypoint.sh

#将容器IP替换到lua的配置模板中(直接改配置文件没用,因为是从模板copy过去覆盖的)
RUN sed -i "5i sed -i 's/cluster_advertise = NONE/cluster_advertise = '\$RANCHER_IP':7946/g' /usr/local/share/lua/5.1/kong/templates/kong_defaults.lua" /docker-entrypoint.sh

ENTRYPOINT ["/docker-entrypoint.sh"]

CMD ["kong","start"]
$docker build -t kong:rancher_cluster .

镜像打好后,使用上面的compose新启动服务,再进去容器看一下,发现集群已经组建成功了,向外宣告的是10.42的地址

【2】微服务架构-kong的集群化部署_第7张图片

于是乎!!!集群组建成功,可以随意增加集群节点个数。

【2】微服务架构-kong的集群化部署_第8张图片