Keepalived通过VIP实现Nginx,NTP的高可用,Nginx做DNS的负载均衡

一、整体架构如下

设备ip 服务 描述
0.9 Keepalived/Nginx/NTP/DNS 高可用-主、Nginx负载DNS、NTP服务、DNS服务
0.8 Keepalived/Nginx/NTP 高可用-备、Nginx负载DNS、NTP服务
0.2 DNS, ghfs服务 DNS服务, ghfs服务

架构

二、Keepalived通过VIP实现高可用

在.8和.9服务器上都部署Keepalived,.9作为主节点,.8作为备节点,使用.19作为虚ip,并编写健康检查脚本。

(1) 使用介绍

1、Keepalived虚拟ip机制
通过虚拟IP(VIP 0.19)在两台服务器(192.168.0.8/0.9)之间实现IP漂移。

2、脚本实现健康检查
通过自定义脚本持续检测节点健康状态,异常节点自动放弃VIP持有权。

3、优先级选举情况
主节点(MASTER)默认配置更高优先级,备节点(BACKUP)处于待命状态。

4、主备节点使用对比

节点IP 角色 优先级 健康检查脚本
192.168.0.9 MASTER 100 自定义检测逻辑
192.168.0.8 BACKUP 50 自定义检测逻辑

5、VIP漂移逻辑说明

主节点状态 备节点状态 VIP持有者 说明
健康 健康 主节点(0.9) 主节点优先持有VIP
健康 异常 主节点(0.9) 备节点故障不影响主节点服务
异常 健康 备节点(0.8) 主节点故障触发VIP自动迁移
异常 异常 无持有者 双节点故障导致服务不可用

Keepalived通过vip实现高可用,在两台机器上安装完成后,启动Keepalived,keepalived会通过脚本健康检查,根据设备的健康情况,来决定虚ip飘到哪台机器上。具体场景示例:

双节点正常

  • MASTER(0.9):持有VIP 0.19
  • BACKUP(0.8):保持监听状态

主节点故障恢复
当主节点恢复健康后,VIP将通过”抢占模式”自动回切到主节点

(2) 配置文件说明

1、keepalived配置文件路径

/etc/keepalived/keepalived.conf

2、配置文件内容

global_defs {
router_id LVS_MASTER
}

vrrp_script chk_services {
script "/usr/local/bin/check_services.sh" # 健康检查脚本的路径
interval 2
weight -50
fall 2
rise 2
}

vrrp_instance VI_1 {
state MASTER # MASTER主节点,BACKUP备节点
unicast_src_ip 192.168.0.9 # 本机真实IP
interface eth0 # 根据实际网卡修改( 通过ip a , 查看当前设备的ip使用哪个网口)
virtual_router_id 51 # 主备节点必须一致,VRRP 协议依赖 virtual_router_id 识别同一个高可用组内的主备节点,若 ID 不同,主备节点会被视为独立无关的组,导致 VIP 无法漂移。
priority 100 # 主服务器优先级更高,
advert_int 1
authentication {
auth_type PASS
auth_pass 12341234 # 验证密码,主备节点必须一致,要求8位
}
virtual_ipaddress {
192.168.0.19/24 # 虚拟ip以及掩码位,替换为你的VIP
}
track_script {
chk_services
}
}

3、健康检查监本

只检查nginx作为健康状态

#!/bin/bash

# 检查 Nginx 服务状态
if systemctl is-active nginx >/dev/null 2>&1; then
exit 0 # 服务正常,返回 0
else
exit 1 # 服务异常,返回非 0
fi

多服务健康检查

# 检查多个服务(Nginx + NDP)
#!/bin/bash

services=("nginx" "ndp") # 按需替换服务名

for service in "${services[@]}"; do
if ! systemctl is-active "$service" >/dev/null 2>&1; then
exit 1 # 任一服务异常则退出
fi
done

exit 0 # 所有服务正常

三、nginx实现DNS负载均衡

nginx主要是应用层的负载,DNS使用的是UDP的53端口,属于传输层的负载,所以nginx还需要stream插件支持,这里使用nginx_upstream_check_module-master

(1)nginx负载分析以及问题

现在是3台服务器,两台nginx,两台dns,那么必然有一台同时部署了nginx与dns。那么nginx与dns就会存在一个端口冲突问题。

1、53端口冲突问题
因nginx与dns都会监听53端口,所以存在冲突

