背景介绍

最近,我们部署了Oceanbase数据库(以下简称OB),并将部分业务迁移至OB中运行。在部署过程中,我们虽然配置了3个OBProxy,但没有为它们设置高可用配置,应用被固定到某一个OBProxy 上,这使我们在实际的运维工作中遇到了诸多不便。例如,当需要对OB集群中的某个主机进行维护时,我们必须提前与业务部门沟通,协商停机时间,并要求业务方配合关停服务,这样的流程不仅繁琐,而且给业务方带来了不佳的体验。

由于在网上没有看到如何利用开源组件,实现OBProxy的高可用的内容,以提高OB集群对于故障、停机等服务不可用情况的容忍度,所以,我们尝试用HAproxy作为HA组件来反代OBProxy,并将其记录与分享给大家参考。如有更好的建议,欢迎随时留言沟通。

拓扑介绍

未命名文件.png

准备工作

主机配置:

系统: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

最后成功连接

image.png

Logo

了解最新的技术洞察和前沿趋势,参与 OceanBase 定期举办的线下活动,与行业开发者互动交流

更多推荐