Ansible自动化运维入门实战:从安装配置到批量管理服务器

举报
yd_248750836 发表于 2026/11/09 08:25:52 2026/11/09
【摘要】 Ansible 自动化运维入门实战:从安装配置到批量管理服务器 一、Ansible 是什么Ansible 是一款无代理(Agentless)的自动化运维工具。所谓无代理,指的是被管理的节点上不需要安装任何客户端程序,Ansible 通过 SSH 连接目标机器并执行命令、推送文件、运行模块。它和 Puppet、Chef 这类需要 Agent 的工具相比,部署成本低得多,适合中小规模集群和云上...

Ansible 自动化运维入门实战:从安装配置到批量管理服务器

一、Ansible 是什么

Ansible 是一款无代理(Agentless)的自动化运维工具。所谓无代理,指的是被管理的节点上不需要安装任何客户端程序,Ansible 通过 SSH 连接目标机器并执行命令、推送文件、运行模块。

它和 Puppet、Chef 这类需要 Agent 的工具相比,部署成本低得多,适合中小规模集群和云上弹性伸缩场景。

Ansible 的核心概念只有四个:

概念 说明 类比
Inventory 主机清单,定义要管哪些机器 通讯录
Playbook YAML 写的剧本,描述要做什么 剧本
Task 剧本里的一个步骤 动作
Module 执行具体工作的插件 工具箱

二、安装 Ansible

2.1 Ubuntu / Debian

sudo apt update
sudo apt install -y ansible
ansible --version

2.2 CentOS / RHEL

sudo yum install -y epel-release
sudo yum install -y ansible

2.3 pip 安装(推荐版本更可控)

python3 -m pip install --user ansible==2.16.14
export PATH="$HOME/.local/bin:$PATH"
ansible --version

2.4 Windows 宿主机管理 Linux

pip install pywinrm
ansible all -m winrm_ping -e ansible_connection=winrm

三、主机清单(Inventory)

3.1 静态清单

在 inventory.ini 中定义主机组:

[web]
web01.example.com
web02.example.com

[db]
db01.example.com ansible_user=root

[all:children]
web
db

[prod:vars]
ansible_user=root
ansible_port=22
ansible_ssh_private_key_file=~/.ssh/id_rsa

3.2 分组变量与组变量

# group_vars/all.yml
ansible_python_interpreter: /usr/bin/python3
timezone: Asia/Shanghai

# group_vars/web.yml
http_port: 80
nginx_worker_processes: 4

3.3 动态清单(云上必备)

在华为云上可以用动态清单自动拉取 ECS 列表,避免每次手动维护:

#!/usr/bin/env python
import json
import subprocess

def main():
    cmd = [
        'hcloud', 'ecs', 'list', '-o', 'json',
        '-f', 'table', '--columns', 'name,ip,status'
    ]
    out = subprocess.check_output(cmd).decode()
    print(json.dumps({"_meta": {"hostvars": {}}}))
    # 实际生产中把解析结果写入 hostvars

if __name__ == '__main__':
    main()

四、第一个 Playbook

4.1 目录结构

ansible-project/
├── inventory.ini
├── group_vars/
│   └── all.yml
├── playbooks/
│   └── site.yml
└── roles/
    └── nginx/
        ├── tasks/main.yml
        ├── handlers/main.yml
        └── templates/nginx.conf.j2

4.2 site.yml

- name: 配置 web 服务器
  hosts: web
  become: yes
  vars:
    package_name: nginx
  tasks:
    - name: 安装 nginx
      ansible.builtin.package:
        name: "{{ package_name }}"
        state: present
      notify: restart nginx

    - name: 确保服务开机自启
      ansible.builtin.service:
        name: "{{ package_name }}"
        state: started
        enabled: yes

    - name: 写入站点首页
      ansible.builtin.copy:
        content: "Hello from Ansible at {{ ansible_date_time.iso8601 }}\n"
        dest: /usr/share/nginx/html/index.html
        mode: "0644"
      notify: restart nginx

  handlers:
    - name: restart nginx
      ansible.builtin.service:
        name: "{{ package_name }}"
        state: restarted

4.3 执行 playbook

ansible-playbook -i inventory.ini playbooks/site.yml

常用参数:

# 检查语法,不实际执行
ansible-playbook --syntax-check playbooks/site.yml

# 详细输出
ansible-playbook -v playbooks/site.yml

# 只跑部分主机
ansible-playbook playbooks/site.yml --limit web01

# 差异对比(改之前先看会变什么)
ansible-playbook playbooks/site.yml --check --diff

五、常用模块速查

场景 模块 关键参数
执行命令 ansible.builtin.command / shell chdir, creates
安装软件 ansible.builtin.package name, state
管理服务 ansible.builtin.service state, enabled
写文件 ansible.builtin.copy / template dest, content, src
模板渲染 ansible.builtin.template src, dest, backup
文件属性 ansible.builtin.file path, state, mode
用户管理 ansible.builtin.user name, groups, shell
拉取文件 ansible.builtin.fetch src, dest, flat

5.1 copy 与 template 的区别

  • copy:内容是静态文本,适合配置文件不随环境变化时
  • template:使用 Jinja2 渲染,适合多环境共用一套模板
- name: 渲染 nginx 配置
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    backup: yes
  notify: restart nginx

对应的 nginx.conf.j2:

worker_processes {{ nginx_worker_processes }};
events {
    worker_connections 1024;
}
http {
    server {
        listen {{ http_port }};
        server_name _;
        root /usr/share/nginx/html;
    }
}