解决方案:

  • dns监听本机地址的53端口,即:127.0.0.1:53
  • nginx监听虚ip的53的端口,即:192.168.0.19:53

2、keepalived的虚ip不存在时,nginx无法绑定虚ip的53端口
当本机异常时,虚ip会飘到备用节点,那么本机就么有虚ip了,此时nginx就会报错,因它需要监听虚ip的53端口。
也就是说,只有当本机存在虚ip时,才能正常启动nginx

可通过ip a命令,查看ip情况,看是否拥有vip

[root@i-sq7eZizx7-2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether fa:16:3a:88:fb:11 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.9/24 brd 10.18.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet 192.168.0.19/24 scope global secondary eth0
valid_lft forever preferred_lft forever
inet6 fe80::f813:3aff:fe85:fa11/64 scope link
valid_lft forever preferred_lft forever

3、当节点没有vip时,如何启动nginx

可暂时先关闭另一节点的keepalived,这样vip就会飘到当前节点,就可以正常nginx了

(2) nginx负载配置文件**

配置文件目录:(可通过whereis nginx.conf查看)
/usr/local/nginx/conf/nginx.conf

[root@i-sq7eZizx7-2 ~]# cat /usr/local/nginx/conf/nginx.conf
# /etc/nginx/nginx.conf 或 /usr/local/nginx/conf/nginx.conf

worker_processes auto;

# 设置 Nginx 的 worker 进程数量
#worker_processes auto;

events {
worker_connections 1024;
}

# 配置负载均衡的 stream 模块
stream {

# 定义日志格式(可自定义字段)
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time';

# 启用日志
access_log /var/log/nginx/stream_access.log basic;
error_log /var/log/nginx/stream_error.log;

# 定义 DNS 服务器集群
upstream dns_cluster {
server 127.0.0.1:53 max_fails=3 fail_timeout=30s; # DNS服务器1, 后端DNS服务器监听本机的53端口,避免与Nginx的冲突
server 192.168.0.2:53 max_fails=3 fail_timeout=30s; # DNS服务器2

# 这里可以根据需要调整健康检查
# check interval=3000 rise=2 fall=3 timeout=1000 type=tcp;
}

# TCP 协议监听
server {
listen 192.168.0.19:53; # 监听端口 53 (TCP) 前端监听入口虚ip的53端口,避免与DNS的冲突
proxy_pass dns_cluster; # 将请求转发给 dns_cluster
proxy_connect_timeout 1s; # 与 upstream 服务器连接的超时时间
proxy_timeout 3s; # 代理超时时间
}

# UDP 协议监听
server {
listen 192.168.0.19:53 udp reuseport; # 监听端口 53 (UDP) 前端监听入口虚ip的53端口,避免与DNS的冲突。
proxy_pass dns_cluster; # 将请求转发给 dns_cluster
# proxy_responses 1; # 预期接收的响应数量
proxy_timeout 3s; # 代理超时时间
}
}

四、 DNS服务named的配置文件

1、DNS配置文件路径

/etc/named.conf

2、配置文件内容

options {
listen-on port 53 { 127.0.0.1; }; #这里绑定127.0.0.1是为了避免和nginx 53端口冲突问题,正常情况可设置为any;
listen-on-v6 port 53 { none; };
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";
secroots-file "/var/named/data/named.secroots";
recursing-file "/var/named/data/named.recursing";
allow-query { any; };

/*
- If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
- If you are building a RECURSIVE (caching) DNS server, you need to enable
recursion.
- If your recursive DNS server has a public IP address, you MUST enable access
control to limit queries to your legitimate users. Failing to do so will
cause your server to become part of large scale DNS amplification
attacks. Implementing BCP38 within your network would greatly
reduce such attack surface
*/
recursion yes;

dnssec-enable yes;
dnssec-validation yes;

managed-keys-directory "/var/named/dynamic";

pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";

/* https://fedoraproject.org/wiki/Changes/CryptoPolicy */
include "/etc/crypto-policies/back-ends/bind.config";
};

logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};

zone "." IN {
type hint;
file "named.ca";
};

include "/etc/named.rfc1912.zones"; # 这是解析区域文件的目录
include "/etc/named.root.key";

DNS服务启动方式

systemctl start named

五、 内网NDP服务(时间服务器)

1、安装ntp

yum install ntp

2、编辑配置文件:/etc/ntp.conf

使用设备的本地时间作为时间源的配置:


