文章

如何实现高可用

如何实现高可用

各位试想一个问题,你好不容易搭建好了一个微服务系统、一个Kubernetes集群或者PostgreSQL集群甚至是Redis集群,然后现在是你开始使用这个集群的时候了,外部访问这个高可用集群的时候你必然会有一个疑惑,最后应该使用哪个节点的作为流量入口呢?有经验的朋友可能会说了:“你傻呀,我直接访问集群节点,那这个节点废了之后不就无法访问了吗?肯定是单独配置负载均衡器进行转发呀!”。确实没有问题,说的很对,假设通过负载均衡器进行转发,那么如果负载均衡器本身又是如何实现高可用的呢?哪怕你负载均衡也是一个集群我最终应该使用哪个均衡节点作为流量入口?如果负载均衡本身是单节点,那负载均衡没有实现高可用的情况下,下级应用的高可用还叫高可用吗?所以实现流量入口本身的高可用才是真正意义上的高可用。不过很遗憾的事情是据我所知,很多技术从业人员下层应用上各种冗余,但是流量却是单一入口,比较诡异。如果你知道这个问题的存在,那么看到这里相信不少朋友已经意识到我今天想要说的东西了:VRRP协议

注意:本文所提到的高可用是指网络层、传输层和应用层的高可用;物理层的高可用不在本文讨论范围,因为物理层花钱就行,杠这个就没有意义

VRRP协议

虚拟路由冗余协议VRRP(Virtual Router Redundancy Protocol)这个名字翻译的有点不好,因为我们这种非网络专业的人角度来看Router或者路由一般指的是侠义上那个路由器设备,然后我们对路由器的理解其实是一个分配IP转发NAT的东西。但是实际上广义的Router的本意其实就是路由本身,简单来说路由就是控制流量设备。这么看VRRP就很清楚了,虚拟的并且是控制流量的同时冗余的协议;更加偏使用的说法就是:创建一个虚拟路由设备,然后使用这个设备对到达虚拟的 IP 数据包进行转发。最简单的说法就是,高可用流量入口。

通过上图和我提供的文字说明大家起码都知道VRRP的原理了,因为他是网络层实现冗余协议,所以对于下级应用与传输角度而言完全无感,就是一个凭空出现的IP地址,对这个地址的全部访问会自动转发到存活的VRRP服务节点。那么问题又来了,我们如何实现VRRP协议呢?

keepalived

目前在开源世界,我们如果想要实现VRRP最优选择应该只能是keepalived了,我甚至没有找到到第二个能够相提并论的可选项。不仅如此,在使用上keepalived这个东西过于简单并且非常符合直觉,通过简单的配置文件就可以正常驱动了。比如按照我们上面介绍VRRP协议是图片之中的网络架构,对应使用的配置文件应该如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vrrp_instance CLUSTER_VIP {
    state BACKUP              # 所有节点均为 BACKUP,选主由 priority 决定
    interface eth0            # 绑定的网卡
    virtual_router_id 42      # 三节点保持一致
    priority 150              # NodeA:150, NodeB:140, NodeC:130
    advert_int 1              # 每秒发送一次心跳
    authentication {
        auth_type PASS
        auth_pass mysecret    # 三节点保持一致
    }
    virtual_ipaddress {
        192.168.0.10/24        # 虚拟IP和掩码
    }
}

简单介绍一下:

  • CLUSTER_VIP:这个是随便写的名字,也就是我们VRRP服务的名称;
  • state:运行VRRP节点的模式,如果是设置为BACKUP则待定等待自动选举主节点,设置为MASTER是就手动指定主节点;
  • interface:对于该节点的物理网卡接口,因为VRRP使用物理网卡发送和接收多播心跳数据包,以协调主备状态;
  • virtual_router_id:内部使用的id,相当于对VRRP分组使用,我们单个入口IP就需要在三个节点保持一致;
  • priority:当前节点的权重,用于选举出主节点;

注意:上述配置文件是最简单的版本,生产使用需要结合服务健康检查进而判断节点的存活状态从而修正VRRP节点权重,如有需要自行参考官方文档

系统级运行keepalived

我们现在以Almalinux或者任何RHEL兼容版为例看看如何部署这个服务,下面的操作需要所有参与VRRP服务的节点都执行安装才行。

首先肯定是安装keepalived:

1
dnf install -y keepalived

编写配置文件,路径为:/etc/keepalived/keepalived.conf

1
# 这里直接使用上文的配置文件即可

启动并且配置开机自启动服务keepalived服务:

1
2
systemctl start keepalived
systemctl enable keepalived

docker运行keepalived

注意:不推荐,因为docker没有官方维护的镜像,同时社区维护的版本已经超过4年没有更新,非要用容器则建议自行制作最新版镜像

为了简单我直接提供一个docker-compose.yaml吧,各位自行修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: '3.8'
services:
  keepalived:
    image: osixia/keepalived:2.0.20
    restart: unless-stopped
    network_mode: host
    cap_add:
      - NET_ADMIN
      - NET_BROADCAST
      - NET_RAW
    environment:
      KEEPALIVED_INTERFACE: "eth0"
      KEEPALIVED_VIRTUAL_IPS: "192.168.0.10/24"
      KEEPALIVED_PASSWORD: "自行修改为你定义的密码"

如果你需要更加详细的镜像说明,这是该镜像的仓库地址

总结

本文仅仅是介绍了一下VRRP协议和实现该协议最简单的工具keepalived,虽然上述配置已经可以实现流量入口的高可用了,但是在生产环境使用的话还是比我这篇文章要复杂一些,比如说:

  1. 如何进行服务健康检查与权重动态调整
  2. 如何保证ARP 广播与网络稳定性
  3. 如何防止裂脑
  4. 如何与容器/云原生环境的集成
  5. 如何实现监控与告警
  6. 如何实现安全隔离与访问控制(如未授权设备伪造心跳包)
  7. 如何运维自动化与配置管理(如gitops)

不过话虽如此,一旦有了本文提供的思路,后续这些具体的实现其实也算是水到渠成,可以慢慢做加法,至少我们已经从零到一实现了流量入口的高可用,你说对不对?

本文由 唐玥璨 版权所有