生产级 Ansible 部署全流程-nginx示例

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.ymlconfigs/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
相关推荐
运维李哥不背锅14 小时前
Ansible 的变量与模板:实现更灵活的自动化配置
java·自动化·ansible
运维李哥不背锅14 小时前
Ansible 的条件语句与循环详解
数据库·ansible
小安运维日记4 天前
RHCA - DO374 | Day03:通过自动化控制器运行剧本
linux·运维·数据库·自动化·ansible·1024程序员节
遇见火星4 天前
Aiops探索:基于Ansible的Dify版本运维智能体落地思路
运维·服务器·ansible
星哥说事5 天前
网络自动化:Ansible/Netmiko 网络设备批量配置与管理
网络·自动化·ansible
zz-zjx5 天前
全平台Ansible一键安装脚本:Ubuntu/Debian/RHEL全支持
ansible
不惑_6 天前
如何使用 Ansible 安装 Docker
docker·github·ansible
小安运维日记8 天前
RHCA - DO374 | Day01:使用红帽Ansible自动化平台开发剧本
运维·服务器·云原生·自动化·云计算·ansible
BullSmall8 天前
Ansible三大Web界面方案全解析
运维·ansible