1. 准备机器(示例)
| 主机 | IP | 角色 |
|---|---|---|
| control-node | 192.168.1.100 | Ansible 控制机(你的笔记本或跳板机) |
| web-node | 192.168.1.101 | 被管理节点(部署 Nginx) |
所有机器为 RHEL7/8/9/10或 Ubuntu 20.04+,
2. 在 control-node 上安装 Ansible
2.1安装ansible
全平台Ansible一键安装脚本:Ubuntu/Debian/RHEL全支持-CSDN博客
2.2 在目标机上创建部署用户(deploy)
此步骤需在 每台目标机 上执行(示例:192.168.1.101)
# 登录目标机
ssh root@192.168.1.101
# 创建 deploy 用户(必须使用 /bin/bash,Ansible 需要 shell)
useradd -m -s /bin/bash deploy
# 设置 deploy 用户密码(临时,用于 ssh-copy-id)
echo "deploy:MySecurePass123" | chpasswd
# 赋予 sudo 权限(无需密码)
echo "deploy ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/deploy
chmod 440 /etc/sudoers.d/deploy
# (可选但推荐)禁用 root 远程登录 + 禁用密码认证
sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
# 退出目标机
exit
2.3跨主机免密码认证
# 切换到普通用户(推荐不要用 root 运行 Ansible)
# 如果控制机尚未创建 deploy 用户,则先创建
useradd -m -s /bin/bash deploy
# 设置本地 deploy 用户密码(仅用于 su 切换,不影响远程)
passwd deploy
# 切换到 deploy 用户(后续所有操作在此用户下进行)
su - deploy
# 生成 SSH 密钥对(无密码,便于自动化)
# - `-t rsa -b 4096`:使用高强度 RSA 密钥
# - `-N ""`:私钥不设密码
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
# 将公钥复制到目标机(会提示输入第 2 步设置的临时密码)
ssh-copy-id deploy@192.168.1.101
# 验证免密登录是否成功(应无需密码直接返回结果)
ssh deploy@192.168.1.101 "whoami && uptime"
# (可选)删除目标机 deploy 用户的密码,仅保留密钥认证
# `passwd -d` 删除密码,用户无法用密码登录
ssh deploy@192.168.1.101 "sudo passwd -d deploy"
此后 deploy 用户只能通过密钥登录,且无密码。
3:创建完整的 Ansible 项目目录结构
# 确保当前在 deploy 用户家目录下
cd ~
# 使用 brace expansion 一次性创建标准 Ansible 项目结构
# 符合官方推荐布局,便于维护和协作
mkdir -p ansible-proj/{ \
configs/group_vars, \
configs/env, \
playbooks, \
roles/prepare/tasks, \
roles/prepare/handlers, \
roles/nginx/tasks, \
roles/nginx/templates, \
roles/nginx/handlers, \
files, \
logs \
}
# 进入项目目录
cd ansible-proj
目录说明:
configs/:存放 inventory 和变量playbooks/:顶层编排文件roles/:模块化任务(符合 Ansible 最佳实践)files/:用于存放离线安装包(如 RPM)logs/:Ansible 执行日志
4:创建所有配置文件
4.1 ansible.cfg ------ Ansible 全局配置
cat > ansible.cfg <<'EOF'
[defaults]
# 指定 inventory 文件路径
inventory = configs/hosts.ini
# 默认远程用户(避免在 playbook 中硬编码)
remote_user = deploy
# 关闭 SSH 主机密钥检查(自动化场景常用,生产环境可开启)
host_key_checking = False
# 指定 roles 搜索路径
roles_path = roles
# 使用 YAML 格式输出,更易读
stdout_callback = yaml
# 启用任务耗时统计(便于性能分析)
callback_whitelist = profile_tasks
# 记录执行日志(便于审计和排错)
log_path = ./logs/ansible.log
[privilege_escalation]
# 默认启用 sudo 提权
become = true
# 使用 sudo 方式提权
become_method = sudo
# 不提示输入 sudo 密码(因已配置 NOPASSWD)
become_ask_pass = false
EOF
4.2 configs/hosts.ini ------ 主机清单
cat > configs/hosts.ini <<'EOF'
# 定义 web 主机组(可扩展多台)
[web]
web-01 ansible_host=192.168.1.101
# 全局变量(适用于所有主机)
[all:vars]
# 显式指定 Python 解释器路径(避免某些系统默认为 python2)
ansible_python_interpreter=/usr/bin/python3
EOF
4.3 configs/group_vars/all.yml ------ 全局默认变量
mkdir -p configs/group_vars
cat > configs/group_vars/all.yml <<'EOF'
# Nginx 默认监听端口(开发/测试用)
nginx_port: 8080
# Nginx worker 连接数
nginx_worker_connections: 1024
EOF
4.4 configs/env/prod.yml ------ 生产环境覆盖变量
mkdir -p configs/env
cat > configs/env/prod.yml <<'EOF'
# 生产环境使用标准 80 端口
nginx_port: 80
# 提高连接数以应对高并发
nginx_worker_connections: 2048
EOF
通过
--extra-vars加载此文件,可覆盖默认值,实现多环境部署。
4.5 roles/prepare/tasks/main.yml ------ 系统初始化任务
cat > roles/prepare/tasks/main.yml <<'EOF'
---
- name: 安装常用工具(便于调试和运维)
package:
name:
- curl # HTTP 测试
- wget # 文件下载
- vim # 编辑器
- net-tools # ifconfig, netstat 等
- rsync # 文件同步
state: present
tags: prepare
- name: 停止并禁用 firewalld(CentOS 系统)
systemd:
name: firewalld
state: stopped
enabled: no
# 仅在 RedHat 系列系统执行
when: ansible_os_family == "RedHat"
# 忽略错误(如系统未安装 firewalld)
ignore_errors: yes
EOF
4.6 roles/nginx/tasks/main.yml ------ Nginx 安装与配置
cat > roles/nginx/tasks/main.yml <<'EOF'
---
- name: 安装 Nginx(Ubuntu/Debian)
apt:
name: nginx
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 安装 Nginx(CentOS/Rocky)
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
- name: 渲染 Nginx 配置文件(使用 Jinja2 模板)
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
# 配置变更后触发 handler 重启服务
notify: restart nginx
- name: 启动并启用 Nginx 服务(开机自启)
systemd:
name: nginx
state: started
enabled: yes
EOF
4.7 roles/nginx/templates/nginx.conf.j2 ------ Nginx 模板
cat > roles/nginx/templates/nginx.conf.j2 <<'EOF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
}
http {
server {
# 动态监听端口(来自变量)
listen {{ nginx_port }};
location / {
root /usr/share/nginx/html;
index index.html;
}
}
}
EOF
使用 Jinja2 模板实现配置参数化,避免硬编码。
4.8 roles/nginx/handlers/main.yml ------ 服务重启逻辑
cat > roles/nginx/handlers/main.yml <<'EOF'
---
- name: restart nginx
systemd:
name: nginx
state: restarted
EOF
Handler 仅在被
notify触发时执行,避免不必要的服务重启。
4.9 Playbook 文件 ------ 编排流程
# 系统初始化 playbook
cat > playbooks/01-prepare.yml <<'EOF'
---
- name: 系统初始化
hosts: all
roles:
- prepare
EOF
# Web 服务部署 playbook
cat > playbooks/02-web.yml <<'EOF'
---
- name: 部署 Nginx Web 服务
hosts: web
# 加载全局变量(也可通过 group_vars 自动加载)
vars_files:
- ../configs/group_vars/all.yml
roles:
- nginx
EOF
# 总入口 playbook(组合执行)
cat > playbooks/90-deploy.yml <<'EOF'
---
- import_playbook: 01-prepare.yml
- import_playbook: 02-web.yml
EOF
使用
import_playbook实现模块化编排,便于复用和测试。
5:执行部署
# 创建日志目录(ansible.cfg 中已指定路径)
mkdir -p logs
# 测试 Ansible 与目标机连通性
ansible all -m ping
# 执行完整部署流程,并加载生产环境变量
ansible-playbook playbooks/90-deploy.yml --extra-vars "@configs/env/prod.yml"
输出为 YAML 格式,清晰显示每个任务状态(ok/changed/failed)。
6:验证结果
# 检查 Nginx 服务状态
ansible web -m systemd -a "name=nginx"
# 在目标机本地测试 Nginx 响应
ssh deploy@192.168.1.101 "curl -s http://localhost:80 | head -n 5"
# 从控制机访问 Web 服务(验证网络连通性)
curl http://192.168.1.101:80
应返回 Nginx 默认欢迎页 HTML 片段。
7:安全收尾(可选)
# 锁定 deploy 用户密码(彻底禁用密码登录)
# 方法 1:锁定密码(仍可通过密钥登录)
ssh deploy@192.168.1.101 "sudo passwd -l deploy"
# 方法 2:设置无效密码(更彻底)
ssh deploy@192.168.1.101 "sudo usermod -p '*' deploy"
此后 deploy 用户 只能通过 SSH 密钥登录,极大提升安全性。
8 最终目录结构验证
# 安装 tree(如未安装)
sudo yum install -y tree || sudo apt install -y tree
# 查看项目结构
tree ~/ansible-proj
预期输出:
ansible-proj/
├── ansible.cfg
├── configs/
│ ├── hosts.ini
│ ├── group_vars/
│ │ └── all.yml
│ └── env/
│ └── prod.yml
├── playbooks/
│ ├── 01-prepare.yml
│ ├── 02-web.yml
│ └── 90-deploy.yml
├── roles/
│ ├── prepare/
│ │ └── tasks/main.yml
│ └── nginx/
│ ├── tasks/main.yml
│ ├── templates/nginx.conf.j2
│ └── handlers/main.yml
├── files/
├── logs/
└── (no other files)
9、生产增强建议(可选)
| 能力 | 实现方式 |
|---|---|
| 离线部署 | 将 Nginx RPM/deb 包放入 files/,用 copy + yum install ./xxx.rpm |
| 多环境 | 创建 configs/prod.yml、configs/staging.yml,通过 -e env=prod 加载 |
| Vault 加密 | 敏感变量用 ansible-vault encrypt_string 加密 |
| CI/CD 集成 | 在 Jenkins/GitLab CI 中执行 ansible-playbook |
| 日志记录 | 添加 --log-path ./deploy.log |
10、项目打包(便于分发)
tar -czvf ansible-web-deploy.tar.gz -C ~/ ansible-web-deploy
交付给运维团队后,只需:
tar -xzvf ansible-proj.tar.gz
cd ansible-proj
ansible-playbook playbooks/90-deploy.yml