0
点赞
收藏
分享

微信扫一扫

Keepalived+容器HAProxy进行负载均衡和检测实践

最近有个需求:有些特殊原因需要开启两个代理同时利用Keepalived来做负载均衡。方案:

  • HAProxy+Keepalived和HAProxy+Nginx分别实现两个用例,检测也方便;
  • HAProxy(容器)+Keepalived,主要是迎合某些特殊原因和需求都要使用HAProxy来进行代理和负载均衡。

说明:以上两种实现在单网口下都需要做好必要的网络端口分配。

环境说明

lb1(RockyLinux9.3): 192.168.0.11/24 lb2(RockyLinux9.3): 192.168.0.12/24 VIP: 192.168.0.10/24 网络端口,我配置服务器使用了端口绑定bond,此处为bond0,配置mode4(802.11ad),正式工程实践还是讲究点。

具体实现步骤:

1.部署HAProxy

关于单机容器,最近几年RedHat在推Podman,所以本次实践就以Podman来代替Docker来进行容器的创建。

具体代理和负载均衡此处不是重点,简要写下。

podman run --name internal-proxy -d \
  -p 8880:8888 \
  -p 8080:8080 \
  -v ./haproxy-internal.cfg:/usr/local/etc/haproxy/haproxy.cfg:Z \
  --restart always \
  docker.io/library/haproxy:2.8.9-alpine

上面有几个需要注意的地方,也是本人踩的坑。 说明

  1. 卷的挂载参数'Z'主要规避SELinux造成不能读取的问题,使用'z'也可以,区别是'Z'说明是不能被其他容器共享,当然'z'说明可以和其它容器共享;另外,还可以加上参数--privileged=true,这样的话与关闭SELinux等效,不是想要的状态。
  2. -d表示以daemon方式运行。

2.部署Keepalived

keepalived使用dnf安装,采用抢占模式。

2.1 keepalived.conf配置文件

lb1配置文件

#简单的头部,这里主要可以做邮件通知报警等的设置,此处就暂不配置了;
global_defs {
    router_id test # 修改自定义的id
    vrrp_skip_check_adv_addr # 如果通告与接收的上一个通告来自统一个master,则跳过检查(默认)
    vrrp_strict # 严格模式不支持节点单播(默认)
    vrrp_garp_interval 0 # arp报文发送延迟(默认)
    vrrp_gna_interval 0 # 消息发送延迟(默认)
}

vrrp_script chk_internal_proxy {
    script "/etc/keepalived/chk_internal_proxy.sh"  # 具体脚本路径
    interval 2  # 脚本循环运行间隔
    timeout 2 # 超时
    fall 2 # 间隔检测失败次数达标后设置该节点为不可用
    rise 1 # 间隔检测成功次数达标后设置该节点为可用
    weight 20 # 权重
}
#VRRP虚拟路由冗余协议配置
vrrp_instance VI_0 {       # VI_1 是自定义的名称;
    state MASTER           # MASTER表示是一台主设备,BACKUP表示为备用设备
    interface bond0        # 指定VIP需要绑定的物理网卡
    virtual_router_id 50   # VRID虚拟路由标识,也叫做分组名称,该组内的设备需要相同
    priority 100           # 定义这台设备的优先级 1-254;大于BACKUP

    advert_int 3           # 生存检测时的组播信息发送间隔,组内一致
    authentication {       # 设置验证信息,组内一致
        auth_type PASS     # 有PASS 和 AH 两种,常用 PASS
        auth_pass 12345678 # 密码
    }
    virtual_ipaddress {
        192.168.1.10/24 dev bond0  # 指定VIP地址,组内一致,可以设置多个IP
    }
    track_script {         # 使用在这个域中使用预先定义的脚本,上面定义的
        chk_internal_proxy
    }
}

lb2配置文件

#简单的头部,这里主要可以做邮件通知报警等的设置,此处就暂不配置了;
global_defs {
    router_id test # 修改自定义的id
    vrrp_skip_check_adv_addr # 如果通告与接收的上一个通告来自统一个master,则跳过检查(默认)
    vrrp_strict # 严格模式不支持节点单播(默认)
    vrrp_garp_interval 0 # arp报文发送延迟(默认)
    vrrp_gna_interval 0 # 消息发送延迟(默认)
}

vrrp_script chk_internal_proxy {
    script "/etc/keepalived/chk_internal_proxy.sh"  # 具体脚本路径
    interval 2  # 脚本循环运行间隔
    timeout 2 # 超时
    fall 2 # 间隔检测失败次数达标后设置该节点为不可用
    rise 1 # 间隔检测成功次数达标后设置该节点为可用
    weight 20 # 权重
}
#VRRP虚拟路由冗余协议配置
vrrp_instance VI_0 {       # VI_1 是自定义的名称;
    state BACKUP           # MASTER表示是一台主设备,BACKUP表示为备用设备
    interface bond0        # 指定VIP需要绑定的物理网卡
    virtual_router_id 50   # VRID虚拟路由标识,也叫做分组名称,该组内的设备需要相同
    priority 90           # 定义这台设备的优先级 1-254;小于MASTER

    advert_int 3           # 生存检测时的组播信息发送间隔,组内一致
    authentication {       # 设置验证信息,组内一致
        auth_type PASS     # 有PASS 和 AH 两种,常用 PASS
        auth_pass 12345678 # 密码
    }
    virtual_ipaddress {
        192.168.1.10/24 dev bond0  # 指定VIP地址,组内一致,可以设置多个IP
    }
    track_script {         # 使用在这个域中使用预先定义的脚本,上面定义的
        chk_internal_proxy
    }
}

