docker下用keepalived+Haproxy实现高可用负载均衡集群

版权声明:原创转载请注明出处,谢谢 https://blog.csdn.net/qq_21108311/article/details/82973763

先记录下遇到的坑,避免之后忘了;

花时间最多去解决的一个题是:在docker下启动haproxy服务后在这个docker服务内安装keepalived无法ping通的问题,虽然最后也是莫名其妙就好了,但是加强了不少对docker的理解和还需深入学习的地方。

为什么要用keepalived+haproxy实现docker下的高可用负载均衡?在不同环境下有哪些方式可以实现高可用负载均衡?

首先第一点,实现负载均衡并不是只有haproxy一个中间件,网上还有很多方案是用keepalived+LVS等等,所以对于docker下的高可用负载均衡不一定只有keepalived+haproxy。只是本次我是基于之前搭建的pxc集群进行继续搭建的,所以用的是haproxy。

为什么这里强调的是docker、keepalived?

首先我们运行环境是docker,keepalived的作用是抢占虚拟ip,docker环境下,镜像内的网段外网是无法访问的,所以我们需要一个外网在宿主机上映射到docker内的ip上,keepalived一方面可以映射ip到docker服务内,二可以在docker服务内强占虚拟ip。所以在docker搭建负载均衡的多种方案中都常见会出现keepalived。

为什么要抢占虚拟ip?为什么要用keepalived呢?

负载均衡中间件(haproxy,lvs)等等在实际中不可能只是单节点存在(单节点不需要keepalived),都要有冗余设计,即集群设计,和数据库集群不一样的是,docker中实现负载均衡中间件的集群是通过抢占一个ip地址实现的,有主备和主主方式,虽然方式不一样,但都有一个心跳检测的共同点,在主节点抢占虚拟ip时,主从节点上会有心跳检测线,如果发现主节点心跳检测连不上,则从节点会主动抢占ip实现数据不中断的冗余机制;

总结描述:由于是在docker环境下,我们要搭建负载均衡集群需要通过keepalived抢占虚拟ip实现,而负载均衡功能需要haproxy中间件实现,所以本次我搭建的是一个在docker环境下高可用的负载均衡方案是:keepalived+haproxy。

haproxy具体方法:

下载docker镜像;
Docker pull haproxy

重命名
docker tag docker.io/haproxy haproxy 

删除多余镜像
docker rmi docker.io/haproxy

ftp上传docker配置文件,目录自行定义,目录映射根据定义目录名映射

查看配置文件(需要编辑可编辑)
cat haproxy.cfg

启动创建docker-haproxy服务
docker run -it -d -p 4001:8888 -p 4002:3306 -v /data/haproxy/config:/usr/local/etc/haproxy --name haproxy01 --privileged --net=net1 --ip 172.20.0.07  haproxy

端口8888是监控页面端口,3006是MySQL服务端口,参数都可以在配置文件中调整


进入docker-haproxy服务
docker exec -it haproxy01 /bin/bash


启用配置文件(启用完配置文件才算是真的启动了haproxy服务)
haproxy -f /usr/local/etc/haproxy/haproxy.cfg

退出haproxy交互,回到宿主机
ctrl+D

haproxy配置信息:

global
	#工作目录
	chroot /usr/local/etc/haproxy
	#日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
	log 127.0.0.1 local5 info
	#守护进程运行
	daemon

defaults
	log	global
	mode	http
	#日志格式
	option	httplog
	#日志中不记录负载均衡的心跳检测记录
	option	dontlognull
    #连接超时(毫秒)
	timeout connect 5000
    #客户端超时(毫秒)
	timeout client  50000
	#服务器超时(毫秒)
    timeout server  50000

#监控界面	
listen  admin_stats
	#监控界面的访问的IP和端口
	bind  0.0.0.0:8888
	#访问协议
    mode        http
	#URI相对地址
    stats uri   /dbs
	#统计报告格式
    stats realm     Global\ statistics
	#登陆帐户信息
    stats auth  admin:abc123456
