最近在工作中遇到需要搭建一个高可用集群的需求,查看了网上的一些资料,发现都相对比较陈旧,步骤也不是非常的详细。于是就写了这篇搭建教程,方便有同样需求的同学参考
下载并安装VirtualBox
https://www.virtualbox.org/wiki/Downloads
本次搭建教程使用的版本是Virtual Box 6.1版本
下载CentOS镜像
https://mirrors.aliyun.com/centos/7/isos/x86_64/
本次搭建教程使用的版本是其中的CentOS-7-x86_64-DVD-2009.iso
配置安装第一台CentOS虚拟机 (下文中用Node01表示)
-
打开VirtualBox应用程序,点击下方图中的New来创建一台新的虚拟机Node01
-
随后参考下图进行虚拟机的类型,版本选择
-
之后可以一路维持默认选项点击下一步,在完成创建后,在左侧列表里可以看到新的虚拟机。双击该虚拟机之后,会让你选择用于启动的ISO文件,此时就可以选中我们之前下载的CentOS 7的ISO文件进行系统安装
-
整个安装过程也非常的便捷,基本上和安装Windows系统差不多
-
注意在安装时候可以去设置root用户的密码,便于后续登陆系统
-
安装结束后,按照提示重启CentOS系统
配置网络接口
-
安装完系统之后,如果尝试执行
ping www.baidu.com
,会提示如下错误
-
这是因为此时网络还没有被正确的配置,通过执行
sudo nmcli d
可以发现网络接口确实处于未连接状态
执行
sudo nmtui
进入如下图的配置界面, 随后依次选择
Edit a connection
enp0s3
其中有部分操作需要用空格键进行选择, 可以自己尝试下
-
将下图中的
Automatically connect
勾选上,选择OK
-
配置完之后,输入
reboot
重启系统,再次执行sudo nmcli d
以及ping www.baidu.com
,可以发现网络已经连通了
配置阿里云的yum源
依次执行下列命令并等待至完成
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all
yum makecache
安装Docker
可以参考官方文档,或者也可以直接按照下面的步骤进行安装
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl start docker
启动微服务容器
为了节省本教程的复杂度,我已经提前准备好了两个微服务镜像方便测试,分别命名为
chuckge/spring-jib-app
chuckge/spring-jib-app-v2
两个服务都提供了一个路径为\helloworld
的Endpoint,差别在于spring-jib-app-v2
在调用后会返回"V2"字样便于区分
执行docker run -dp 8080:8080 chuckge/spring-jib-app
后等待容器启动完成
此时,可以尝试在虚拟机中执行curl localhost:8080/helloworld
, 会发现返回了一个IP地址的字符串
创建第二台虚拟机 (下文中用Node02表示)
按照上面的步骤创建第二台虚拟机,唯一不同之处是在这台虚拟机上运行以spring-jib-app-v2
为镜像的容器,用于和第一台虚拟机Node01后续进行区分,在完成上述的步骤之后,在Node02上执行下面的命令运行该V2版本的微服务容器
docker run -dp 8080:8080 chuckge/spring-jib-app-v2
下文中如果不特殊说明,所有的步骤都需要再两个Node上均操作
虚拟机的两种网络链接模式
在VirtualBox中选中某台虚拟机,点击Settings -> Network之后,可以进行网络适配器的配置
在本次实验中,会用到其中两种 (切换模式后,记得通过reboot
重启虚拟机)
-
NAT
在这个模式下,虚拟机可以直接连接Internet,在使用yum等进行安装的时候需要切换到此模式
-
Host-only Adapter
在这个模式下,宿主机以及虚拟机会处于同一网段,并且互相之间可以Ping通,在全部安装配置完毕之后可以切换到此模式再宿主机上进行访问测试
-
下文中在haproxy.cfg配置文件中的两台虚拟机IP(192.168.56.101和192.168.56.102),需要在这个模式下,通过
ip addr
命令获取后按照实际情况进行配置
安装HAProxy
-
关闭SELINUX
编辑
/etc/selinux/config
文件,将SELINUX=enforcing
修改成SELINUX=disabled
-
关闭IP Tables (防火墙)
systemctl stop firewalld.service systemctl disable firewalld.service
-
通过yum安装haproxy
yum -y install haproxy
-
创建haproxy的日志文件
mkdir /var/log/haproxy chmod a+w /var/log/haproxy
-
开启rsyslog记录haproxy日志功能
vi /etc/rsyslog.conf 将下面两行的注释去掉(#号) $ModLoad imudp $UDPServerRun 514 在文件的末尾添加 local3.* /var/log/haproxy/haproxy.log vi /etc/sysconfig/rsyslog 修改 SYSLOGD_OPTIONS="-r -m 0 -c 2" vi /etc/haproxy/haproxy.cfg 将`log 127.0.0.1 local2`改成`log 127.0.0.1 local3 info` 重启日志服务 systemctl restart rsyslog.service
-
修改haproxy配置
vi /etc/haproxy/haproxy.cfg #--------------------------------------------------------------------- # Example configuration for a possible web application. See the # full configuration options online. # # http://haproxy.1wt.eu/download/1.4/doc/configuration.txt # #--------------------------------------------------------------------- #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global # to have these messages end up in /var/log/haproxy.log you will # need to: # # 1) configure syslog to accept network log events. This is done # by adding the '-r' option to the SYSLOGD_OPTIONS in # /etc/sysconfig/syslog # # 2) configure local2 events to go to the /var/log/haproxy.log # file. A line like the following can be added to # /etc/sysconfig/syslog # # local2.* /var/log/haproxy.log # log 127.0.0.1 local3 info chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats #--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 #--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend main *:80 acl url_static path_beg -i /static /images /javascript /stylesheets acl url_static path_end -i .jpg .gif .png .css .js use_backend static if url_static default_backend app #--------------------------------------------------------------------- # static backend for serving up images, stylesheets and such #--------------------------------------------------------------------- backend static balance roundrobin server static1 192.168.56.101:8080 check server static2 192.168.56.102:8080 check #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend app balance roundrobin server app1 192.168.56.101:8080 check server app2 192.168.56.102:8080 check listen stats bind :10086 stats uri /admin?stats stats auth admin:admin stats admin if TRUE
安装keepalived
-
通过yum进行安装
yum -y install keepalived
-
配置keepalived (Node 1)
vi /etc/keepalived/keepalived.conf global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node01 } vrrp_instance VI_1 { state MASTER interface enp0s3 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS } virtual_ipaddress { 192.168.56.105 } }
-
配置keepalived (Node 2)
vi /etc/keepalived/keepalived.conf global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node02 }s vrrp_instance VI_1 { state BACKUP interface enp0s3 virtual_router_id 51 priority 98 advert_int 1 authentication { auth_type PASS } virtual_ipaddress { 192.168.56.105 } }
启动Docker, Docker container, HAProxy, Keepalived (Node01)
systemctl start docker
docker run -dp 8080:8080 chuckge/spring-jib-app
systemctl start haproxy
systemctl status haproxy #查看haproxy启动状态,如果有绿色active,说明成功启动
systemctl start keepalived
systemctl status keepalived #查看keepalived启动状态,如果有绿色active,说明成功启动
启动Docker, Docker container, HAProxy, Keepalived (Node02)
systemctl start docker
docker run -dp 8080:8080 chuckge/spring-jib-app-v2 #注意此处和上面Node01的不同
systemctl start haproxy
systemctl status haproxy #查看haproxy启动状态,如果有绿色active,说明成功启动
systemctl start keepalived
systemctl status keepalived #查看keepalived启动状态,如果有绿色active,说明成功启动
下面开始进行测试
首先查看当前VIP(192.168.56.105)在哪台虚拟机上
由于Node01的priority数值较高,所以会被选作Master,在Node01上执行ip addr
可以看到持有该VIP
通过VIP访问HAProxy的控制台页面
http://192.168.56.105:10086/admin?stats
用户名: admin
密码: admin
在这个页面中,可以清晰的看到HAProxy的一些实时统计数据
通过VIP访问后端服务
注意此处使用的是192.168.56.105进行访问,而并不是真实的IP(101和102),这样才能实现和具体实例IP解耦,实现高可用
http://192.168.56.105/helloworld
多次刷新后,可以看到请求被均匀分发到两个后端服务上
将Node01上的HAProxy和Keepalived停止,查看VIP是否能自动漂移到Node02
在Node01上执行
systemctl stop haproxy
systemctl stop keepalived
在Node02上执行ip addr
,可以发现VIP已经自动漂移到Node02上
再次通过VIP访问后端服务验证
http://192.168.56.105/helloworld
多次访问会发现,请求仍然能被正常处理,并且均匀的分发到两个后端服务上,不过此时工作的已经Node02上的HAProxy了
TIPS:
-
如果遇到启动haproxy报错 HAProxy cannot bind socket [0.0.0.0:10086]
在虚拟机命令行执行
setsebool -P haproxy_connect_any=1