项目:构建高可用、负载均衡的高效Web服务器
一、项目需求
实现高可用,防止单点故障,实现负载均衡
负载均衡:将流量分摊给一个或多个后端服务器,提高公司业务的可用性、方便业务后期的水平动态扩展。
二、项目描述
本项目旨在构建一个集高可用性、负载均衡、高效Web服务及缓存技术于一体的综合解决方案, 以显著提升Web应用的可靠性、性能和响应速度。通过精细规划和实施,我们成功搭建了一个能够应对高并 发访问、确保业务连续性的Web应用架构。
三、设备要求
准备四台主机
1.准备两台主机实现keepalived+haproxy
第一台主机:
- 主机名:ka1.lm.org
- IP1为172.25.254.30
第二台主机:
- 主机名:ka2.lm.org
- IP2为172.25.254.40
2.准备两台主机作为后端服务器(realserver)
第一台主机:
- 主机名:realserver1.lm.org
- IP1:172.25.254.101
第二台主机:
- 主机名:realserver2.lm.org
- IP2:172.25.254.102
四、搭建
4.1 基础设置
注:四台主机都需同样的操作,也可以准备好一台主机,再克隆,修改IP,hostname即可
1.配置网络
ka1:
[root@localhost ~]# nmcli connection modify ens160 ipv4.addresses 172.25.254.30/24
[root@localhost ~]# nmcli connection modify ens160 ipv4.gateway 172.25.254.2
[root@localhost ~]# nmcli connection modify ens160 ipv4.dns 114.114.114.114
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual
[root@localhost ~]# nmcli connection modify ens160 connection.autoconnect yes
[root@localhost ~]# nmcli connection up ens160
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/12)
ka2:
[root@localhost ~]# vim /etc/NetworkManager/system-connections/ens160.nmconnection
connection]
id=ens160
type=ethernet
interface-name=ens160
[ethernet]
[ipv4]
address1=172.25.254.40/24,172.25.254.2
dns=114.114.114.114;
method=manual
[ipv6]
addr-gen-mode=eui64
method=auto
[root@localhost ~]# nmcli connection reload
[root@localhost ~]# nmcli connection up ens160
注意:分别使用两种方式更改IP
realserver1:172.25.254.101
realserver2:172.25.254.102
使用上面的方式修改IP
2.配置软件仓库
[root@localhost ~]# mkdir /rhel9
[root@localhost ~]# echo /dev/sr0 /rhel9 >> /etc/rc.d/rc.local
[root@localhost ~]# chmod +x /etc/rc.d/rc.local
[root@localhost ~]# mount /dev/sr0 /rhel9
mount: /rhel9: WARNING: source write-protected, mounted read-only.
3.设置主机名和本地解析
[root@ka1 ~]# hostnamectl set-hostname ka1.lm.org
[root@ka2 ~]# hostnamectl set-hostname ka2.lm.org
4.2 搭建高可用负载均衡集群
1.安装keepalived,haproxy
ka1,ka2主机都需此操作
[root@ka1 ~]# hostnamectl set-hostname ka1
[root@ka1 ~]# dnf install -y keepalived
[root@ka1 ~]# dnf install -y haproxy
# 开机自启
[root@ka1 ~]# systemctl enable --now haproxy
Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /usr/lib/systemd/system/haproxy.service.
[root@ka1 ~]# systemctl enable --now keepalived
Created symlink /etc/systemd/system/multi-user.target.wants/keepalived.service → /usr/lib/systemd/system/keepalived.service.
2.修改keepalived和haproxy配置文件
ka1
[root@ka1 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
3041609716@qq.com
}
notification_email_from keepalived@lm.org
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id ka1.lm.org
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_haproxy {
script "/etc/keepalived/scripts/haproxy.sh"
interval 1
weight -30
fall 2
rise 2
timeout 2
}
vrrp_instance web1 {
state MASTER
interface ens160
virtual_router_id 100
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.100 dev ens160 label ens160:1
}
track_script {
check_haproxy
}
}
vrrp_instance web2 {
state SLAVE
interface ens160
virtual_router_id 200
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.200 dev ens160 label ens160:2
}
track_script {
check_haproxy
}
}
[root@ka1 ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster1
bind 172.25.254.100:80
server web1 172.25.254.101:80 check
server web2 172.25.254.102:80 check
listen webcluster2
bind 172.25.254.200:80
server web1 172.25.254.101:80 check
server web2 172.25.254.102:80 check
ka2
# 40
[root@ka2 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
3041609716@qq.com
}
notification_email_from keepalived@lm.org
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id ka1.lm.org
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_haproxy {
script "/etc/keepalived/scripts/haproxy.sh"
interval 1
weight -30
fall 2
rise 2
timeout 2
}
vrrp_instance web1 {
state SLAVE
interface ens160
virtual_router_id 100
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.100/24 dev ens160 label ens160:1
}
track_script {
check_haproxy
}
}
vrrp_instance web2 {
state MASTER
interface ens160
virtual_router_id 200
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.200 dev ens160 label ens160:2
}
track_script {
check_haproxy
}
}
[root@ka1 ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster1
bind 172.25.254.100:80
server web1 172.25.254.101:80 check
server web2 172.25.254.102:80 check
listen webcluster2
bind 172.25.254.200:80
server web1 172.25.254.101:80 check
server web2 172.25.254.102:80 check
3.修改内核参数
[root@ka1 ~]# vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind = 1
[root@ka1 ~]# sysctl -p
[root@ka2 ~]# vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind = 1
[root@ka2 ~]# sysctl -p
[root@localhost ~]# hostnamectl set-hostname realserver1
[root@realserver1 ~]# dnf install -y nginx
[root@realserver1 ~]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
[root@realserver1 ~]# echo 172.25.254.101 > /usr/share/nginx/html/index.html
[root@realserver1 ~]# curl 172.25.254.101
172.25.254.101
4.3 后端服务器设置
realserver1,realserver2都是几乎相同的操作
[root@localhost ~]# hostnamectl set-hostname realserver1
[root@realserver1 ~]# dnf install -y nginx
[root@realserver1 ~]# echo 172.25.254.101 > /usr/share/nginx/html/index.html
[root@realserver1 ~]# curl 172.25.254.101
172.25.254.101
[root@localhost ~]# hostnamectl set-hostname realserver2
[root@realserver2 ~]# dnf install -y nginx
[root@realserver2 ~]# echo 172.25.254.102 > /usr/share/nginx/html/index.html
[root@realserver2 ~]# curl 172.25.254.102
172.25.254.102
4.4 测试
[root@ka1 ~]# ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.30 netmask 255.255.255.0 broadcast 172.25.254.255
inet6 fe80::20c:29ff:fef1:9875 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:f1:98:75 txqueuelen 1000 (Ethernet)
RX packets 3109 bytes 211759 (206.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3775 bytes 227206 (221.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens160:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.100 netmask 255.255.255.255 broadcast 0.0.0.0
ether 00:0c:29:f1:98:75 txqueuelen 1000 (Ethernet)
[root@ka1 ~]# curl 172.25.254.100
172.25.254.102
[root@ka1 ~]# curl 172.25.254.100
172.25.254.101
[root@ka1 ~]# curl 172.25.254.100
172.25.254.102
[root@ka1 ~]# curl 172.25.254.200
172.25.254.101
[root@ka1 ~]# curl 172.25.254.200
172.25.254.102
[root@ka1 ~]# curl 172.25.254.200
172.25.254.101
[root@ka1 ~]# curl 172.25.254.200
172.25.254.102
[root@ka2 ~]# ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.40 netmask 255.255.255.0 broadcast 172.25.254.255
inet6 fe80::20c:29ff:fed5:289d prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:d5:28:9d txqueuelen 1000 (Ethernet)
RX packets 306952 bytes 22903523 (21.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 560789 bytes 37705879 (35.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens160:2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.200 netmask 255.255.255.255 broadcast 0.0.0.0
ether 00:0c:29:d5:28:9d txqueuelen 1000 (Ethernet)
[root@ka2 ~]# curl 172.25.254.100
172.25.254.101
[root@ka2 ~]# curl 172.25.254.100
172.25.254.102
[root@ka2 ~]# curl 172.25.254.100
172.25.254.101
[root@ka2 ~]# curl 172.25.254.100
172.25.254.102
[root@ka2 ~]# curl 172.25.254.100
172.25.254.101
[root@ka2 ~]# curl 172.25.254.100
172.25.254.102
[root@ka2 ~]# curl 172.25.254.100
172.25.254.101
[root@ka2 ~]# curl 172.25.254.200
172.25.254.101
[root@ka2 ~]# curl 172.25.254.200
172.25.254.102
[root@ka2 ~]# curl 172.25.254.200
172.25.254.101
[root@ka2 ~]# curl 172.25.254.200
172.25.254.102
模拟故障:
关闭ka1的keepalived
[root@ka1 ~]# systemctl stop keepalived
[root@ka1 ~]# ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.30 netmask 255.255.255.0 broadcast 172.25.254.255
inet6 fe80::20c:29ff:fef1:9875 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:f1:98:75 txqueuelen 1000 (Ethernet)
RX packets 927274 bytes 72325472 (68.9 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1854187 bytes 129793327 (123.7 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@ka2 ~]# ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.40 netmask 255.255.255.0 broadcast 172.25.254.255
inet6 fe80::20c:29ff:fed5:289d prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:d5:28:9d txqueuelen 1000 (Ethernet)
RX packets 683628 bytes 53310970 (50.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1365919 bytes 95613730 (91.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens160:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.100 netmask 255.255.255.0 broadcast 0.0.0.0
ether 00:0c:29:d5:28:9d txqueuelen 1000 (Ethernet)
ens160:2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.200 netmask 255.255.255.255 broadcast 0.0.0.0
ether 00:0c:29:d5:28:9d txqueuelen 1000 (Ethernet)
# 即使发生故障,依然可以成功访问
[root@ka1 ~]# curl 172.25.254.100
172.25.254.102
[root@ka1 ~]# curl 172.25.254.100
172.25.254.101
[root@ka1 ~]# curl 172.25.254.100
172.25.254.102
[root@ka1 ~]# curl 172.25.254.100
172.25.254.101
[root@ka1 ~]# curl 172.25.254.200
172.25.254.102
[root@ka1 ~]# curl 172.25.254.200
172.25.254.101
[root@ka1 ~]# curl 172.25.254.200
172.25.254.102
[root@ka1 ~]# curl 172.25.254.200
172.25.254.101