Skip to content

VirtualBox + CentOS + NGINX + Keepalived 初阶实战:负载均衡 + HA #2

@lilins

Description

@lilins

负载均衡 + HA

当用户通过互联网访问服务器的时候,互联网将请求转发给服务器(通常是单台)。然而随着互联网的发展,对于服务器的要求也更高,对于活跃网站的访问量例如 Google 每秒需要处理的搜索可能高达上万次,如果只部署单台服务器肯定无法应对如此大的访问量,所以出现了负载均衡技术(Load Balance)

1548924638700

负载均衡是使用一些策略来将工作负载分配到多台服务器上进行处理,同时,在某些服务器出现故障的时候,将其他机器作为备用机器,以提高网站的可用性。

Nginx 通常作为负载均衡器来使用。

然而,这个负载均衡的架构同样可能出现问题,例如当负载均衡器出现故障时,尽管后台的服务器没有出现问题,但也都无法使用了。

要避免这样的问题,可以在负载均衡的基础上部署 Keepalived 实现高可用(HA, High Availability)

Keepalived 是基于VRRP协议的高可用方案,VRRP(Virtual Router Redundancy Protocol) 即虚拟路由冗余协议。原理是提供一组服务器,其中有1台 master 服务器以及多台 backup 服务器,再设置一个虚拟 IP(VIP, Virtual IP),将 VIP 给予 master 服务器,其他 backup 服务器待命,master 会发送组播消息,一旦当 backup 收不到 VRRP 包就认为 master 出现故障,协议通过优先级来选出一个 backup 作为 master。

1548926729520

下面就开始通过 VirtualBox 来实现一个负载均衡 + HA 的 Web,以下是架构图:

1548928037603

创建两台虚拟机 192.168.56.103192.168.56.104(作为Keepalived集群),在虚拟机上分别部署两个Web应用在 91009200 端口(作为服务器)。

目录

  1. 软件准备
  2. VirtualBox 创建虚拟机及设置
  3. CentOS firewall 设置
  4. NGINX 安装配置
  5. Keepalived 安装配置
  6. 测试

0. 软件准备

1. VirtualBox 创建虚拟机及设置

网络设置

VirtualBox的网络设置比较复杂,为了满足这次实现要求,我们既需要让不同的虚拟机之间达到互联,又需要让虚拟机与主机网络相连通,所以要设置如下的两个网络:

1) 主机网络管理:提供虚拟机之间的互联

管理 -> 主机网络管理器 -> 创建 -> VirtualBox Host-Only Ethernet Adapter -> 设置如下

  • 网卡 - √ 手动配置网卡
    • IPv4地址 192.168.56.1
    • IPv4网络掩码 255.255.255.0
  • DHCP服务器 - √ 启用服务器
    • 服务器地址 192.168.56.100
    • 服务器网络掩码 255.255.255.0
    • 最小地址 192.168.56.101
    • 最大地址 192.168.56.254

1548913655722

2) Nat 网络:提供虚拟机与主机之间的互联

管理 -> 全局设定 -> 网络 -> 添加新的 Nat 网络 -> NatNetwork -> 编辑 -> 设置如下

  • 网络CIDR 10.0.2.0/24
  • 网络选项 √ 支持DHCP

1548913914360

创建 CentOS

  • 点击 新建
    • 类型 Linux
    • 版本 Other Linux (64-bit)
    • 内存 512MB
    • √ 现在创建虚拟硬盘
  • 点击 创建
    • 文件大小 8.00GB
    • 虚拟硬盘文件类型 VDI
    • 存储在物理硬盘上 动态分配

1548914690074

右击 testOS 设置 -> 网络

将刚刚设置的两个网络分别绑定到 网卡1网卡2

网卡1

1548914827461

网卡2

1548914849024

这里请将两个网卡的 MAC 地址记录下来:

  • 网卡1 MAC 地址 080027F7B648
  • 网卡2 MAC 地址 080027023D2E

启动 CentOS

右击 testOS 启动 -> 正常启动 -> 选择启动盘的时候选择已经下载好的CentOS 7 ISO