#数据库负载均衡
listen  proxy-mysql
	#访问的IP和端口(前面ip=0代表任何ip都可访问)
	bind  0.0.0.0:3306  
    #网络协议
	mode  tcp
	#负载均衡算法(轮询算法)
	#轮询算法:roundrobin
	#权重算法:static-rr
	#最少连接算法:leastconn
	#请求源IP算法:source 
    balance  roundrobin
	#日志格式
    option  tcplog
	#在MySQL中创建一个没有权限的haproxy用户,密码为空。Haproxy使用这个账户对MySQL数据库心跳检测
    option  mysql-check user haproxy
    server  NODE1 172.20.0.2:3306 check weight 1 maxconn 2000  
    server  NODE2 172.20.0.3:3306 check weight 1 maxconn 2000  
	server  NODE3 172.20.0.4:3306 check weight 1 maxconn 2000 
	server  NODE4 172.20.0.5:3306 check weight 1 maxconn 2000
	server  NODE5 172.18.0.6:3306 check weight 1 maxconn 2000
	#使用keepalive检测死链
    option  tcpka  

要解释配置文件真的可以写个单独的说明,我这里只说下链接数据库的几点,即option参数后面的;

NODE1+ip这个是指的PXC集群的docker镜像名和所制定的ip地址,这个要和数据库集群一致,后面的权重,最大链接数可以执行设置,也可以直接套用我的,其他的说明配置文件中都有;可直接使用;最后在网页上输入宿主机IP+监控端口+/dbs即可进入监控页面。

监控界面:

keepalived搭建:

keepalived的实现是要在docker服务内创建,最后宿主机中也要创建实现docker内外的连接;
docker服务内创建,我们需要进入到该服务并安装keepalived


进入docker-haproxy服务
docker exec -it haproxy01 /bin/bash

更新update,安装keepalived
apt-get update
apt-get install keepalived

安装vim 安装ifconfig命令 安装ping
apt-get install net-tools    
apt-get install iputils-ping


新建并写入一个keepalived的配置文件
vim /etc/keepalived/keepalived.conf


配置文件信息:
#取名为K1,可自定义
vrrp_instance  VI_1 {
#定义节点属性
    state  MASTER
	#定义虚拟网卡
    interface  eth0
	#定义组vriid
    virtual_router_id  100
	#定义权重
    priority  100
	#定义心跳检测时间1秒
    advert_int  1
	#定义组用户密码
    authentication {
        auth_type  PASS
        auth_pass  123456
    }
	#定义docker内ip地址,必须要在和haproxy同一个网段
    virtual_ipaddress {
        172.20.0.100
    }
}


启动
service keepalived start

到这一步理论上就完事了,只需要在新建一个haproxy+keepalived组成集群即可,在这里我遇到一个坑是:

启动keepalived后宿主机无法ping通用keepalived,报错:

[root@centos7 ~]# ping 172.20.0.100
PING 172.20.0.100 (172.20.0.100) 56(84) bytes of data.
From 172.20.0.100 icmp_seq=1 Destination Host Unreachable
From 172.20.0.100 icmp_seq=2 Destination Host Unreachable

解决方案:

大多数都是我把配置文件没写对,重写配置文件,重启服务;

这里检查能否ping通,需要看服务内你的配置文件写入的ip有没有出现在docker的网卡上,具体方法是:

进入到docker服务内,不是在宿主机上哦,查看配置文件
root@8351443065ea:/etc/keepalived# cat keepalived.conf
vrrp_instance  VI_1 {
    state  MASTER
    interface  eth0
    virtual_router_id  100
    priority  100
    advert_int  1
    authentication {
        auth_type  PASS
        auth_pass  123456
    }
    virtual_ipaddress {
        172.20.0.100
    }
}
如果配置文件信息都是正确的,通过ip a命令会显示如当前docker服务有的网卡
root@8351443065ea:/etc/keepalived# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
73: eth0@if74: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:14:00:07 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.20.0.7/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe14:7/64 scope link 
       valid_lft forever preferred_lft forever

很明显没有我配置文件中的172.20.0.100ip地址,代表配置文件未生效,大多数配置文件错误

停掉keepalived服务重新修改编辑后重启
root@8351443065ea:/etc/keepalived# service keepalived stop
[ ok ] Stopping keepalived: keepalived.
重启服务
root@8351443065ea:/etc/keepalived# service keepalived start
[ ok ] Starting keepalived: keepalived.

再次查看docker服务的ip
root@8351443065ea:/etc/keepalived# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
73: eth0@if74: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:14:00:07 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.20.0.7/24 scope global eth0
       valid_lft forever preferred_lft forever
这里出现了我的配置文件ip地址
    inet 172.20.0.100/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe14:7/64 scope link 
       valid_lft forever preferred_lft forever

在服务内直接ping这个ip,发现能ping通,切换宿主机,也能ping通,解决问题
root@8351443065ea:/etc/keepalived# ping 172.20.0.100
PING 172.20.0.100 (172.20.0.100) 56(84) bytes of data.
64 bytes from 172.20.0.100: icmp_seq=1 ttl=64 time=0.042 ms
64 bytes from 172.20.0.100: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 172.20.0.100: icmp_seq=3 ttl=64 time=0.060 ms
^C

