OpenEuler系统全栈自动化部署实战
一、前言
在之前的Playbook系列文章中,我们学习了Ansible的基础语法、变量、条件判断、循环和Handlers等核心概念。本文将通过一个综合性的实战案例,演示如何使用Ansible Playbook在OpenEuler系统上一键部署一个完整的企业级服务集群,包括:远程获取SSH密钥认证、部署Nginx Web服务、搭建Keepalived高可用反向代理集群、配置DNS域名解析服务以及DHCP动态IP分配服务。
本文将按照CSDN博客的完整格式,带你从环境规划、目录结构设计到Playbook编写,一步步完成整个自动化部署项目。
二、环境规划
2.1 主机清单(Inventory)
在Ansible控制节点192.168.64.128上,编辑/etc/ansible/hosts文件:
bash
[all:vars]
ansible_user=root
ansible_password=openeuler123
# ansible_ssh_private_key_file=/root/.ssh/id_rsa # 密钥认证后可切换为私钥认证
[webservers]
192.168.64.100
192.168.64.101
[loadbalancers]
192.168.64.200 priority=100 state=MASTER vip=192.168.64.250
192.168.64.201 priority=90 state=BACKUP vip=192.168.64.250
[dnsserver]
192.168.64.108
[dhcpserver]
192.168.64.109
2.2 服务器角色规划
| IP地址 | 主机名建议 | 角色说明 |
|---|---|---|
| 192.168.64.100 | web01 | Nginx Web服务器(主) |
| 192.168.64.101 | web02 | Nginx Web服务器(备) |
| 192.168.64.108 | dns01 | DNS域名解析服务器 |
| 192.168.64.109 | dhcp01 | DHCP动态IP分配服务器 |
| 192.168.64.200 | lb01 | Keepalived + Nginx反向代理(Master) |
| 192.168.64.201 | lb02 | Keepalived + Nginx反向代理(Backup) |
| 192.168.64.128 | ansible | Ansible控制节点 |
2.3 VIP规划
-
VIP地址:192.168.64.250
-
作用:Keepalived虚拟IP,作为整个集群的统一入口,客户端访问此VIP即可获得Nginx反向代理服务
三、项目目录结构
在Ansible控制节点上创建如下目录结构:
bash
mkdir -p /ansible/playbooks/roles/{common,nginx,keepalived,dns,dhcp}/{tasks,handlers,templates,files,vars}
mkdir -p /ansible/playbooks/{group_vars,host_vars}
完整目录结构:
bash
/ansible/playbooks/
├── site.yml # 主入口Playbook
├── ssh_key_distribution.yml # SSH密钥分发Playbook
├── inventory # 主机清单文件
├── group_vars/
│ └── all.yml # 全局变量
├── roles/
│ ├── common/
│ │ └── tasks/
│ │ └── main.yml # 通用任务(防火墙、SELinux等)
│ ├── nginx/
│ │ ├── tasks/
│ │ │ └── main.yml # Nginx安装配置任务
│ │ ├── handlers/
│ │ │ └── main.yml # Nginx服务重启处理
│ │ ├── templates/
│ │ │ ├── nginx.conf.j2 # Nginx主配置模板
│ │ │ └── index.html.j2 # Web页面模板
│ │ └── vars/
│ │ └── main.yml
│ ├── keepalived/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ └── templates/
│ │ ├── keepalived.conf.j2
│ │ └── nginx-lb.conf.j2 # 反向代理配置模板
│ ├── dns/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ └── templates/
│ │ ├── named.conf.j2
│ │ └── zone.db.j2
│ └── dhcp/
│ ├── tasks/
│ │ └── main.yml
│ └── templates/
│ └── dhcpd.conf.j2
└── files/
└── id_rsa.pub # Ansible控制节点的SSH公钥
四、SSH密钥远程分发
在执行所有自动化部署任务之前,首先需要将Ansible控制节点的SSH公钥分发到所有目标主机,实现免密登录。这一步是后续Playbook顺畅执行的基础。
4.1 生成SSH密钥对
在Ansible控制节点上执行:
bash
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa
4.2 编写SSH密钥分发Playbook
创建/ansible/playbooks/ssh_key_distribution.yml:
bash
---
- name: 分发SSH公钥到所有目标主机
hosts: all
gather_facts: no
vars:
ansible_user: root
ansible_password: "openeuler123" # 首次连接使用的密码
tasks:
- name: 确保目标主机.ssh目录存在
ansible.builtin.file:
path: /root/.ssh
state: directory
owner: root
group: root
mode: '0700'
- name: 读取控制节点的SSH公钥
ansible.builtin.slurp:
src: /root/.ssh/id_rsa.pub
register: ssh_pub_key
delegate_to: localhost
run_once: true
- name: 将公钥添加到目标主机的authorized_keys
ansible.posix.authorized_key:
user: root
state: present
key: "{{ ssh_pub_key.content | b64decode }}"
exclusive: no
manage_dir: yes
- name: 关闭SSH密码认证(可选,提高安全性)
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PasswordAuthentication'
line: 'PasswordAuthentication no'
state: present
notify: restart sshd
handlers:
- name: restart sshd
ansible.builtin.service:
name: sshd
state: restarted
执行命令:
bash
ansible-playbook /ansible/playbooks/ssh_key_distribution.yml
注意 :
authorized_key模块位于ansible.posix集合中,如果未安装,先执行:bash
ansible-galaxy collection install ansible.posix
密钥分发成功后,可以将inventory中的密码认证注释掉,改用私钥认证:
bash
[all:vars]
ansible_user=root
ansible_ssh_private_key_file=/root/.ssh/id_rsa
# ansible_password=openeuler123 # 已注释
五、全局变量配置
创建/ansible/playbooks/group_vars/all.yml:
bash
---
# 网络配置
domain_name: "example.local"
dns_server: "192.168.64.108"
dhcp_server: "192.168.64.109"
gateway: "192.168.64.2"
netmask: "255.255.255.0"
network: "192.168.64.0"
# Nginx Web配置
nginx_version: "1.20.1"
web_domain: "www.example.local"
web_root: "/usr/share/nginx/html"
# Keepalived配置
vip_address: "192.168.64.250"
vip_interface: "ens33" # 根据实际网卡修改
vrid: 51
# DNS配置
dns_zone: "example.local"
dns_network_reverse: "64.168.192"
dns_forwarders:
- "114.114.114.114"
- "8.8.8.8"
# DHCP配置
dhcp_subnet: "192.168.64.0"
dhcp_netmask: "255.255.255.0"
dhcp_range_start: "192.168.64.150"
dhcp_range_end: "192.168.64.200"
dhcp_lease_time: 3600
dhcp_max_lease_time: 7200
六、通用角色(common)
创建/ansible/playbooks/roles/common/tasks/main.yml:
bash
---
- name: 关闭SELinux
ansible.builtin.selinux:
state: disabled
- name: 停止并禁用firewalld
ansible.builtin.service:
name: firewalld
state: stopped
enabled: no
ignore_errors: yes
- name: 安装基础工具包
ansible.builtin.dnf:
name:
- vim
- wget
- curl
- net-tools
- lsof
- tcpdump
- bash-completion
state: present
- name: 配置hosts文件
ansible.builtin.lineinfile:
path: /etc/hosts
line: "{{ item }}"
state: present
loop:
- "192.168.64.100 web01 web01.example.local"
- "192.168.64.101 web02 web02.example.local"
- "192.168.64.108 dns01 dns01.example.local"
- "192.168.64.109 dhcp01 dhcp01.example.local"
- "192.168.64.200 lb01 lb01.example.local"
- "192.168.64.201 lb02 lb02.example.local"
- "{{ vip_address }} vip.example.local"
七、Nginx Web服务器角色
7.1 Nginx安装配置任务
创建/ansible/playbooks/roles/nginx/tasks/main.yml:
bash
---
- name: 安装Nginx依赖包
ansible.builtin.dnf:
name:
- gcc
- pcre
- pcre-devel
- zlib
- zlib-devel
- openssl
- openssl-devel
state: present
- name: 安装Nginx(使用openEuler官方源)
ansible.builtin.dnf:
name: nginx
state: present
- name: 创建Web根目录
ansible.builtin.file:
path: "{{ web_root }}"
state: directory
owner: nginx
group: nginx
mode: '0755'
- name: 配置Nginx主配置文件
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: restart nginx
- name: 部署自定义首页
ansible.builtin.template:
src: index.html.j2
dest: "{{ web_root }}/index.html"
owner: nginx
group: nginx
mode: '0644'
- name: 启动Nginx服务并设置开机自启
ansible.builtin.service:
name: nginx
state: started
enabled: yes
7.2 Nginx配置模板
创建/ansible/playbooks/roles/nginx/templates/nginx.conf.j2:
nginx
bash
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
gzip on;
gzip_vary on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
server {
listen 80;
server_name {{ ansible_default_ipv4.address }} {{ ansible_hostname }} {{ web_domain }};
root {{ web_root }};
location / {
index index.html index.htm;
}
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
}
7.3 自定义首页模板
创建/ansible/playbooks/roles/nginx/templates/index.html.j2:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Ansible自动化部署 - Nginx Web服务器</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
.container { max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
.info { background: #ecf0f1; padding: 15px; border-radius: 5px; margin: 20px 0; }
.footer { margin-top: 30px; color: #7f8c8d; font-size: 14px; text-align: center; }
</style>
</head>
<body>
<div class="container">
<h1>🚀 Ansible自动化部署成功!</h1>
<div class="info">
<p><strong>服务器信息:</strong></p>
<ul>
<li>主机名:{{ ansible_hostname }}</li>
<li>IP地址:{{ ansible_default_ipv4.address }}</li>
<li>操作系统:{{ ansible_distribution }} {{ ansible_distribution_version }}</li>
<li>内核版本:{{ ansible_kernel }}</li>
<li>部署时间:{{ ansible_date_time.iso8601 }}</li>
</ul>
</div>
<p>🎉 恭喜!Nginx Web服务器已通过Ansible Playbook成功部署在OpenEuler系统上。</p>
<div class="footer">
<p>Powered by Ansible | OpenEuler | Nginx</p>
</div>
</div>
</body>
</html>
7.4 Handlers
创建/ansible/playbooks/roles/nginx/handlers/main.yml:
bash
---
- name: restart nginx
ansible.builtin.service:
name: nginx
state: restarted
八、Keepalived + Nginx反向代理角色
在两台负载均衡器(192.168.64.200和192.168.64.201)上部署Keepalived实现高可用,同时配置Nginx作为反向代理,将请求转发到后端Web服务器。Keepalived基于VRRP协议实现故障切换与健康检查功能。
8.1 Keepalived安装配置任务
创建/ansible/playbooks/roles/keepalived/tasks/main.yml:
bash
---
- name: 安装Nginx(反向代理)
ansible.builtin.dnf:
name: nginx
state: present
- name: 安装Keepalived
ansible.builtin.dnf:
name: keepalived
state: present
- name: 启用IP转发
ansible.builtin.sysctl:
name: net.ipv4.ip_forward
value: '1'
sysctl_set: yes
state: present
reload: yes
- name: 配置Nginx反向代理
ansible.builtin.template:
src: nginx-lb.conf.j2
dest: /etc/nginx/conf.d/loadbalancer.conf
owner: root
group: root
mode: '0644'
notify: reload nginx
- name: 备份原有Keepalived配置
ansible.builtin.copy:
src: /etc/keepalived/keepalived.conf
dest: /etc/keepalived/keepalived.conf.bak
remote_src: yes
force: no
ignore_errors: yes
- name: 配置Keepalived
ansible.builtin.template:
src: keepalived.conf.j2
dest: /etc/keepalived/keepalived.conf
owner: root
group: root
mode: '0644'
notify: restart keepalived
- name: 启动Nginx服务
ansible.builtin.service:
name: nginx
state: started
enabled: yes
- name: 启动Keepalived服务
ansible.builtin.service:
name: keepalived
state: started
enabled: yes
8.2 Nginx反向代理配置模板
创建/ansible/playbooks/roles/keepalived/templates/nginx-lb.conf.j2:
bash
# Nginx反向代理配置 - 负载均衡器
upstream backend_web {
# 使用加权轮询算法,将请求分发到后端Web服务器
server 192.168.64.100:80 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.64.101:80 weight=1 max_fails=3 fail_timeout=30s;
# 开启会话保持
keepalive 32;
}
upstream backend_api {
# API反向代理后端服务
server 192.168.64.100:8080 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.64.101:8080 weight=1 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 80;
server_name {{ web_domain }} {{ vip_address }};
# 访问日志
access_log /var/log/nginx/lb_access.log main;
error_log /var/log/nginx/lb_error.log;
# Web流量转发
location / {
proxy_pass http://backend_web;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
# 超时设置
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# API流量转发
location /api/ {
proxy_pass http://backend_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
# 重写请求路径(可选)
# rewrite ^/api/(.*)$ /$1 break;
}
# 健康检查端点
location /health {
access_log off;
return 200 "LB-{{ ansible_hostname }}-OK\n";
add_header Content-Type text/plain;
}
# Nginx状态页(仅内网访问)
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.64.0/24;
deny all;
}
}
8.3 Keepalived配置模板
创建/ansible/playbooks/roles/keepalived/templates/keepalived.conf.j2:
bash
! Configuration File for keepalived
global_defs {
router_id {{ ansible_hostname }}
script_user root
enable_script_security
}
vrrp_script check_nginx {
script "/usr/bin/killall -0 nginx"
interval 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state {{ state }}
interface {{ vip_interface }}
virtual_router_id {{ vrid }}
priority {{ priority }}
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
{{ vip_address }}/24 dev {{ vip_interface }}
}
track_script {
check_nginx
}
notify_master "/usr/bin/echo '{{ ansible_hostname }} became MASTER' | /usr/bin/logger -t keepalived"
notify_backup "/usr/bin/echo '{{ ansible_hostname }} became BACKUP' | /usr/bin/logger -t keepalived"
notify_fault "/usr/bin/echo '{{ ansible_hostname }} became FAULT' | /usr/bin/logger -t keepalived"
}
8.4 Handlers
创建/ansible/playbooks/roles/keepalived/handlers/main.yml:
bash
---
- name: reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
- name: restart keepalived
ansible.builtin.service:
name: keepalived
state: restarted
九、DNS域名解析角色
在DNS服务器(192.168.64.108)上部署BIND9,为内网提供域名解析服务。OpenEuler使用DNF包管理器,直接安装BIND即可。
9.1 DNS安装配置任务
创建/ansible/playbooks/roles/dns/tasks/main.yml:
bash
---
- name: 安装BIND9 DNS服务
ansible.builtin.dnf:
name: bind
state: present
- name: 创建正向解析区域文件目录
ansible.builtin.file:
path: /var/named/zones
state: directory
owner: named
group: named
mode: '0750'
- name: 配置named主配置文件
ansible.builtin.template:
src: named.conf.j2
dest: /etc/named.conf
owner: root
group: named
mode: '0640'
notify: restart named
- name: 配置正向解析区域文件
ansible.builtin.template:
src: zone.db.j2
dest: "/var/named/zones/{{ dns_zone }}.db"
owner: named
group: named
mode: '0640'
notify: restart named
- name: 配置反向解析区域文件
ansible.builtin.template:
src: reverse.db.j2
dest: "/var/named/zones/{{ dns_network_reverse }}.db"
owner: named
group: named
mode: '0640'
notify: restart named
- name: 配置防火墙规则(允许DNS查询)
ansible.builtin.firewalld:
service: dns
permanent: yes
state: enabled
immediate: yes
ignore_errors: yes
- name: 启动named服务并设置开机自启
ansible.builtin.service:
name: named
state: started
enabled: yes
9.2 named主配置模板
创建/ansible/playbooks/roles/dns/templates/named.conf.j2:
bash
options {
listen-on port 53 { any; };
listen-on-v6 port 53 { ::1; };
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; };
recursion yes;
forwarders {
{% for fwd in dns_forwarders %}
{{ fwd }};
{% endfor %}
};
dnssec-validation no;
managed-keys-directory "/var/named/dynamic";
pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
};
logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};
zone "." IN {
type hint;
file "named.ca";
};
# 正向解析区域
zone "{{ dns_zone }}" IN {
type master;
file "zones/{{ dns_zone }}.db";
allow-update { none; };
};
# 反向解析区域
zone "{{ dns_network_reverse }}.in-addr.arpa" IN {
type master;
file "zones/{{ dns_network_reverse }}.db";
allow-update { none; };
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
9.3 正向解析区域文件模板
创建/ansible/playbooks/roles/dns/templates/zone.db.j2:
bash
$TTL 86400
@ IN SOA dns01.{{ dns_zone }}. admin.{{ dns_zone }}. (
{{ ansible_date_time.epoch }} ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
; 名称服务器
@ IN NS dns01.{{ dns_zone }}.
dns01 IN A {{ dns_server }}
; Web服务器
web01 IN A 192.168.64.100
web02 IN A 192.168.64.101
www IN CNAME web01
www2 IN CNAME web02
; 负载均衡器
lb01 IN A 192.168.64.200
lb02 IN A 192.168.64.201
lb IN CNAME lb01
; 虚拟IP
vip IN A {{ vip_address }}
portal IN CNAME vip
; DHCP服务器
dhcp01 IN A {{ dhcp_server }}
dhcp IN CNAME dhcp01
; 其他服务
api IN A {{ vip_address }}
9.4 反向解析区域文件模板
创建/ansible/playbooks/roles/dns/templates/reverse.db.j2:
bash
$TTL 86400
@ IN SOA dns01.{{ dns_zone }}. admin.{{ dns_zone }}. (
{{ ansible_date_time.epoch }} ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
; 名称服务器
@ IN NS dns01.{{ dns_zone }}.
; PTR记录
100 IN PTR web01.{{ dns_zone }}.
101 IN PTR web02.{{ dns_zone }}.
108 IN PTR dns01.{{ dns_zone }}.
109 IN PTR dhcp01.{{ dns_zone }}.
200 IN PTR lb01.{{ dns_zone }}.
201 IN PTR lb02.{{ dns_zone }}.
250 IN PTR vip.{{ dns_zone }}.
9.5 Handlers
创建/ansible/playbooks/roles/dns/handlers/main.yml:
bash
---
- name: restart named
ansible.builtin.service:
name: named
state: restarted
十、DHCP分配IP角色
在DHCP服务器(192.168.64.109)上部署DHCP服务,为内网客户端动态分配IP地址。DHCP服务器自身必须使用静态IP,否则服务会失效。
10.1 DHCP安装配置任务
创建/ansible/playbooks/roles/dhcp/tasks/main.yml:
bash
---
- name: 安装DHCP服务
ansible.builtin.dnf:
name: dhcp-server
state: present
- name: 从模板复制DHCP配置文件
ansible.builtin.template:
src: dhcpd.conf.j2
dest: /etc/dhcp/dhcpd.conf
owner: root
group: root
mode: '0644'
notify: restart dhcpd
- name: 配置DHCP监听网卡
ansible.builtin.lineinfile:
path: /etc/sysconfig/dhcpd
line: 'DHCPDARGS="{{ ansible_default_ipv4.interface }}"'
regexp: '^DHCPDARGS='
state: present
notify: restart dhcpd
- name: 配置防火墙规则(允许DHCP服务)
ansible.builtin.firewalld:
service: dhcp
permanent: yes
state: enabled
immediate: yes
ignore_errors: yes
- name: 启动DHCP服务并设置开机自启
ansible.builtin.service:
name: dhcpd
state: started
enabled: yes
10.2 DHCP配置模板
创建/ansible/playbooks/roles/dhcp/templates/dhcpd.conf.j2:
bash
# 全局配置
option domain-name "{{ domain_name }}";
option domain-name-servers {{ dns_server }};
default-lease-time {{ dhcp_lease_time }};
max-lease-time {{ dhcp_max_lease_time }};
authoritative;
# 禁用DNS动态更新
ddns-update-style none;
# 日志配置
log-facility local7;
# 子网配置
subnet {{ dhcp_subnet }} netmask {{ dhcp_netmask }} {
range {{ dhcp_range_start }} {{ dhcp_range_end }};
option routers {{ gateway }};
option subnet-mask {{ dhcp_netmask }};
option broadcast-address 192.168.64.255;
option domain-name-servers {{ dns_server }};
option domain-name "{{ domain_name }}";
}
# 为特定MAC地址分配固定IP
# 例如:为测试客户端分配固定IP
host test-client {
hardware ethernet 00:0C:29:XX:XX:XX; # 替换为实际MAC地址
fixed-address 192.168.64.210;
option host-name "test-client";
}
10.3 Handlers
创建/ansible/playbooks/roles/dhcp/handlers/main.yml:
bash
---
- name: restart dhcpd
ansible.builtin.service:
name: dhcpd
state: restarted
十一、主入口Playbook(site.yml)
创建/ansible/playbooks/site.yml,作为整个自动化部署的入口:
bash
---
- name: 1. 初始化所有服务器(通用配置)
hosts: all
gather_facts: yes
roles:
- common
- name: 2. 部署Nginx Web服务器
hosts: webservers
gather_facts: yes
roles:
- nginx
- name: 3. 部署Keepalived + Nginx反向代理(高可用负载均衡)
hosts: loadbalancers
gather_facts: yes
roles:
- keepalived
- name: 4. 部署DNS域名解析服务器
hosts: dnsserver
gather_facts: yes
roles:
- dns
- name: 5. 部署DHCP动态IP分配服务器
hosts: dhcpserver
gather_facts: yes
roles:
- dhcp
- name: 6. 部署后验证
hosts: localhost
gather_facts: no
tasks:
- name: 显示部署完成信息
ansible.builtin.debug:
msg:
- "========================================"
- "🎉 恭喜!全栈自动化部署已完成!"
- "========================================"
- "Nginx Web服务器: 192.168.64.100, 192.168.64.101"
- "Keepalived高可用集群 (VIP: 192.168.64.250): 192.168.64.200(MASTER), 192.168.64.201(BACKUP)"
- "DNS服务器: 192.168.64.108"
- "DHCP服务器: 192.168.64.109"
- "========================================"
- "验证命令:"
- " curl http://192.168.64.250"
- " nslookup web01.example.local 192.168.64.108"
- " ip addr show | grep 192.168.64.250"
- " systemctl status dhcpd"
- "========================================"
十二、执行Playbook
12.1 语法检查
bash
cd /ansible/playbooks
ansible-playbook site.yml --syntax-check
12.2 试运行(Dry Run)
bash
ansible-playbook site.yml --check
12.3 正式执行
bash
ansible-playbook site.yml
12.4 指定执行部分角色
bash
# 仅部署Web服务器
ansible-playbook site.yml --tags nginx
# 仅部署负载均衡器
ansible-playbook site.yml --tags keepalived
十三、部署验证
13.1 验证Nginx Web服务
bash
# 访问单台Web服务器
curl http://192.168.64.100
curl http://192.168.64.101
# 查看Nginx服务状态
ansible webservers -m shell -a "systemctl status nginx | head -3"
13.2 验证Keepalived高可用集群
bash
# 查看VIP所在节点
ansible loadbalancers -m shell -a "ip addr show | grep {{ vip_address }}"
# 模拟故障切换测试
# 在MASTER节点上停止Keepalived服务
ansible 192.168.64.200 -m service -a "name=keepalived state=stopped"
# 观察VIP是否漂移到BACKUP节点
ansible 192.168.64.201 -m shell -a "ip addr show | grep 192.168.64.250"
# 恢复MASTER节点
ansible 192.168.64.200 -m service -a "name=keepalived state=started"
13.3 验证反向代理
bash
# 通过VIP访问(应该轮询分发到两台Web服务器)
for i in {1..10}; do curl -s http://192.168.64.250 | grep "主机名"; done
# 查看负载均衡器状态
curl http://192.168.64.250/nginx_status
13.4 验证DNS解析
bash
# 测试正向解析
nslookup web01.example.local 192.168.64.108
nslookup www.example.local 192.168.64.108
nslookup vip.example.local 192.168.64.108
# 测试反向解析
nslookup 192.168.64.100 192.168.64.108
13.5 验证DHCP服务
bash
# 查看DHCP服务状态
ansible dhcpserver -m shell -a "systemctl status dhcpd"
# 查看DHCP租约文件
ansible dhcpserver -m shell -a "cat /var/lib/dhcpd/dhcpd.leases"
十四、故障排查与优化建议
14.1 常见问题排查
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| SSH连接失败 | 密钥未正确分发 | 重新执行ssh_key_distribution.yml |
| Nginx启动失败 | 端口被占用 | `netstat -tlnp |
| Keepalived VIP不漂移 | 防火墙阻止VRRP协议 | 确保firewalld已关闭或放行VRRP(协议号112) |
| DNS解析失败 | named服务未启动 | systemctl restart named |
| DHCP分配失败 | 网卡配置错误 | 检查/etc/sysconfig/dhcpd中的网卡名称 |
14.2 优化建议
-
使用Ansible Vault加密敏感信息:将密码等敏感变量放入加密文件中
-
开启Pipeline :在
ansible.cfg中设置pipelining = True可提升执行效率 -
配置Fact缓存 :设置
fact_caching = jsonfile加速重复执行 -
使用Roles结构:将不同服务拆分为独立Role,便于维护和复用
十五、总结
本文通过一个完整的实战案例,演示了如何使用Ansible Playbook在OpenEuler系统上自动化部署一套企业级服务集群,涵盖:
-
SSH密钥分发 :使用
authorized_key模块实现免密登录 -
Nginx Web服务:通过模板部署Web服务器和自定义页面
-
Keepalived高可用集群:基于VRRP协议实现VIP漂移,配合Nginx实现反向代理和API转发
-
DNS域名解析:部署BIND9服务,实现内网正向/反向域名解析
-
DHCP动态IP分配:为内网客户端自动分配IP地址