边侧高可用解决方案

2023-08-01
4分钟阅读时长

边侧服务高可用其实就是当年服务还没上云的时候,使用的那套技术栈。不过稍微有些不同的是,边缘计算需要考虑完全封闭的局域网,有点像组态软件的场景。

基于域名

本地域名一般使用.local/.lan之类的后缀,避免和.com等云上域名冲突。

基于域名的高可用显然需要依赖DNS来解决,简单的思路就是:

  1. 为私有域名配置多个后端host ip;
  2. 私有域名自动探测后端的存活性(即健康检查);
  3. 当DNS解析的请求过来时,如果是配置的私有域名(或其子域名),则随机(或者其他负载均衡策略)返回一个健康的ip地址;

这个需求最简单的解决方案是使用CoreDNS的插件机制自己写一个插件,存活探测使用ping即可。

基于虚拟IP

这个其实也是成熟技术栈,就是基于LVS的Keepalived. 不过要注意的是这玩意仅支持Linux,Windows平台可以考虑使用WSFC(Windows Server Failover Clustering)来实现类似的功能。不过该组件也是仅支持windows server,普通的家用操作系统是不行的。

Keepalived原理概述

Keepalived底层基于linux内核中的IPVS,即LVS模块,后者提供了负载均衡的功能。Keepalived则主要基于VRRP协议(即虚拟路由冗余协议)解决了高可用(单点故障)问题。

在多个节点上安装Keepalived,通过配置使其中一个成为master,其他结点都是backup. 外部服务通过master节点的**虚拟IP(vip)**地址访问结点上的服务。如果边侧是k3s环境,由于自带了LoadBalancer,所以只要指向任意一个k3s结点都可以访问暴露出来的服务。所以可以在k3s的server节点上都装上keepalived, 第一台初始化成功的作为master,其他的作为backup即可。

当master节点宕机时,backup节点会根据配置选举出新的master,这个新的master接管了vip,所以客户端访问该vip的流量就会自动切换过来。

vrrp设计是给路由器使用的,是将多个路由器视为一个路由器,所以它的算法其实比较简单,见下图:

Master设备选举过程

默认情况下,所有节点之间通过UDP组播通信,如果在云上也可以改为单播。选举主要需要配置的参数是抢占策略和优先级数值。

需要注意的是,存在多个master的可能性,不过对于k3s而言这个问题不大。k3s的server节点本来就是等价的,对于LoadBalancer服务而言更是如此。

配置示例

一个比较简单的配置如下:

global_defs {
   vrrp_skip_check_adv_addr
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state BACKUP     # 建议都设成BACKUP,不要直接指定MASTER
    nopreempt        # 不抢占,避免来回切换master 
    interface enp3s0 # 真实网卡的名称
 
    virtual_router_id 51 # VRID标记,多个集群不能重复
    priority 80			 # 优先级,建议配置的不同
    advert_int 1		 # 检测的默认时间,默认1s
    authentication {	  # 认证
        auth_type PASS
        auth_pass 1111	  # 同一个集群内的认证密码应该一样	
    }
    virtual_ipaddress {    # 设置VIP,一般一个就行了
        172.16.11.111
    }
}

virtual_server 172.16.11.111 { # VIP与真实IP的映射配置,可以具体到端口
    protocol *				 # 支持所有协议,可选TCP/UDP/SCTP

    real_server 172.16.11.66 { # 真实网卡的ip地址
        weight 1
    }
}

如果仅仅是为了将虚拟ip的流量转发到真实ip,上面的配置就够用了。主要需要修改的就是主机的网卡名称和真实ip,以及虚拟的ip地址。

启动命令:keepalived -f /etc/keepalived/keepalived.conf,建议设置systemd启动:

[Unit]
Description=LVS and VRRP High Availability Monitor
After=syslog.target network.target

[Service]
Type=forking
PIDFile=/var/run/keepalived.pid
KillMode=control-group
ExecStart=/usr/sbin/keepalived -D -f /etc/keepalived/keepalived.conf
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID

[Install]
WantedBy=multi-user.target

静态编译方法

官方只提供了源码,可以使用docker buildx来完成静态编译,Dockerfile如下:

FROM alpine as build
RUN if [ -f /etc/apk/repositories ];then sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories; fi && \
    if [ -f /etc/apt/sources.list ];then sed -ri 's/(deb|security).debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list; fi && \
    if [ ! -e /etc/nsswitch.conf ];then echo 'hosts: files dns myhostname' > /etc/nsswitch.conf; fi  && \
    apk --no-cache add \
        binutils \
        file \
        file-dev \
        gcc \
        glib \
        glib-dev \
        ipset \
        ipset-dev \
        iptables \
        iptables-dev \
        libmnl-dev \
        libnftnl-dev \
        libnl3 \
        libnl3-dev \
        make \
        musl-dev \
        net-snmp-dev \
        openssl \
        openssl-dev \
        openssl-libs-static \
        pcre2 \
        pcre2-dev \
        autoconf \
        automake zlib-static  alpine-sdk linux-headers  libmnl-static
WORKDIR /opt
RUN wget http://ghproxy.com/https://github.com/acassen/keepalived/archive/refs/tags/v2.2.8.tar.gz && tar xzvf v2.2.8.tar.gz && mv ./keepalived-2.2.8 /opt/keepalived

RUN set -ex && \
    cd /opt/keepalived && \
    ./autogen.sh && \
    CFLAGS='-static -s' LDFLAGS=-static ./configure  --disable-dynamic-linking \
    --prefix=/usr \
    --exec-prefix=/usr \
    --bindir=/usr/bin \
    --sbindir=/usr/sbin \
    --sysconfdir=/etc \
    --datadir=/usr/share \
    --localstatedir=/var \
    --mandir=/usr/share/man \
    --enable-bfd \
    --enable-snmp \
    --enable-snmp-rfc \
    --enable-nftables \
    --enable-regex \
    --enable-json  --with-init=systemd --enable-vrrp --enable-libnl-dynamic
RUN set -ex && \
    cd /opt/keepalived && \
    make && \
    make DESTDIR=/install_root install && \
    find /install_root && \
    rm -rf /install_root/usr/share

FROM scratch AS bin
COPY --from=build /install_root /

运行

docker buildx build . --platform linux/amd64 --target bin --output .

之后在usr/sbin/下就可以看到静态编译好的二进制文件了。注意libnl仍然是动态链接的,需要安装依赖:

yum install -y libnl3 libnl3-devel

apt install -y libnl-3-dev

其他方案

Keepalived是比较古老的方案,现代集群一般使用raft来进行选举,也可以考虑其他方案.

不过在边侧用keepalived其实够了,因为该软件最开始就是为了解决局域网问题的写的。

上一页 Sqlx备忘录
下一页 边侧监控选型