5.2 让命令幂等

command 模块默认不幂等,重复执行就会报错。加 creates 条件:

- name: 解压安装包
  ansible.builtin.command: tar -xzf /tmp/app.tar.gz -C /opt/
  args:
    creates: /opt/app

或者改用 unarchive 模块,它本身就是幂等的。

六、变量与优先级

Ansible 变量优先级(从高到低,数字越小越优先):

  1. 命令行 -e key=value
  2. host_vars/
  3. group_vars/
  4. Playbook 内 vars:
  5. set_fact 产生的事实变量
  6. 采集到的 facts(ansible_* 开头)

6.1 常用内置变量

ansible_default_ipv4.address: 192.168.1.10
ansible_distribution: Ubuntu
ansible_os_family: Debian
ansible_processor_vcpus: 4
ansible_memtotal_mb: 8192
ansible_date_time.iso8601: "2026-11-09T08:30:00.000000+08:00"

6.2 set_fact 跨任务传值

- name: 探测服务端口
  ansible.builtin.shell: ss -tlnp | grep {{ port }} || true
  register: port_probe
  changed_when: false

- name: 记录结果
  ansible.builtin.set_fact:
    service_running: "{{ port_probe.rc == 0 }}"

set_fact 产生的变量在同一 play 内可被后续任务引用,优先级高于 vars。

七、角色(Role)组织结构

Role 把一组可复用的任务、变量、模板、文件打包在一起:

roles/
└── deploy-app/
    ├── defaults/main.yml    # 默认变量(优先级最低,但最该写默认值)
    ├── vars/main.yml        # 强制变量
    ├── tasks/main.yml       # 任务列表
    ├── handlers/main.yml    # 处理器
    ├── templates/           # Jinja2 模板
    ├── files/               # 静态文件
    └── meta/main.yml        # 依赖声明

7.1 defaults/main.yml

app_name: demo
app_port: 8080
app_dir: /opt/{{ app_name }}

7.2 tasks/main.yml

- name: 创建应用目录
  ansible.builtin.file:
    path: "{{ app_dir }}"
    state: directory
    mode: "0755"

- name: 复制应用包
  ansible.builtin.copy:
    src: "{{ app_name }}.tar.gz"
    dest: "{{ app_dir }}/"
    mode: "0644"
  notify: restart app

- name: 编写启动脚本
  ansible.builtin.template:
    src: start.sh.j2
    dest: "{{ app_dir }}/start.sh"
    mode: "0755"
  notify: restart app

7.3 使用角色

- name: 部署应用
  hosts: all
  become: yes
  roles:
    - role: deploy-app
      app_port: 9090
      tags: [deploy]

八、标签与跳过

- name: 配置数据库
  hosts: db
  tasks:
    - name: 初始化数据
      ansible.builtin.command: /opt/db/init.sh
      tags: [init, db]

执行时只跑指定标签:

ansible-playbook site.yml --tags init
ansible-playbook site.yml --skip-tags db

九、错误处理

9.1 忽略错误

- name: 探测服务(失败不中断)
  ansible.builtin.command: systemctl status nginx
  failed_when: false
  changed_when: false

9.2 block 与 rescue

- name: 带兜底的部署流程
  hosts: web
  block:
    - name: 执行部署
      ansible.builtin.script: /opt/deploy.sh
  rescue:
    - name: 回滚
      ansible.builtin.command: /opt/rollback.sh
  always:
    - name: 清理临时文件
      ansible.builtin.file:
        path: /tmp/deploy.lock
        state: absent

9.3 any_errors_fatal

- name: 关键节点
  hosts: all
  any_errors_fatal: true
  tasks:
    - name: 不可失败的操作
      ansible.builtin.command: /opt/check.sh

十、最佳实践

  1. 用 --check --diff 预演:正式执行前先看差异,确认没写错路径
  2. 所有任务保持幂等:用 state: present 而不是无脑执行命令
  3. 敏感数据用 Vault:ansible-vault encrypt group_vars/all/vault.yml
  4. 统一用 become: yes 提权,不要在命令里拼 sudo
  5. 日志输出到文件:ANSIBLE_LOG_PATH=/var/log/ansible.log ansible-playbook site.yml
  6. 版本管理:playbook 和 inventory 一起进 Git,改动走 code review
  7. 超时保护:长任务加 async + poll: 0
- name: 耗时的编译任务
  ansible.builtin.command: make -j4
  async: 3600
  poll: 0
  register: compile_job

十一、常用命令速查

# 查看所有主机
ansible all -i inventory.ini --list-hosts

# Ping 测试连通性
ansible all -m ping

# 采集 facts(可缓存加速)
ansible all -m setup
ansible all -m setup --facts-cache

# 执行临时命令
ansible web -m command -a "uptime"

# 同步文件到远程
ansible web -m copy -a "src=./nginx.conf dest=/tmp/nginx.conf"

# 列出可用模块
ansible-doc -l

# 查看模块文档
ansible-doc ansible.builtin.template

十二、小结

Ansible 的学习曲线主要在三个地方:

  1. YAML 写法:注意缩进统一用空格,不要用 Tab
  2. 变量优先级:搞清楚了才知道该改哪一层
  3. 幂等性:让 playbook 可以反复执行而不产生副作用

一旦这三个点吃透,Ansible 就能替代掉绝大部分重复的批量运维操作。建议的上手路径是:先在 localhost 上用 connection: local 练手,写通一个安装 Nginx 的 playbook,再扩展到多机,最后才引入 Role 拆分。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。