生产级 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
相关推荐
有毒的教程2 小时前
Ansible批量操作自动化完整教程:批量部署服务、配置同步、软件更新实战
运维·自动化·ansible
Hy行者勇哥5 天前
用Cursor智能编写Ansible/Terraform脚本,打通CI/CD链路
ci/cd·ansible·terraform
芷栀夏7 天前
飞牛NAS怎么部署Immich?家庭照片自动备份与远程访问教程
服务器·nginx·ansible
悠然南风18 天前
Ansible常见模块总结及LDAP Role 编写与调试
ansible
祺风挽楠1 个月前
ansible编辑
网络·ansible
芳心粽伙饭1 个月前
Ansible课后作业
ansible
烁3471 个月前
Ansible初识
ansible
烁3471 个月前
Ansible安装部署调试
ansible
烁3471 个月前
Ansible命令
ansible
小义_1 个月前
【Ansible】(三)基础配置与连接设置
云原生·ansible