项目名称:使用nginx和keepalived搭建高可用web集群
项目环境:centOS 7.9,nginx,keepalived,ansible,prometheus,nfs,bind,ab压力测试工具等
项目简介:
本项目旨在通过使用nginx和keepalived搭建高可用的web集群,提供稳定、可靠的web服务。通过使用ansible进行自动化配置管理,实现快速部署和维护。
项目步骤:
集群网络拓扑结构图如下所示:
为所有机器关闭防火墙和seLinux:
# 关闭防火墙
systemctl stop firewalld
# 临时关闭seLinux
setenforce 0
# 永久关闭
sed -i "/^SELINUX=/ s/enforcing/disabled/g" /etc/selinux/config
关闭防火墙之后,根据网络拓扑结构图为相关机器配置IP地址,以及按职责设置主机名称。
# 通过epel源安装ansible
yum install epel-release -y
yum install ansible -y
由于ansible底层通过ssh协议进行集群管理,要求需要配置ssh免密
ssh教学博客:ssh详解–让你彻底学会ssh
# 生成密钥
ssh-keygen
# 将密钥传入相关服务器,完成免密通道
# -i指定密钥文件,可不接默认使用~/.ssh/id_rsa.pub
ssh-copy-id [-i ~/.ssh/id_rsa.pub] [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
ssh-copy-id [email protected]
完成免密通道配置之后,使用ssh
命令测试免密通道配置是否成功(部分验证结果如下):
web1服务器连接测试结果:
web2服务器连接测试结果:
web3服务器连接测试结果:
prometheus服务器连接测试结果:
使用yum
安装方式安装ansible,在/etc/ansible
有一个hosts
文件,其中包含ansible管理和控制的远程主机清单。
# 进入hosts文件
vim /etc/ansible/hosts
# 写入下列内容
[webservers]
192.168.94.100
192.168.94.101
192.168.94.102
[monitor]
192.168.94.105
[load_balance]
192.168.94.107
192.168.94.108
[nfs]
192.168.94.103
[dnsserver]
192.168.94.106
ansible并非守护进程,修改相关配置文件之后,并不需要重启服务
在完成配置之后,使用ansible的ping
模块,通过控制机器ping
验证配置是否成功。
通过执行如下命令并查看结果:
ansible all -m ping
成功的预期结果如下所示:
your_host | SUCCESS => {
"changed": false,
"ping": "pong"
}
验证结果如下所示:
1. 撰写nginx一键安装脚本:
此处使用shell脚本以二进制编译的方式安装nginx
nginx二进制安装脚本如下所示:
#!/bin/bash
# 创建工作目录
mkdir -p /nginx
cd /nginx
# 创建nginx运行用户
useradd nginx -s /sbin/nologin
# 安装软件使用的依赖或辅助工具
yum install epel-release -y
yum install -y zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ autoconf automake make psmisc net-tools lsof vim geoip geoip-devel wget -y
# 下载nginx源码包
wget https://nginx.org/download/nginx-1.25.1.tar.gz
# 解压文件
tar xf nginx-1.25.1.tar.gz
cd nginx-1.25.1
# 指定部分nginx运行模块
./configure --prefix=/usr/local/bin/nginx --user=nginx --with-http_ssl_module --with-http_v2_module --with-threads --with-http_stub_status_module --with-stream
# 执行configure之后,会生成Makefile的编译蓝图文件
# 直接使用make即可进行安装
# 指定多线程安装
make -j 2
make install
# 将nginx的安装目录加入环境变量
echo "PATH=/usr/local/bin/nginx/sbin:$PATH" >> /etc/rc.local
echo "PATH=/usr/local/bin/nginx/sbin:$PATH" >> ~/.bashrc
chmod +x /etc/rc.local
export PATH=/usr/local/bin/nginx/sbin:$PATH
# 启动nginx
nginx
2. 使用ansible编写playbook将nginx安装脚本传送到web机器,并完成安装
在ansible编写上述one_key_install.sh
脚本,然后编写playbook文件nginx_playbook.yaml
nginx_playbook.yaml
文件内容如下所示:
- hosts: load_balance
remote_user: root
tasks:
- name: transfer script
copy:
src: ./one_key_install.sh
dest: ~/
notify:
- install nginx
handlers:
- name: install nginx
shell: bash ~/one_key_install.sh
该playbook有两个任务,第一个将nginx安装脚本传到web机器上,其次运行nginx安装脚本。
# 检查playbook文件语法
ansible-playbook --syntax-check nginx_playbook.yaml
# 确认无误执行playbook
ansible-playbook nginx_playbook.yaml
任务执行完成之后确认web集群nginx软件安装完毕,再次编写playbook文件check_nginx.yaml
内容如下所示:
- hosts: webservers
remote_user: root
tasks:
- name: check nginx
shell: pgrep nginx
register: nginx_process
ignore_errors: true
- name: Display nginx process status
debug:
msg: "Nginx process is {{ 'running' if nginx_process.rc == 0 else 'not running' }}"
执行结果:
3. 修改nginx相关参数配置
在ansible中控机上编写一份nginx.conf文件,在该文件中修改worker进程数,长连接数,日志文件格式等配置,然后通过ansible将该文件替换各web机器上的nginx配置文件
# 获取nginx.conf文件
ansible webservers -m fetch -a 'src=/usr/local/bin/nginx/conf/nginx.conf dest=~/'
nginx.conf主要文件修改内容如下所示:
...
# 修改worker进程数
worker_processes 2;
# 修改并发数
events {
worker_connections 2048;
}
...
http{
...
# 打开日志文件格式配置,并添加$http_x_real_ip
log_format main '$remote_addr - $http_x_real_ip - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 打开access_log logs/access.log main;
access_log logs/access.log main;
...
# 设置最大请求数
keepalive_requests 10000;
...
}
...
使用ansible替换各机器nginx.conf文件
文件名:change_nginx_config.yaml
,内容如下所示:
- hosts: webservers
remote_user: root
tasks:
- name: Change Nginx Config
copy:
src: ~/nginx.conf
dest: /usr/local/bin/nginx/conf/
backup: yes
notify:
- Reload Nginx service
handlers:
- name: Reload Nginx service
command: nginx -s reload
此处为web集群安装nginx之后,不对其展示内容进行修改
编写一键安装脚本:
脚本名称:one_key_install_prome.sh
编写完成之后与nginx安装一致,使用playbook文件通过ansible进行安装和运行
#!/bin/bash
# 关闭防火墙和selinux
systemctl stop firewalld
systemctl disable firewalld
sed -i "/^SELINUX/ s/enforcing/disabled/" /etc/selinux/config
# 创建工作目录
mkdir /prom
# 解压安装文件并将安装文件传入工作目录
tar xf prometheus-2.45.0-rc.0.linux-amd64.tar.gz
mv prometheus-2.45.0-rc.0.linux-amd64 /prom/prometheus
# 将Prometheus制作为主机服务
cat << EOF > /usr/lib/systemd/system/prometheus.service
[Unit]
Description=prometheus
[Service]
ExecStart=/prom/prometheus/prometheus --config.file=/prom/prometheus/prometheus.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# 刷新服务
systemctl daemon-reload
# 使用systemctl命令重新启动prometheus
systemctl start prometheus
systemctl enable prometheus
# 查看运行结果
systemctl status prometheus
prometheus的playbook安装文件:
- hosts: monitor
remote_user: root
tasks:
- name: transfer script
copy:
src: ./one_key_install_prom.sh
dest: ~/
notify:
- prometheus install
handlers:
- name: prometheus install
shell: bash ~/one_key_insatll_prom.sh
确保playbook完美执行成功:
使用浏览器访问prometheus网页(192.168.94.105:9090),查看prometheus安装情况,以下结果即安装成功:
在上一步为web集群安装nginx时,已经准备好playbook文件,此处直接运行命令进行安装即可:(需将组名改为对应主机组load_balance)
# 为负载均衡服务器安装nginx
ansible-playbook nginx_playbook.yaml
验证安装结果:
此处使用同样的方法,通过在ansible中控机上修改预设config文件再通过替换load balance机器的config文件来实现配置修改。
负载均衡机器nginx.config
文件主要修改如下:
http{
......
upstream webservers{
server 192.168.94.100;
server 192.168.94.101;
server 192.168.94.102;
}
......
server{
...
location / {
proxy_pass http://webservers;
# 获取真实IP地址,以便做日志分析
proxy_set_header X-Real-IP $remote_addr;
}
...
}
}
通过修改之前编写playbook文件(主要修改组名为load_balance)替换负载均衡机器nginx配置文件:
ansible-playbook change_nginx_config.yaml
此处使用的nginx为7层负载均衡,然后使用IP-hash的负载均衡方式,通过使用tail -f
命令查看web服务器的nginx日志(access.log),命令如下:
tail -f /usr/local/bin/nginx/logs/access.log
通过该命令紧盯文件末尾,一直查看被访问日志,并且使用IP-hash的方式,同一IP地址访问会转发至同一台web服务器上,而且该日志中显示IP地址应该为负载均衡器IP地址。
使用浏览器访问其中一台负载均衡器,可得到如下结果:
至此,集群基本的web服务功能已经实现。
在完成基本的web功能之后,通过搭建一个nfs服务器,实现web服务器之间共享同一个页面显示文件(文件共享)
部署nfs服务:
所有需要使用nfs服务的机器均需要安装nfs服务,这也包括挂载nfs文件的web服务器
# 安装nfs服务
yum install nfs-utils -y
#为所有的web服务器安装nfs服务
ansible webservers -m yum -a "name=nfs-utils state=installed"
# 启动nfs服务
systemctl start nfs
systemctl enable nfs
安装完成nfs服务之后,设置共享目录,共享内容为nginx服务器显示页面
此处操作可在ansible中控机上执行。
# 在nfs服务器上设置挂载文件
# 通过修改nfs服务器上/etc/exports文件挂载提前准备好的web页面文件
# 创建挂载文件夹
mkdir /html
cat << EOF > /html/index.html
hello, world! This is my web
EOF
设置共享文件之后,通过编写yaml文件使用ansible为web服务器进行文件挂载
playbook文件内容如下所示:
- hosts: webservers
remote_user: root
tasks:
- name: Monut NFS
mount:
path: /usr/local/bin/nginx/html
src: 192.168.94.103:/html
fstype: nfs
opts: "defaults"
state: mounted
上述挂载只是临时挂载,还需要实现开机自动挂载。
相关ansible playbook文件如下所示:
实现开机自动挂载
- hosts: webservers
remote_user: root
tasks:
- name: Auto Monut
lineinfile:
dest: /etc/fstab
line: "192.168.94.103:/html /usr/local/bin/nginx/html nfs defaults 0 0"
state: present
挂载文件完成之后,可以通过访问对应网页进行验证,也可以使用df -Th
查看web服务器的磁盘分区来验证配置结果。
df -Th
命令查看结果:
浏览器通过访问负载均衡服务器查看结果:
在前面的步骤中,已经为监控服务器安装好了prometheus监控软件,而现在需要为每台服务器安装后门软件,为监控服务器提供监控数据来源,并确保各服务器正常运行。
监控服务器的职责是监控整个集群的性能,所以需要为所有的服务器安装ndoe_exporter数据获取软件。
提前准备node_exporter安装包及其一键安装脚本,通过ansible传递至各个服务器上,并进行安装。
一键安装脚本one_key_install_node_exporter.sh
如下所示:
#!/bin/bash
# 解压文件夹
tar -xf ~/node_exporter-1.6.0.linux-amd64.tar.gz
# 移动文件至工作目录
mv ~/node_exporter-1.6.0.linux-amd64 /node_exporter
# 将node_expoerter制作为主机服务
cat << EOF > /usr/lib/systemd/system/node_exporter.service
[Unit]
Description=prometheus
[Service]
ExecStart=/node_exporter/node_exporter --web.listen-address 0.0.0.0:9090
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# 刷新服务
systemctl daemon-reload
# 使用systemctl命令启动node_exporter
systemctl start node_exporter
systemctl enable node_exporter
# 查看安装结果
systemctl status node_exporter
playbook文件如下所示:
- hosts: webservers:load_balance:nfs:dnsserver
remote_user: root
tasks:
- name: Copy Node_Exports
copy:
src: ./node_exporter-1.6.0.linux-amd64.tar.gz
dest: ~/
- name: Copy One key Install Shell
copy:
src: ./one_key_install_node_exporter.sh
dest: ~/
notify:
- install node exporter
handlers:
- name: install node exporter
shell: bash one_key_install_node_exporter.sh
在为集群服务安装node_exporter之后,可通过访问IP地址:8090/metrics
来确定配置结果
在确定安装node_exporter之后,还需对prometheus服务器进行配对服务器数据进行获取。
通过ansible替换prometheus配置的方法来修改prometheus配置文件。
首先获取prometheus配置文件
ansible monitor -m fetch -a "src=/prom/prometheus/prometheus.yml dest=~/"
prometheus配置文件添加如下配置:
scrape_configs:
# The job name is added as a label `job=` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ["localhost:9090"]
# 主要修改位置
- job_name: "allservers"
static_configs:
- targets: ["192.168.94.100:9090","192.168.94.101:9090","192.168.94.102:9090","192.168.94.103:9090","192.168.94.104:9090","192.168.94.106:9090","192.168.94.107:9090","192.168.94.108:9090"]
使用ansible替换配置文件并重启prometheus服务:
- hosts: monitor
remote_user: root
tasks:
- name: copy config
copy:
src: ~/prometheus.yml
dest: /prom/prometheus
notify:
- restart service
handlers:
- name: restart service
shell: systemctl restart prometheus
使用浏览器进入192.168.94.105:9090/targets
网页验证服务器数据抓取结果:
由于prometheus自带的web UI图片显示效果并不好,所以使用Grafana用于参数显示
在prometheus服务器上安装Grafana软件,playbook如下所示:
- hosts: monitor
remote_user: root
tasks:
- name: Copy Grafana Rpm
copy:
src: ~/grafana-enterprise-10.1.1-1.x86_64.rpm
dest: ~/
notify:
- install Grafana
handlers:
- name: install Grafana
yum:
name: grafana-enterprise-10.1.1-1.x86_64.rpm
state: installed
后续还需在prometheus启动grafana服务,此处不再赘述
访问192.168.94.105:3000
查看效果:
然后在grafana网页配置prometheus源并且设置恰当数据可视化模板
在前面的步骤已经开启高可用服务器的nginx反向代理功能,但是并未配置keepalived软件,不好做消息转发,以及高可用未实现。
使用ansible中控机控制高可用服务器安装keepalived
ansible load_balance -m yum -a "name=keepalived state=installed"
keepalived配置文件如下所示:
LB1(192.168.94.107):
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
# vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_nginx{
script "/etc/keepalived/chck_nginx.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 60
priority 110
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.94.188
}
track_script {
chk_nginx
}
}
vrrp_instance VI_2 {
state BACKUP
interface ens33
virtual_router_id 61
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.94.199
}
track_script {
chk_nginx
}
}
LB2(192.168.94.108):
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
# vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_nginx {
script "/etc/keepalived/chck_nginx.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 60
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.94.188
}
track_script {
chk_nginx
}
}
vrrp_instance VI_2 {
state MASTER
interface ens33
virtual_router_id 61
priority 110
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.94.199
}
}
track_script {
chk_nginx
}
}
当一台高可用机器的nginx挂掉之后,这台高可用机器不应该再拥有VIP,即优先级应该降低。
检测脚本如下所示:
#!/bin/bash # 判断nginx是否运行 if pidof nginx >/dev/null 2>&1;then exit 0 else exit 1 fi
至此,除去dns服务外,所有服务部署完毕。
部署dns服务器的目的是为了将双vip绑定在同一个域名上,并提供相关的域名解析功能,再二外提供。
在一台服务器上安装dns服务,再将其服务器做成dns主域名服务器,对集群域名做解析:
# 安装dns服务
yum install bind* -y
# 运行dns服务
systemctl start named
systemctl enable named
对dns服务相关配置文件进行修改,对其他主机提供域名解析服务,并将该服务器搭建为主域名服务器。
修改named配置文件配置文件,文件路径:/etc/named.conf
,部分配置文件如下所示(修改部分):
options {
listen-on port 53 { any; };
listen-on-v6 port 53 { any; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
recursing-file "/var/named/data/named.recursing";
secroots-file "/var/named/data/named.secroots";
allow-query { any; };
通过修改/etc/named.rfc1912.zones
文件添加主域名解析,为集群web网页设置自定义的域名(该项目域名设置为:webceshi.cn
)。
/etc/named.rfc1912.zones
配置文件修改如下(仅展示修改添加部分):
zone "webceshi.cn" IN {
type master;
file "/var/named/webceshi.cn.zone";
allow-update { none; };
};
修改格式如下所示:
zone "需要解析的域名" IN { type master; file "解析文件"; allow-update { none; }; };
添加解析文件,此处文件名称为:/var/named/webceshi.cn.zone
文件内容如下所示:
$TTL 1D
@ IN SOA @ rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS @
A 127.0.0.1
AAAA ::1
webceshi.cn. IN A 192.168.94.188
webceshi.cn. IN A 192.168.94.199
一定要修改/var/named/webceshi.cn.zone
的文件属组:
chown root:named /var/named/webceshi.cn.zone
配置文件修改完成重启named服务
systemctl restart named
将Linux客户机域名服务器IP地址修改为该域名服务器,并测试解析服务是否成功。
Linux机器nslookup
命令查询结果:
Linux机器curl
命令获取结果:
在客户机上安装ab软件,然后通过ab对集群进行压力测试
安装ab软件
yum install httpd-tools -y
在客户机上执行压力测试命令
ab -n 10000 -c 10 http://192.168.94.107/
然后可以得到相关性能参数。
通过测试结果,对Linux机器的内核信息进行优化,可以通过使用ulimit
命令查看内核参数。修改内核参数使得web服务器性能释放。