最后,再新建一个haproxy再添加slave的keepalive,加入到master中,即完成负载均衡集群的搭建。

新建第二个haproxy容器的配置文件和第一个容器是一样的,需要注意的地方是,在docker run新建容器的时候,由于4001,4002端口和ip都被占用了,所以在run的时候要指定未使用的新端口和ip,比如4003,4004端口等等;

第二个keepalived的配置文件和第一个配置文件完全一样,如果想要分配不同的权重比列,只需要更改权重参数就可以了。

最后,本地宿主机安装keepalived进行外网路由:

宿主机操作:

安装keepalived
yum install -y keepalived

安装完后配置文件本省有自带的在,/etc/keepalived文件夹中,通过ftp替换掉这个配置文件

宿主机KP配置文件信息:

vrrp_instance VI_1 {
    state MASTER
#这里是宿主机的网卡,可以通过ip a查看当前自己电脑上用的网卡名是哪个
    interface ens33
    virtual_router_id 100
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
#这里是指定的一个宿主机上的虚拟ip,一定要和宿主机网卡在同一个网段,我的宿主机网卡ip是192.168.1.85,所以指定虚拟ip是给的90
       	192.168.1.90
    }
}

#接受监听数据来源的端口,网页入口使用
virtual_server 192.168.1.90 8888 {
    delay_loop 3
    lb_algo rr 
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
#把接受到的数据转发给docker服务的网段及端口,由于是发给docker服务,所以和docker服务数据要一致
    real_server 172.20.0.100 8888 {
        weight 1
    }
}

#接受数据库数据端口,宿主机数据库端口是3306,所以这里也要和宿主机数据接受端口一致
virtual_server 192.168.1.90 3306 {
    delay_loop 3
    lb_algo rr 
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
#同理转发数据库给服务的端口和ip要求和docker服务中的数据一致
    real_server 172.20.0.100 3306 {
        weight 1
    }
}

配置完后,通过命令service keepalived start启动宿主机的KP,通过ip a查看网卡中是否出现定义的90 IP地址,如果没有出现大多数是配置文件不正确。

通过ping 90ip地址,发现能够ping通

切换到windows上,进入cmd ping宿主机90ip地址发现能ping通,通过浏览器输入 

http://192.168.1.90:8888/dbs

进入到监听页面:

到此实现了外网访问的负载均衡集群搭建。

在此如果cmd能ping通90ip 而网页无法进入监听界面,问题出现在防火墙上,centos7默认防火墙是没有开启开启vrrp 协议,而keepalived用的是vrrp协议,所以要么让防火强开通vrrp协议,命令:

执行命令1
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface em1 --destination 224.0.0.18 --protocol vrrp -j ACCEPT

执行命令2
firewall-cmd --reload

或者直接关闭防火墙:

systemctl stop firewalld.service

以上防火墙命令只针对于centos7的firewalld,其他防火墙或者linux版本可以自行百度让vrrp协议能够使用即能让网页进入到监听界面。

最后通过navicat链接进行验证:

HA链接的是宿主机90 IP 的3306端口进入MySQL服务,代表总keepalived,

H1,H2是链接宿主机85 IP的4002、4004端口进入MySQL服务,代表HA单节点

PXC各节点是链接宿主机85 IP的3307、3308、3309等端口代表PXC集群各个单节点

测试:

手动关掉PXC部分节点,监控界面观察H1、H2,出现集群预警,正常PXC节点写入数据,发现能正常写入。PXC集群成功。

手动关掉H1或H2、通过HA观察,发现正常,在通过navicat链接关掉的HA单节点,发现无法链接,二HA 能正常写入,代表HA集群搭建成功。

以上,实现了高可用的MySQL数据库集群及其负载均衡。

还没解决的问题:

虽然目前通过调整配置文件ping通了keepalived,但是这也只是偶然猜测出来的一个解决方案,其实我本来希望是通过docker logs去查看服务报错信息确定具体问题出现在哪里,但是使用docker logs后发现,这个日志查询命令只能查看haproxy容器的日志,我在haproxy中安装了keepalived之后,keepalived的日志没有办法查看,目前还没有找到一个简单易懂能查看docker服务内独立应用的日志方法,这里还需要继续深入学习。

猜你喜欢

转载自blog.csdn.net/qq_21108311/article/details/82973763