driftfile /var/lib/ntp/drift

# 本地时钟作为备用(Stratum 10)
server 127.127.1.0
fudge 127.127.1.0 stratum 1

# Permit time synchronization with our time source, but do not
# permit the source to query or modify the service on this system.
# restrict default nomodify notrap nopeer noepeer noquery

# Permit association with pool servers.
# 用于限制外部客户端对NTP服务的访问权限,禁止其修改配置、发送控制消息、建立对等关联和查询时间信息
#restrict source nomodify notrap noepeer noquery

# Permit all access over the loopback interface. This could
# be tightened as well, but to do so would effect some of
# the administrative functions.
# restrict 127.0.0.1
# restrict ::1

# Hosts on local network are less restricted.
# 允许内网设备访问该时间服务器
#restrict 192.168.0.0 mask 255.255.255.0 nomodify notrap

# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# pool 2.kylin.pool.ntp.org iburst

# Reduce the maximum number of servers used from the pool.
# tos maxclock 5指令用于控制NTP服务器在同步时间时考虑的最大候选服务器数量,设置为5意味着最多使用5个候选服务器。
# tos maxclock 5

# Enable public key cryptography.
# crypto

# 编辑 NTP 配置文件(如 /etc/ntp.conf)
# 从NTP主服务器上同步时间
#server 192.168.0.9 prefer

includefile /etc/ntp/crypto/pw

示例1:

driftfile /var/lib/ntp/drift

# Permit time synchronization with our time source, but do not
# permit the source to query or modify the service on this system.
# restrict default nomodify notrap nopeer noepeer noquery

# Permit association with pool servers.
# 用于限制外部客户端对NTP服务的访问权限,禁止其修改配置、发送控制消息、建立对等关联和查询时间信息
restrict source nomodify notrap noepeer noquery

# Permit all access over the loopback interface. This could
# be tightened as well, but to do so would effect some of
# the administrative functions.
# restrict 127.0.0.1
# restrict ::1

# Hosts on local network are less restricted.
# 允许内网设备访问该时间服务器
restrict 192.168.0.0 mask 255.255.255.0 nomodify notrap

# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# pool 2.kylin.pool.ntp.org iburst

# Reduce the maximum number of servers used from the pool.
# tos maxclock 5指令用于控制NTP服务器在同步时间时考虑的最大候选服务器数量,设置为5意味着最多使用5个候选服务器。
tos maxclock 5

# Enable public key cryptography.
# crypto

includefile /etc/ntp/crypto/pw

配置上游NTP服务器
阿里云与腾讯云

server ntp.aliyun.com iburst  
server ntp1.tencent.com iburst

**从NTP主服务器上同步时间 **

server 192.168.0.9 prefer

启动开机自启服务

sudo systemctl enable ntpd --now

**3、启动ntp服务

systemctl start ntpd

4、防火墙放行ntp服务

sudo firewall-cmd --add-service=ntp --permanent
sudo firewall-cmd --reload

放行123端口

sudo firewall-cmd --add-port=123/udp --permanent
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-ports

5、从远程服务器同步时间代码

#!/bin/bash
internal_ip="192.168.1.100"
timestamp=$(ssh user@$internal_ip "date +%s")
sudo date -s "@$timestamp" //设置时间 date -s "2022-01-01 12:00:00"

6、检查当前系统时间与硬件时钟

# 查看系统时间
date

# 查看硬件时钟
hwclock

7、手动同步系统时间到硬件时钟
必须同步硬件时钟

# 临时设置系统时间(示例:设置为2024-03-01 12:00)
sudo date -s "2024-03-01 12:00:00"

# 将系统时间同步到硬件时钟
sudo hwclock --systohc

NTP服务测试

测试NTP服务器连通性(同时会同步本地时间)

ntpdate -d 192.168.0.9

查询服务器时间

ntpdate -q 10.18.0.9

查看123端口是可访问

nc -vzu 192.168.0.9 123  (好像不太准确,一直都是success)

云虚拟机NTP的注意事项

麒麟V10云虚拟机上的时间,发现根本修改不了,修改后,过一会会自动恢复,应该是内部有时间同步的功能。

YUM查看已安装的服务(nginx示例)

yum list installed | grep nginx

mac电脑设置时间源之后,需要重启或睡眠一会,再次进入才会同步时间

微信打赏

意外收获认可,内心充满感激;打赏之举,更添无限动力。