接下来进行正常安装,一般安装时间为10~15分钟左右,用户名和密码一般设置为 root/root。

1548915925670

配置 CentOS 网络

输入 ip addr 可以查看网络接口设置:

1548916054063

enp0s3enp0s8 分别对应刚才的两张网卡。

vi /etc/sysconfig/network-scripts/ifcfg-enp0s3
#原有的内容保留,插入如下内容,也可以只保留如下内容
TYPE=Ethernet
NAME=enp0s3
BOOTPROTO=dhcp
HWADDR=08:00:27:f7:b6:48 # 网卡1 MAC地址
ONBOOT=yes

vi /etc/sysconfig/network-scripts/ifcfg-enp0s8
#原有的内容保留,插入如下内容,也可以只保留如下内容
TYPE=Ethernet
NAME=enp0s8
BOOTPROTO=static # 静态IP
IPADDR0=192.168.56.103 # 指定IP地址,可随意指定
prefix0=16	# 分配IP地址
HWADDR=08:00:27:02:3d:2e # 网卡2 MAC地址
ONBOOT=yes

#重启网络使其生效
systemctl restart network
systemctl status network
#可以看到 network 的状态是 active

输入 ip addr 可以查看网络接口设置:

1548918478282

可以看到都已经分配到了 IP 地址,enp0s310.0.2.6enp0s8192.168.56.103

MobaXterm SSH 登录

使用 MobaXterm 可以使用更多的工具。

点击 Session -> SSH -> 输入 192.168.56.103 -> 输入用户名和密码

Proxy 设置

如果你的网络环境可以直接访问外网,那么可以跳过这一步。但如果不行,可以参照一下方式进行 Proxy 的设置,保证 yum 正常访问外网。

输入 yum upgrade ,如果如下显示,说明网络无法访问外网。

1548920839553

进行如下的代理设置:

vi /etc/yum.conf
#添加如下一行
proxy=http://[$proxy.com]:[$port]

2. CentOS firewalld 设置

如果不想设置 firewall 可以直接禁用这个 Service,并跳过这一节。

systemctl stop firewalld
systemctl disable firewalld

从 CentOS 7 开始,firewalld 开始取代 iptables 来接管服务器的防火墙网络设置,所以如果我们想要让服务器对外提供服务的同时又保证服务器的安全,我们可以使用 firewalld 进行设置。

首先我们可以查看 firewalldpublic 区域上可以使用的服务:

firewall-cmd --zone=public --list-all

# 显示
public (active)
  ...
  interfaces: enp0s3 enp0s8
  ...
  services: ssh dhcpv6-client
  ...

发现在 services 中没有 http 服务,所以需要先将 http 服务加入:

firewall-cmd --zone=public --add-service=http --permanent

在之后也会用到 91009200 端口,所以也需要加入:

firewall-cmd --zone=public --add-port=9100/tcp --permanent
firewall-cmd --zone=public --add-port=9200/tcp --permanent

最后需要记住重启 firewalld 使配置生效

firewalld-cmd --reload

3. NGINX 安装配置

在这里我们要开始部署 192.168.56.103192.168.56.104 上的 4 个 Web 应用。

NGINX 安装

Nginx 的安装有两种方式,一种是下载Nginx的源文件并进行编译,第二种是通过 yum 直接安装。这里选择第二种进行直接安装 Install Step

首先安装 yum-utils

yum install yum-utils -y

设置 yum repository

vi /etc/yum.repos.d/nginx.repo

#写入以下文件
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ #$releasever 填写CentOS 版本号 7
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key

安装 Ninx

yum install nginx -y

启动 Nginx

systemctl enable nginx
systemctl start nginx
systemctl status nginx

如果显示 active 说明运行正常,输入命令查看版本:

nginx -v

# 显示:nginx version: nginx/1.14.2

这个时候,可以在本机的浏览器上输入 192.168.56.103 看到已经可以访问 Nginx 了。

新建两个 HTML 作为 Webapp 应用

输入 cd /opt,并新建 nginx 文件夹,继续新建文件夹 Webapp ,并在其下新建 91009200 两个文件夹,并分别创建 index.html

/opt/nginx
--/Webapp
----/9100
------/index.html
----/9200
------/index.html

