如何用 HAproxy 实施高可用部署 | OceanBase 实践
背景介绍
最近,我们部署了Oceanbase数据库(以下简称OB),并将部分业务迁移至OB中运行。在部署过程中,我们虽然配置了3个OBProxy,但没有为它们设置高可用配置,应用被固定到某一个OBProxy 上,这使我们在实际的运维工作中遇到了诸多不便。例如,当需要对OB集群中的某个主机进行维护时,我们必须提前与业务部门沟通,协商停机时间,并要求业务方配合关停服务,这样的流程不仅繁琐,而且给业务方带来了不佳的体验。
由于在网上没有看到如何利用开源组件,实现OBProxy的高可用的内容,以提高OB集群对于故障、停机等服务不可用情况的容忍度,所以,我们尝试用HAproxy作为HA组件来反代OBProxy,并将其记录与分享给大家参考。如有更好的建议,欢迎随时留言沟通。
拓扑介绍
准备工作
主机配置:
系统:https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso内核:3.10.0-1160.el7.x86_64
$ grubby --update-kernel=ALL --args="numa=off"
$ grubby --update-kernel=ALL --args="transparent_hugepage=never"
$ systemctl stop postfix.service
$ systemctl disable postfix
$ systemctl disable auditd
$ systemctl disable kdump
$ systemctl stop firewalld.service
$ systemctl disable firewalld.service
$ sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
$ setenforce 0
$ sed -i "s/\#UseDNS yes/UseDNS no/g" /etc/ssh/sshd_config
$ sed -i "s/GSSAPIAuthentication yes/GSSAPIAuthentication no/g" /etc/ssh/sshd_config
YUM源准备:
# 备份
$ mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
$ mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
$ mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
# 下载Base源
$ curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
$ sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
# 下载epel源
$ curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
$ yum clean all
$ yum makecache
内核参数
$ cat >> /etc/sysctl.conf << EOF
# for oceanbase
## 修改内核异步 I/O 限制
fs.aio-max-nr=1048576
## 网络优化
net.core.somaxconn = 2048
net.core.netdev_max_backlog = 10000
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.ip_local_port_range = 3500 65535
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_slow_start_after_idle=0
vm.swappiness = 0
vm.min_free_kbytes = 2097152
fs.file-max = 6573688
# 修改进程可以拥有的虚拟内存区域数量
vm.max_map_count = 655360
# 此处为 OceanBase 数据库的 data 目录
kernel.core_pattern = /data/core-%e-%p-%t
EOF
$ sysctl -p
$ cat >>/etc/security/limits.conf <<EOF
* soft nproc 655300
* hard nproc 655300
* soft nofile 655300
* hard nofile 655300
* soft core unlimited
* hard core unlimited
* soft stack unlimited
* hard stack unlimited
admin soft nofile 655350
admin hard nofile 655350
admin soft stack unlimited
admin hard stack unlimited
admin soft nproc 655360
admin hard nproc 655360
EOF
$ cat >>/etc/security/limits.d/20-nproc.conf <<EOF
* soft nproc 655300
* soft nofile 655300
* soft core unlimited
* soft stack unlimited
root soft nproc unlimited
EOF
基础软件包安装
$ yum install -y tree nmap dos2unix lrzsz nv lsof wget tcpdump htop iftop iotop sysstat nethogs
$ yum install -y psmisc net-tools bash-completion vim-enhanced
# 安装bash命令tab自动补全组件
$
# 安装vim编辑器
$ yum -y install vim screen lrzsz tree psmisc
# 安装压缩解压工具
$ yum -y install zip unzip bzip2 gdisk
# 安装网络及性能监控工具
$ yum -y install telnet net-tools sysstat iftop lsof iotop htop dstat
到这一步,最好重启一下机器。
安装HAproxy
安装HAproxy
两台机器都采用相同的操作
$ yum install -y haproxy
验证软件包是否被正确安装
$ rpm -qa | grep haproxy
haproxy-1.5.18-9.el7_9.1.x86_64
版本可能与本文存在差异,但一定要高于1.4.9
准备一个数据目录,如果有条件,可以把数据目录单独mount
到一个磁盘上面
$ mkdir -p /data/haproxy
$ chown -R haproxy:haproxy /data/haproxy
准备HAproxy的配置文件
备份原始的配置文件(两个节点都需要操作)
mv /etc/haproxy/haproxy.cfg{,.bak}
节点OBHA-T1
的配置文件(/etc/haproxy/haproxy.cfg
):
## https://cloud.tencent.com/developer/article/2046159
# 全局配置主要用于设定义全局参数,属于进程级的配置,通常和操作系统配置有关
global
# 定义全局的syslog服务器,接收haproxy启动和停止的日志。最多可以定义两个;
# log <address> <facility> [max level [min level]]
log 127.0.0.1 local0 err
# 设定每haproxy进程所接受的最大并发连接数,当达到此限定连接数后将不再接受新的连接。该参数特指和客户端的连接数,不包括和服务端的连接。等同于命令行选项"-n";"ulimit -n"就是根据此值进行自动调整的;
maxconn 8000
# 设定每进程能够打开的最大文件描述符数量,默认haproxy会自动进行计算,因此不推荐修改此选项;(不建议设置项)
#ulimit-n 16384
# 和多进程haproxy有关,由于不建议使用多进程,所以也不建议设置此项。但建议设置为"stats socket"将套接字和本地文件进行绑定,如"stats socket /var/lib/haproxy/stats"。
#stats timeout 30s
# 修改haproxy工作目录至指定目录,可提升haproxy安全级别,但要确保必须为空且任何用户均不能有写权限;
chroot /data/haproxy
# 以指定的UID或用户名身份运行haproxy进程;
user haproxy
# 以指定的GID或组名运行haproxy,建议使用专用于运行haproxy的GID,以免因权限问题带来风险;
group haproxy
# 让haproxy以守护进程的方式工作于后台,等同于命令行的"-D"选项,当然,也可以在命令行中以"-db"选项将其禁用;(建议设置项)
daemon
# (配置默认参数,这些参数可以被用到frontend,backend,Listen组件)
# 在此部分中设置的参数值,默认会自动引用到下面的frontend、backend、listen部分中,
# 因引,某些参数属于公用的配置,只需要在defaults部分添加一次即可。
# 而如果frontend、backend、listen部分也配置了与defaults部分一样的参数,Defaults部分参数对应的值自动被覆盖。
defaults
# 所处理的类别(7层代理http,4层代理tcp)
mode tcp
# 最大连接数
maxconn 6000
log global
# 日志类别为http日志格式
option httplog
# 不记录健康检查日志信息
option dontlognull
# 3次连接失败就认为服务器不可用,也可以通过后面设置
retries 3
# 设置连接超时时间
timeout connect 10s
# 设置连接超时时间
timeout client 1m
# 设置服务器超时时间
timeout server 1m
# 默认队列超时时间
timeout queue 1m
# 设置心跳检查超时时间
timeout check 10s
# 默认持久连接超时时间
# timeout http-keep-alive 15s
# 默认http请求超时时间
# timeout http-request 10s
# ( 接收请求的前端虚拟节点,Frontend可以更加规则直接指定具体使用后端的backend)
# frontend是在haproxy 1.3版本以后才引入的一个组件,同时引入的还有backend组件。
# 通过引入这些组件,在很大程度上简化了haproxy配置文件的复杂性。
# forntend可以根据ACL规则直接指定要使用的后端backend。
frontend obrsproxy
bind 0.0.0.0:2883
bind 127.0.0.1:2883
mode tcp
option tcplog
default_backend obrsproxy
# (后端服务集群的配置,真实服务器,一个Backend对应一个或者多个实体服务器)
# 在HAProxy1.3版本之前,HAProxy的所有配置选项都在这个部分中设置。
# 为了保持兼容性,haproxy新的版本依然保留了listen组件配置试。两种配置方式任选一中。
backend obrsproxy
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server OBC-T1 192.168.1.36:2883 check
server OBC-T2 192.168.1.37:2883 check
server OBC-T3 192.168.1.38:2883 check
# (Fronted和backend的组合体) 比如haproxy实例状态监控部分配置
# 定义一个监控页面,监听在18080端口,并启用了验证机制
Listen stats
# 设置模式为http
mode http
# haroxy的ip地址和端口
bind 192.168.1.33:18080
# 错误日志记录
log 127.0.0.1 local3 err
# 设置监控页面刷新时间:30s
stats refresh 30s
stats enable
# 隐藏统计页面的HAproxy版本信息
stats hide-version
# 设置监控页面的url
stats uri /haproxyadmin?stats #开启网页访问
# 设置页面提示信息
stats realm Haproxy\ Statistics
# 用户名和密码
stats auth admin:admin
# 设置手工启动/禁用,后端服务器(haproxy-1.4.9以后版本)
stats admin if TRUE
节点OBHA-T2
的配置文件(/etc/haproxy/haproxy.cfg
):
global
log 127.0.0.1 local0 err
maxconn 8000
chroot /data/haproxy
user haproxy
group haproxy
daemon
defaults
mode tcp
maxconn 6000
log global
option httplog
option dontlognull
retries 3
timeout connect 10s
timeout client 1m
timeout server 1m
timeout queue 1m
timeout check 10s
frontend obrsproxy
bind 0.0.0.0:2883
bind 127.0.0.1:2883
mode tcp
option tcplog
default_backend obrsproxy
backend obrsproxy
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server OBC-T1 192.168.1.36:2883 check
server OBC-T2 192.168.1.37:2883 check
server OBC-T3 192.168.1.38:2883 check
Listen stats
mode http
bind 192.168.1.34:18080
log 127.0.0.1 local3 err
stats refresh 30s
stats enable
stats hide-version
stats uri /haproxyadmin?stats #开启网页访问
stats realm Haproxy\ Statistics
stats auth admin:admin
stats admin if TRUE
启动服务
$ systemctl enable --now haproxy.service
$ systemctl status haproxy.service
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2024-06-21 12:00:15 CST; 1min 13s ago
Main PID: 18700 (haproxy-systemd)
CGroup: /system.slice/haproxy.service
├─18700 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
├─18701 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
└─18702 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Jun 21 12:00:15 OBHA-T2 systemd[1]: Stopped HAProxy Load Balancer.
Jun 21 12:00:15 OBHA-T2 systemd[1]: Started HAProxy Load Balancer.
Jun 21 12:00:15 OBHA-T2 haproxy-systemd-wrapper[18700]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
安装keepalived
安装keepalived
两台机器都采用相同的操作
$ yum install -y keepalived
验证软件包是否被正确安装
$ rpm -qa | grep keepalived
keepalived-1.3.5-19.el7.x86_64
版本可以与本文不一致
准备keepalived的配置文件
备份2部机器上的keepalived的配置文件:
$ mv /etc/keepalived/keepalived.conf{,.bak}
创建OBHA-T1
上的keepalived
配置文件/etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id OBHA-T1
}
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 5
weight -5
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface ens192
mcast_src_ip 192.168.1.33
virtual_router_id 35
priority 101
nopreempt
advert_int 2
authentication {
auth_type PASS
auth_pass OB_HA_AUTH
}
virtual_ipaddress {
192.168.1.35
}
track_script {
chk_haproxy
} }
创建OBHA-T2
上的keepalived
配置文件/etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id OBHA-T1
}
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 5
weight -5
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface ens192
mcast_src_ip 192.168.1.34
virtual_router_id 35
priority 100
nopreempt
advert_int 2
authentication {
auth_type PASS
auth_pass OB_HA_AUTH
}
virtual_ipaddress {
192.168.1.35
}
track_script {
chk_haproxy
} }
注意: 本节所述的配置文件中的interface指的是服务器的网卡名称,实际环境可能与本文有差异,以实际环境配置为准。 两部服务器上的keepalived的配置文件中virtual_router_id 的值必须相同。
准备keepalived的检测脚本
三台上的脚本一样,文件路径为/etc/keepalived/check_haproxy.sh
#!/bin/bash
err=0
for k in $(seq 1 3)
do
check_code=$(pgrep haproxy)
if [[ $check_code == "" ]]; then
err=$(expr $err + 1)
sleep 1
continue
else
err=0
break
fi
done
if [[ $err != "0" ]]; then
echo "systemctl stop keepalived"
/usr/bin/systemctl stop keepalived
exit 1
else
exit 0
fi
为检测脚本添加执行权限
$ chmod +x /etc/keepalived/check_haproxy.sh
启动服务
两台机器上的操作相同
$ systemctl daemon-reload
$ systemctl enable --now keepalived
检查服务
$ systemctl status keepalived.service
● keepalived.service - LVS and VRRP High Availability Monitor
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2024-06-21 13:54:54 CST; 40s ago
Process: 22784 ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
Main PID: 22785 (keepalived)
CGroup: /system.slice/keepalived.service
├─22785 /usr/sbin/keepalived -D
├─22786 /usr/sbin/keepalived -D
└─22787 /usr/sbin/keepalived -D
$ ping -c 4 192.168.1.35
PING 192.168.1.35 (192.168.1.35) 56(84) bytes of data.
64 bytes from 192.168.1.35: icmp_seq=1 ttl=64 time=0.027 ms
64 bytes from 192.168.1.35: icmp_seq=2 ttl=64 time=0.058 ms
64 bytes from 192.168.1.35: icmp_seq=3 ttl=64 time=0.046 ms
64 bytes from 192.168.1.35: icmp_seq=4 ttl=64 time=0.034 ms
--- 192.168.1.35 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.027/0.041/0.058/0.012 ms
$ telnet 192.168.1.35 2883
Trying 192.168.1.35...
Connected to 192.168.1.35.
Escape character is '^]'.
J
5.6.25AKE=@js'b=��.�E%(9%L3U5HIwmysql_native_password