说明

a. vrrp_script区域

keepalived只能做到对网络故障和keepalived本身的监控,即当出现网络故障或者keepalived本身出现问题时,进行切换。但是这些还不够,我们还需要监控keepalived所在服务器上的其他业务进程,比如说haproxy,keepalived+haproxy实现haproxy的负载均衡高可用,如果haproxy异常,仅仅keepalived保持正常,是无法完成系统的正常工作的,因此需要根据业务进程的运行状态决定是否需要进行主备切换。这个时候,我们可以通过编写脚本对业务进程进行检测监控。

如果配置了权重'weight',keepalived会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级。

  • 如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加
  • 如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少
  • 其他情况,维持原本配置的优先级,即配置文件中priority对应的值。 注意:
  1. 优先级会不断的提高或者降低
  2. 可以编写多个检测脚本并为每个检测脚本设置不同的weight
  3. 不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况 这样可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
b. 主备切换策略

在Keepalived集群中,其实并没有严格意义上的主、备节点,虽然可以在Keepalived配置文件中设置“state”选项为“MASTER”状态,但是这并不意味着此节点一直就是Master角色。控制节点角色的是Keepalived配置文件中的“priority”值,但是它并不控制所有节点的角色,另一个能改变节点角色的是在vrrp_script模块中设置的“weight”值,这两个选项对应的都是一个整数值,其中“weight”值可以是个负整数,一个节点在集群中的角色就是通过这两个值的大小决定的。 不设置weight 在vrrp_script模块中,如果不设置“weight”选项值,那么集群优先级的选择将由Keepalived配置文件中的“priority”值决定,而在需要对集群中优先级进行灵活控制时,可以通过在vrrp_script模块中设置“weight”值来实现。 设置weight vrrp_script 里的script返回值为0时认为检测成功,其它值都会当成检测失败; weight为正时,脚本检测成功时此weight会加到priority上,检测失败时不加;

  • 主失败: 主priority < 从priority + weight 时会切换。
  • 主成功:主priority + weight > 从priority + weight 时,主依然为主

weight 为负时,脚本检测成功时此weight不影响priority,检测失败时priority – abs(weight)

  • 主失败: 主priority – abs(weight) < 从priority 时会切换主从
  • 主成功: 主priority > 从priority 主依然为主
c. 检测脚本内容

针对容器充分利用了以下两个命令来对容器状态进行检测

  • podman container inspect <container_name>
  • podman container exists <container_name> 具体内容如下:
#!/bin/bash
if ! ( /usr/bin/podman container exists internal-proxy ); then
  exit 1
fi

chk=$( /usr/bin/podman container inspect -f '{{.State.Running}}' internal-proxy )
if  [ "$chk" == "true" ]; then
  exit 0
else
  exit 1
fi
d. SELinux对脚本执行的影响

上述检测脚本,在SELinx开启的情况下会报错大致如下:

systemctl status keepalived
...
...Keepalived_vrrp[...]: SECURITY VIOLATION - scripts are being executed but script_security not enabled
...Keepalived_vrrp[...]: /etc/keepalived/chk_internal_proxy.sh exited with status 1

查看文件上下文属性

$ ls -Z /etc/keepalived/check.sh
-rwxr-xr-x. root root system_u:object_r:etc_t:s0 /etc/keepalived/chk_internal_proxy.sh

更改文件上下文属性

$ sudo chcon -t keepalived_unconfined_script_exec_t /etc/keepalived/chk_internal_proxy.sh

当然关闭SELinux就没必要说了,不是我希望的。

sysctl配置
# enable ip forwarding
sysctl -w net.ipv4.ip_forward="1"

# This option seems to be required and allows
# applications to bind to ip addresses which does not exist
# on the system (yet). For example a service which might get the virtual
# ip address later.
sysctl -w net.ipv4.ip_nonlocal_bind="1"
firewall配置

配置允许VRRP协议

sudo firewall-cmd --permanent --new-service=VRRP
sudo firewall-cmd --permanent --service=VRRP --set-description="Virtual Router Redundancy Protocol"
sudo firewall-cmd --permanent --service=VRRP --set-short=VRRP
sudo firewall-cmd --permanent --service=VRRP --add-protocol=vrrp
sudo firewall-cmd --permanent --service=VRRP --set-destination=ipv4:224.0.0.18
sudo firewall-cmd --add-service=VRRP --permanent

参考资料:

  1. https://syntaxbug.com/0172891e5e/
  2. https://zhuanlan.zhihu.com/p/150670778
  3. https://www.ibm.com/docs/en/linux-on-systems?topic=available-keepalived-haproxy
举报

相关推荐

0 条评论