index.html 文件中我们分别按照如下格式插入:

<h1>${IP}:${port}</h1>

#例如9100下的index.html
<h1>192.168.56.103:9100</h1>

NGINX 基本配置

Nginx 的配置文件都存放在 /etc/nginx 中,打开 /etc/nginx/nginx.conf 可以注意以下两行:

user  nginx;
...
http{
    ...
    include /etc/nginx/conf.d/*.conf;
}

说明其他的配置文件都存放在 conf.d 中,新建 webapp.conf,在里面插入:

server{
  listen 9100;
  server_name vm001.myhost.net;
  location / {
    root /opt/nginx/Webapp/9100;
    index index.html;
  }
}
server{
  listen 9200;
  server_name vm001.myhost.net;
  location / {
    root /opt/nginx/Webapp/9200;
    index index.html;
  }
}

重启 Nginx

systemctl restart nginx

# 发现报错,查看错误原因
systemctl status nginx -l

# 显示
... localhost.localdomain nginx[3405]: nginx: [emerg] bind() to 0.0.0.0:9100 failed (13: Permission denied)

是因为 Linux selinux 的安全检查,如果想要快速处理,可以直接临时关闭 setenforce 1 或永久关闭,修改 /etc/selinux/config 文件,将 SELINUX=enforcing 改为 SELINUX=disabled,重启机器。

但是非常不推荐这么做,我们可以通过增加安全端口的方式,首先安装 selinux 的管理器 semanage

yum install policycoreutils-python -y

通过命令查看当前允许的端口:

semanage port -l | grep http_port_t
http_port_t  tcp  80, 81, 443, 488, 8008, 8009, 8443, 9000

并加上自己端口

semanage port -m -t http_port_t -p tcp 9100
semanage port -m -t http_port_t -p tcp 9200

到这一步,还没结束,因为我们可以看到启动 Nginx 的用户是 nginx(在上文提到的 nginx.conf 文件中)这个用户没有权限查看 /opt/nginx/Webapp/ 下的 index.html,这里我们要为其添加权限:

chcon -Rt httpd_sys_content_t /opt/nginx/Webapp/

重启 Nginx

systemctl restart nginx

在主机浏览器访问 192.168.56.103:9100192.168.56.103:9200 发现都可以访问了。

NGINX 负载均衡配置

在保证 192.168.56.103:9100192.168.56.103:9200 都可以访问后,就可以开始做负载均衡配置了。

仍然在 /etc/nginx/conf.d/ 文件夹下创建 upstream.conf 文件

upstream loadbalance {
  server 192.168.56.103:9100 weight=1;
  server 192.168.56.103:9200 weight=1;
}

这部分是用于负载均衡的反向代理,使用的策略是均分流量,weight 代表的是流量分配比重,现在的比重是 1:1 也就是说通过 loadbalance 的流量会在 91009200 各占一半。

修改 /etc/nginx/conf.d/default.conf 文件,将 80 端口的流量指向 loadbalance

server{
	listen       80;
    server_name  localhost;
	...
    location / {
    	## 将以下两行注释
        #root   /usr/share/nginx/html; 
        #index  index.html index.htm;
        ## 添加以下
        proxy_pass http://loadbalance;
    }
    ...
}

重启 Nginx

systemctl restart nginx

在主机浏览器访问 192.168.56.103 ,通过刷新浏览器可以看到在 91009200 两个端口切换,说明负载均衡已经成功。

复制虚拟机

现在已经完成了一台虚拟机的配置,我们将其正常关闭,做一个 Snapshot (快照)。

在右上角的 虚拟电脑工具 的下拉按钮,找到 备份 按钮,点击 生成,即可做一个快照作为备份。

接着右击 testOS,复制,命名为 testOS2,点选重新初始化所有网卡的 MAC 地址,下一步,点击完全复制,等待几分钟完成。

接着,记录下 testOS2 的两张新AC 地址:

  • 网卡1 MAC 地址 080027911293
  • 网卡2 MAC 地址 0800275A727C

根据刚才的设置分别对以下部分进行修改:

  • MAC 地址修改
    • /etc/sysconfig/network-scripts/ifcfg-enp0s3
    • /etc/sysconfig/network-scripts/ifcfg-enp0s8
  • IP 地址修改
    • /etc/sysconfig/network-scripts/ifcfg-enp0s8 ( 192.168.56.103 -> 192.168.56.104 )
  • Webapp 修改
    • /opt/nginx/Webapp/9100/index.html ( 192.168.56.103 -> 192.168.56.104 )
    • /opt/nginx/Webapp/9200/index.html ( 192.168.56.103 -> 192.168.56.104 )
  • Nginx 配置修改
    • /etc/nginx./conf.d/webapp.conf ( vm001.myhost.net -> vm002.myhost.net )
    • /etc/nginx./conf.d/upstream.conf ( 192.168.56.103 -> 192.168.56.104 )

重启 networkNginx

systemctl restart network
systemctl restart nginx

可以看到已经能够成功访问。

hosts 映射

可能会发现,每次输入IP地址来访问 Web 非常奇怪,所以在刚才的设置中,会看到出现了 vm001.myhost.netvm002.myhost.net,这是我们自己设定的一个内部域名,如何才能通过这个域名来访问 Web 呢?

在主机的 hosts 文件中加入域名映射即可:

...
192.168.56.103 vm001.myhost.net
192.168.56.104 vm002.myhost.net

如果访问无法成功,请在 cmd 中输入 ipconfig /flushdns(如果你使用的是 Windows) 刷新 DNS。

当然,我们可以在这里添加一个 VIP 的域名映射,为后面的章节做准备:

...
192.168.56.108 vip.myhost.net

4. Keepalived 安装配置

Keepalived 安装

yum install keepalived -y
systemctl enable keepalived
systemctl start keepalived

Keepalived 配置

192.168.56.103 上编辑 /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   ...
}

vrrp_instance VI_1 {
    state MASTER
-   interface eth0
+   interface enp0s8
    virtual_router_id 51
-   priority 100
+   priority 130
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
-		//删去所有IP地址
-		192.168.200.16
-		192.168.200.17
-		192.168.200.18
+       192.168.56.108/24 brd 192.168.56.255
    }
}

在上面的配置中需要注意的是以下几个值:

  • state 的值为 MASTERBACKUP,按照分配,将 192.168.56.103设定为 MASTER 192.168.56.104 设定为 BACKUP
  • interface 应该改为 enp0s8 网卡接口;
  • priority 是服务器的优先级,在 MASTER 宕机时,会根据优先级在 BACKUP 选举出一个新的 MASTER,所以 MASTER要设为 100 以上;
  • virtual_router_id 值所有的 Keepalived 集群都需要保持为一致,这里的值是 51
  • virtual_ipaddress 就是你需要填写的 VIP 列表。

同样的,在 192.168.56.104 编辑 /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   ...
}

vrrp_instance VI_1 {
+   state MASTER
-   state BACKUP
-   interface eth0
+   interface enp0s8
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
-		//删去所有IP地址
-		192.168.200.16
-		192.168.200.17
-		192.168.200.18
+       192.168.56.108/24 brd 192.168.56.255
    }
}

重启两台服务器上的 Keepalived 服务

systemctl restart keepalived

重启后,在 192.168.56.103 上输入 ip addr 应该可以看到 VIP 已经绑定

1549005878556

至此,所有的配置都完成了,现在可以通过 vip.myhost.net 来访问了。(如果仍然无法访问,直接 reboot 服务器)

5. 测试

  1. 在主机浏览器上访问 vip.myhost.net
  2. 可以看到访问的是 192.168.56.103:9100192.168.56.103:9200
  3. 进行破坏测试,将 192.168.56.103 服务器强制关机;
  4. 可以发现,Keepalived 会及时将 VIP 和包漂移到 192.168.56.104 的备用服务器上;
  5. 此时访问 vip.myhost.net 可以看到192.168.56.104:9100192.168.56.104:9200
  6. 再次启动 192.168.56.103 服务器;
  7. Keepalived 会自动再将 VIP 转移到 192.168.56.103 服务器上。

(本文完)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions