基于docker+Keepalived+Haproxy高可用前后端分离技术
架构图
服务名 | docker-ip地址 | docker-keepalived-vip-ip |
---|---|---|
haproxy-01 | docker-ip自动分配 未指定ip | 192.168.31.252 |
haproxy-02 | docker-ip自动分配 未指定ip | 192.168.31.253 |
安装haproxy
宿主机ip 192.168.31.254
宿主机keepalived虚拟网络未定义
global
#工作目录
chroot /usr/local/etc/haproxy
#日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
log 127.0.0.1 local5 info
#守护进程运行
daemon
defaults
log 127.0.0.1 local0 err #[err warning info debug]
mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
retries 2 #两次连接失败就认为是服务器不可用,也可以通过后面设置
option redispatch #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
option dontlognull #日志中不记录负载均衡的心跳检测记录
maxconn 4096 #默认的最大连接数
timeout connect 5000ms #连接超时
timeout client 30000ms #客户端超时
timeout server 30000ms #服务器超时
#timeout check 2000 #=心跳检测超时
######## 监控界面配置 #################
listen admin_stats
#监控界面的访问的IP和端口
bind 0.0.0.0:8888
#访问协议
mode http
#URI相对地址
stats uri /dbs
#统计报告格式
stats realm Global\ statistics
#登陆帐户信息
stats auth admin:admin
########frontend配置##############
#mycat负载均衡
listen proxy-mycat
#访问的IP和端口
bind 0.0.0.0:9000
#网络协议
mode tcp
#负载均衡算法(轮询算法)
#轮询算法:roundrobin
#权重算法:static-rr
#最少连接算法:leastconn
#请求源IP算法:source
balance roundrobin
# 这里是容器中的IP地址,由于配置的是轮询roundrobin,weight 权重其实没有生效
server haproxy01 192.168.31.252:4001 check weight 1 maxconn 2000
server haproxy02 192.168.31.253:4002 check weight 1 maxconn 2000
# 使用keepalive检测死链
option tcpka
创建Haproxy容器
haproxy01
docker run -d -p 4001:8888 -p 9000:8066 \
-v /haproxy/haproxy01:/usr/local/etc/haproxy \
--name haproxy01 --privileged haproxy:2.1
haproxy02
docker run -d -p 4002:8888 -p 9001:8066 \
-v /haproxy/haproxy02:/usr/local/etc/haproxy \
--name haproxy02 --privileged haproxy:2.1
参数配置详解
-p 4001:8888 将Haproxy提供的监控界面服务端口8888映射到宿主机的4001端口
-p 4002:3306 将Haproxy提供的数据库负载均衡的服务端口3306映射到宿主机的4002端口
-v /home/soft/haproxy:/usr/local/etc/haproxy 将宿主机的/home/soft/haproxy目录映射到容器的/usr/local/etc/haproxy目录。将来在宿主机的/home/soft/haproxy中放入配置文件,在相映射的容器目录中就可以使用了。
--name h1 给容器起名,为了保证Haproxy的高可用,将来也会启动多个Haproxy容器实例
--privileged 配置权限
--net=net1 使用的网段,数据库实例使用的都是net1网段,需和数据库实例使用的网段保持一致
--ip 172.18.0.7 手动分配的ip地址,如不设置,docker虚拟机也会给其分配一个ip地址
haproxy:2.1 docker run使用的镜像名
在haproxy容器中启动haproxy实例
由于容器是使用-d做后台运行的,因此之后还需要进入后台运行的容器,把haproxy中间件启动起来。
进入后台运行的容器:
docker exec -it haproxy01 /bin/bash
启用配置文件(启用完配置文件才算是真的启动了haproxy服务)
(haproxy01 、haproxy02 都需要执行)
haproxy -f /usr/local/etc/haproxy/haproxy.cfg
查看haproxy监控界面
http://对应ip:4001/dbs
用户名:admin
密码:admin
对应上面的配置
keepalived搭建
(haproxy01 、haproxy02 都需要执行)
1、进入docker-haproxy服务
docker exec -it haproxy01 /bin/bash
2、更新update,安装keepalived
apt-get update
apt-get install keepalived
更换源这里就不操作了
3、安装vim 安装ifconfig命令 安装ping
apt-get install net-tools vim iputils-ping
4、新建并写入一个keepalived的配置文件(注意把注释删掉)
vim /etc/keepalived/keepalived.conf
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.17.0.66
}
}
keepalived配置文件详细说明
vrrp_instance VI_1 {
state MASTER #Keepalive的身份(MASTER为主服务,BACKUP为备用服务,抢占到ip的为主服务器,没有抢占到的自动降级为备用服务器)
interface eth0 #docker中虚拟ip使用到的docker内部网卡
virtual_router_id 51 #虚拟路由标识,MASTER和BACKUP的虚拟路由标识必须一致。 标识可以是0~255之间任意值。
priority 100 #硬件设备条件不同时采用的权重,MASTER权重要高于BACKUP,数字越大优先级越高。
advert_int 1 #keepalived节点之间的心跳检测间隔,单位为秒,主备之间必须一致。
authentication {
auth_type PASS
auth_pass 123456
} #心跳检测需要登录到keepalived节点内,登录使用的账号密码。主备必须用相同的密码才能正常通信。
virtual_ipaddress {
172.18.0.201
} #虚拟ip,该虚拟ip将被写入到上面的docker网卡ens33中,如数据库集群的网段是172.18.0.xxx,这里就定义个大一点的该网段的ip地址。由于是docker内部的虚拟ip,在docker内部能访问,出了docker是不能访问的。
}
启动keepalived
service keepalived start
执行 /bin/systemctl start keepalived.service 即可
尝试宿主机能否ping通keepalived占有的虚拟ip,能ping通就说明这个虚拟ip已经配置成功了:
如若ping不通需检查配置是否正确,以及网络模式是否是桥接。
一开始我使用的网络模式是nat,无法ping通,改为桥接后重启linux可以ping通
三、在宿主机内安装Keepalived
Haproxy容器内的keepalive已经正常运行了,其抢占的虚拟ip也可以正常ping通了。
之后需要把该虚拟ip和宿主机的ip做映射,以使外部网络可以访问到该虚拟ip,需要在宿主机上也安装keepalived。
宿主机的linux是centos,所以安装命令有所不同:
yum install -y keepalived
apt-get install -y keepalived
编写Keepalived配置文件
位置/etc/keepalived文件夹
宿主机配置信息
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.136.140
}
}
#接受监听数据来源的端口,网页入口使用
virtual_server 192.168.136.140 8888 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
#把接受到的数据转发给docker服务的网段及端口,由于是发给docker服务,所以和docker服务数据要一致
real_server 172.18.0.15 8888 {
weight 1
}
}
#接受数据库数据端口,宿主机数据库端口是3306,所以这里也要和宿主机数据接受端口一致
virtual_server 192.168.136.140 8066 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
#同理转发数据库给服务的端口和ip要求和docker服务中的数据一致
real_server 172.18.0.15 8066 {
weight 1
}
}
配置文件详解
注意:
1. 如上配置中的virtual_server 192.168.31.252,这是我当前的宿主机的网段ip地址,需将配置中所有192.168.132.252改成自己使用的宿主机网段
2. ipaddress查看自己连接宿主机的ip地址,查看ip地址对应的网卡名。把interface eth1一项修改成自己正确的宿主机网卡名。
3、启动keepalived
service keepalived start
执行 /bin/systemctl start keepalived.service 即可 如果报错
启动成功后,尝试ping宿主机供请求访问的ip ping 192.168.31.99
测试Haproxy监控服务
通过宿主机keepalived绑定的ip访问haproxy监控服务
注意,这次访问haproxy监控服务的ip192.168.31.99是宿主机keepalived所占有的虚拟ip,
keepalived通过这个虚拟ip192.168.31.99 转发请求到docker的虚拟ip 172.17.0.66。
haproxy01容器中的keepalived所在主服务器haproxy最后进行负载均衡请求分发。
这次访问的已经不是原本的未使用keepalived时的宿主机192.168.132.252的ip了
以上都是为了实现高可用功能,没有配置前后端分离。
至此完成高可用
Haproxy配置动静分离页面
修改主配置文件如下
global
chroot /usr/local/etc/haproxy
log 127.0.0.1 local0 info ##定义日志级别;
log 127.0.0.1 local1 notice
maxconn 4096 ##设定每个haproxy进程所接受的最大并发连接数
uid 99 ##指定运行服务的用户和组
gid 99
daemon ##指定运行模式为daemon,以守护进程的方式工作在后台
defaults
log global ##采取global中的日志配置
mode http ##默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
option httplog ##采用http日志格式记录日志
option dontlognull ##不记录健康检查的日志记录
option httpclose ##关闭保持连接
retries 3 ##检查节点最多失败次数
maxconn 2000 ##最大连接数,定义不得大于global中的值
contimeout 5000 ##连接超时时间,毫秒,在此期间,如若客户端与服务端无法成功建立连接,则断掉
clitimeout 50000 ##设置连接客户端发送数据时的成功连接最长等待时间,单位为毫秒,如若在这期间无法请求成功,则断掉
srvtimeout 50000 ##设置服务器端回应客户端数据发送的最长等待时间,如果在这期间还无法发送成功,则断掉
##################无分离页面需求的配置##############
#listen webcluster 0.0.0.0:80 ##指定haproxy服务监听地址和端口
# option httpchk GET /index.html ##指定http请求方法和默认文件
# balance roundrobin ##指定轮询调度算法
# server inst1 192.168.100.155:80 check inter 2000 fall 3 ##定义web节点,检测心跳频率,单位为毫秒,定义检查节点最多失败次数
# server inst2 192.168.100.156:80 check inter 2000 fall 3
##################有分离页面需求的配置##############
frontend http ##定义名称为http
bind *:80 ##指定监听地址和端口
acl linuxfan1 hdr_end(host) -i 192.168.31.253 ##指定类型为访问路径的域名,-i不区分大小写
acl linuxfan2 hdr_end(host) -i www.ceshi.con
acl linuxfan3 path_end -i .jsp .do .css .js ##指定请求文件格式为.jsp
#acl linuxfan3 hdr_reg -i \.(css|png|jpg|jpeg|gif|ico|swf|xml|txt|pdf|do|jsp|js)$ ##调用正则表达式
acl linuxfan4 path_end -i .html .css .png .jpg .jpeg .xml ##指定请求文件格式为.html
acl linuxfan5 path_beg -i /WebRoot ##指定访问URL中的路径,如http://www.linuxfan.cn/WebRoot/index.jsp
use_backend dongtai if linuxfan1 linuxfan3
use_backend dongtai if linuxfan2 linuxfan3
use_backend dongtai if linuxfan1 linuxfan5 linuxfan3
use_backend dongtai if linuxfan2 linuxfan5 linuxfan3
default_backend jingtai ##默认的请求使用backend dongtai
backend jingtai ##定义backend :jingtai
mode http ##定义模式
balance roundrobin ##定义调度算法为轮询
server jingtai01 192.168.31.253:80 check inter 2000 fall 3 ##定义节点
backend dongtai
mode http
balance roundrobin
server dongtai01 192.168.31.254:8080 check inter 2000 fall 3
部署nginx
创建目录
mkdir -p /usr/local/docker/nginx
vim docker-compose.yml
version: "3.0"
services:
nginx:
image: nginx:1.21.6
restart: always
#network_mode: "host"
ports:
- 80:80
- 443:443
volumes:
- "./nginx/html:/usr/share/nginx/html"
- "./nginx/conf.d:/etc/nginx/conf.d"
- "./nginx/ssl:/etc/nginx/ssl"
- "./nginx/logs:/var/log/nginx"
启动
部署tomcat
创建目录,为了放置 Tomcat 的配置文件等
mkdir bin conf docker-compose.yml logs webapps
先随便启动一个 tomcat 容器(用第一种方法,docker run),主要是为了获取 tomcat 容器内部的配置文件
#启动一个容器
docker run -d --name tomcat tomcat
# 查看 容器 获取容器ID
docker ps -a
其中将,容器内 tomcat 文件夹下的 conf bin logs webapps 里面的内容都拷贝到上面宿主机上创建的对应文件夹内。容器的文件拷贝到宿主机的命令如下:
# 注意!是在宿主机上执行这条命令。
docker cp 容器名:/usr/local/tomcat/webapps/* /usr/local/tomcat/webapps
其它文件夹内的内容也要这样拷贝到宿主机对应的文件夹内。
创建这个文件,docker-compose.yml
version: '3'
services:
tomcat:
user: root
restart: always
container_name: tomcat
image: tomcat
privileged: true
environment:
- TZ="Asia/Shanghai"
ports:
- 1002:8080
volumes:
- /usr/local/tomcat/webapps/:/usr/local/tomcat/webapps/
- /usr/local/tomcat/conf:/usr/local/tomcat/conf
- /usr/local/tomcat/logs:/usr/local/tomcat/logs
- /usr/local/tomcat/bin:/usr/local/tomcat/bin
- /etc/localtime:/etc/localtime