Ansible自动化配置,从入门到实战

Ansible作为无代理、易上手的自动化运维工具,能通过简单的YAML配置实现服务器批量管理、软件部署、配置同步、任务执行等操作,大幅降低人工运维成本。

一、Ansible核心认知:为什么选择Ansible?

1.1 Ansible核心优势

  • 无代理架构:目标主机无需安装Agent,仅需SSH和Python(大部分Linux系统默认自带),部署零侵入;
  • 声明式配置:通过YAML编写Playbook,只需定义"最终状态",无需关注执行过程;
  • 模块化设计:内置上千个模块(如yum、service、file),覆盖运维90%以上场景,无需重复造轮子;
  • 幂等性:多次执行同一配置,结果一致(不会重复安装已存在的软件、不会重复启动已运行的服务);
  • 易扩展:支持自定义模块、插件,适配企业个性化运维需求。

1.2 适用场景

  • 批量服务器初始化(系统配置、用户创建、依赖安装);
  • 软件包批量安装/升级/卸载(Nginx、MySQL、Redis等);
  • 配置文件统一分发(跨服务器同步配置,保证一致性);
  • 服务批量启停/重启(如集群服务重启、应用发布);
  • 定时任务自动化(结合Crond实现周期性运维操作);
  • 跨机房/跨云平台服务器管理(兼容阿里云、腾讯云、物理机等)。

1.3 核心架构

复制代码
控制节点(Control Node) → SSH连接 → 目标节点(Managed Nodes)
  • 控制节点:安装Ansible的主机(仅需1台,推荐Linux系统,Windows需WSL);
  • 目标节点:需要被管理的服务器(Linux/Windows,本文以Linux为主);
  • 核心组件:Inventory(主机清单)、Module(模块)、Playbook(剧本)、Role(角色)。

二、第一步:Ansible环境搭建

2.1 控制节点安装Ansible

2.1.1 CentOS/RHEL系统
bash 复制代码
# 安装EPEL源(CentOS默认无Ansible)
yum install -y epel-release
# 安装Ansible(推荐2.10+版本)
yum install -y ansible
# 验证安装
ansible --version
2.1.2 Ubuntu/Debian系统
bash 复制代码
# 更新源
apt update
# 安装软件依赖
apt install -y software-properties-common
# 添加Ansible源
add-apt-repository --yes --update ppa:ansible/ansible
# 安装Ansible
apt install -y ansible
2.1.3 验证安装

执行以下命令,输出Ansible版本即安装成功:

bash 复制代码
ansible --version
# 预期输出示例:
# ansible [core 2.15.0]
#  config file = /etc/ansible/ansible.cfg
#  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
#  ansible python module location = /usr/lib/python3.9/site-packages/ansible
#  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
#  executable location = /usr/bin/ansible
#  python version = 3.9.16 (main, May 15 2023, 23:46:34) [GCC 8.5.0 20210514 (Red Hat 8.5.0-18)]
#  jinja version = 3.1.2
#  libyaml = True

2.2 目标节点前置配置

Ansible通过SSH管理目标节点,需保证控制节点能免密登录目标节点:

2.2.1 控制节点生成SSH密钥
bash 复制代码
# 生成RSA密钥(一路回车,无需设置密码)
ssh-keygen -t rsa -b 2048
# 查看公钥
cat ~/.ssh/id_rsa.pub
2.2.2 推送公钥到目标节点
bash 复制代码
# 方式1:手动复制(单节点)
ssh-copy-id root@192.168.1.10  # 替换为目标节点IP/用户名

# 方式2:批量推送(多节点,需提前安装sshpass)
# 安装sshpass
yum install -y sshpass
# 批量推送(示例:推送至192.168.1.10-12)
for ip in 192.168.1.10 192.168.1.11 192.168.1.12; do
  sshpass -p "目标节点root密码" ssh-copy-id -o StrictHostKeyChecking=no root@$ip
done
2.2.3 验证免密登录
bash 复制代码
ssh root@192.168.1.10  # 无需输入密码即登录成功

2.3 基础配置(可选)

修改Ansible主配置文件/etc/ansible/ansible.cfg,优化默认配置:

ini 复制代码
[defaults]
# 禁用主机密钥检查(避免首次连接提示)
host_key_checking = False
# 默认Inventory文件路径
inventory = /etc/ansible/hosts
# 超时时间(避免SSH连接超时)
timeout = 30
# 模块并行执行数
forks = 50

[privilege_escalation]
# 默认提权(目标节点执行sudo无需密码)
become = True
become_method = sudo
become_user = root
become_ask_pass = False

三、第二步:核心组件解析与基础使用

3.1 Inventory(主机清单):定义被管理节点

Inventory是Ansible的"主机列表",用于分组管理目标节点,支持静态文件和动态脚本(如对接云平台API)。

3.1.1 静态Inventory示例(/etc/ansible/hosts)
ini 复制代码
# 单主机配置
192.168.1.10 ansible_ssh_port=22 ansible_ssh_user=root

# 分组配置(推荐)
[web_servers]  # 组名:Web服务器
192.168.1.10
192.168.1.11

[db_servers]   # 组名:数据库服务器
192.168.1.20
192.168.1.21

# 组变量(该组所有主机共用)
[web_servers:vars]
nginx_port=80
app_path=/var/www/html

# 嵌套组(包含其他组)
[all_servers:children]
web_servers
db_servers
3.1.2 验证Inventory
bash 复制代码
# 列出所有主机
ansible all --list-hosts
# 列出指定组主机
ansible web_servers --list-hosts

3.2 Ad-Hoc命令:临时执行单条运维操作

Ad-Hoc是Ansible的"临时命令",适合快速执行简单操作(无需编写Playbook),语法:

bash 复制代码
ansible <目标主机/组> -m <模块名> -a <模块参数>
3.2.1 常用Ad-Hoc命令示例
bash 复制代码
# 1. 测试所有主机连通性(ping模块)
ansible all -m ping

# 2. 批量执行shell命令(查看目标主机内存)
ansible web_servers -m shell -a "free -h"

# 3. 批量安装Nginx(yum模块)
ansible web_servers -m yum -a "name=nginx state=present"

# 4. 批量启动Nginx服务(service模块)
ansible web_servers -m service -a "name=nginx state=started enabled=yes"

# 5. 批量分发文件(copy模块)
ansible web_servers -m copy -a "src=/root/nginx.conf dest=/etc/nginx/nginx.conf mode=0644"

# 6. 批量创建目录(file模块)
ansible web_servers -m file -a "path=/var/www/html state=directory mode=0755"

# 7. 批量重启服务(service模块)
ansible all_servers -m service -a "name=network state=restarted"

3.3 Module(模块):Ansible的"功能单元"

Ansible内置上千个模块,覆盖运维全场景,核心模块分类:

模块类型 常用模块 用途
系统模块 yum/apt、service、user 软件安装、服务管理、用户创建
文件模块 copy、file、template 文件拷贝、目录创建、模板渲染
命令模块 shell、command、script 执行命令/脚本
网络模块 uri、iptables、firewalld HTTP请求、防火墙配置
数据库模块 mysql_db、redis 数据库管理、Redis操作
3.3.2 模块帮助查询
bash 复制代码
# 查看模块列表
ansible-doc -l
# 查看指定模块详细用法(如yum模块)
ansible-doc yum

3.4 Playbook:自动化配置的核心(声明式配置)

Playbook是Ansible的"剧本",通过YAML格式定义一系列运维任务,支持变量、条件、循环、角色等高级特性,是企业级自动化配置的核心。

3.4.1 Playbook基础结构

一个Playbook包含一个或多个"Play",每个Play对应一组目标主机和任务:

yaml 复制代码
# 示例:install_nginx.yml
- name: 批量安装并配置Nginx  # Play名称(可选,便于日志查看)
  hosts: web_servers        # 目标主机/组
  remote_user: root         # 执行用户
  become: yes               # 是否提权到root(默认no)

  tasks:                    # 任务列表(按顺序执行)
    - name: 安装Nginx软件包  # 任务名称(必填,便于调试)
      yum:                  # 模块名
        name: nginx         # 模块参数
        state: present

    - name: 部署Nginx配置文件
      copy:
        src: ./nginx.conf
        dest: /etc/nginx/nginx.conf
        mode: 0644
      notify: restart nginx  # 触发Handlers(配置变更后重启)

    - name: 启动Nginx服务
      service:
        name: nginx
        state: started
        enabled: yes

  handlers:                 # 触发器(仅被notify触发时执行)
    - name: restart nginx
      service:
        name: nginx
        state: restarted
3.4.2 执行Playbook
bash 复制代码
# 基本执行
ansible-playbook install_nginx.yml

# 常用参数
ansible-playbook install_nginx.yml \
  -i inventory.ini  # 指定自定义Inventory文件(默认/etc/ansible/hosts)
  --check           # 干跑模式(验证语法,不实际执行)
  -v                # 详细输出(-vvv为最详细,用于调试)
  --limit web_servers  # 仅执行指定组
  --tags install    # 仅执行带指定标签的任务

四、第三步:Playbook核心特性实战

4.1 变量(Variables):减少重复配置

变量用于存储可复用的值,支持多种定义方式,优先级:命令行变量 > Play变量 > Inventory变量 > 事实变量。

4.1.1 定义变量的4种方式
yaml 复制代码
# 方式1:Play内部定义(vars字段)
- name: 使用Play变量
  hosts: web_servers
  vars:
    nginx_port: 80
    nginx_conf_path: /etc/nginx/nginx.conf
  tasks:
    - name: 打印变量
      debug:
        msg: "Nginx端口:{{ nginx_port }}"  # 引用变量:{{ 变量名 }}

# 方式2:外部变量文件(vars_files字段)
# 新建vars/nginx_vars.yml
# nginx_port: 8080
# nginx_conf_path: /etc/nginx/nginx.conf

- name: 使用外部变量文件
  hosts: web_servers
  vars_files:
    - ./vars/nginx_vars.yml
  tasks:
    - name: 打印变量
      debug:
        msg: "Nginx端口:{{ nginx_port }}"

# 方式3:Inventory变量(在hosts文件中定义)
# [web_servers:vars]
# nginx_port=80

# 方式4:命令行传递(-e参数)
# ansible-playbook playbook.yml -e "nginx_port=8080"
4.1.2 事实变量(Facts):自动采集目标主机信息

Ansible自动采集目标主机的系统信息(如IP、CPU、系统版本),可直接引用:

yaml 复制代码
- name: 使用事实变量
  hosts: all
  tasks:
    - name: 打印目标主机信息
      debug:
        msg: |
          主机名:{{ ansible_hostname }}
          IP地址:{{ ansible_default_ipv4.address }}
          系统版本:{{ ansible_distribution_version }}
          CPU核心数:{{ ansible_processor_vcpus }}

4.2 模板(Templates):动态生成配置文件

通过Jinja2模板引擎动态生成配置文件,支持变量、条件、循环,模板文件后缀为.j2

4.2.1 模板示例(templates/nginx.conf.j2)
nginx 复制代码
worker_processes {{ ansible_processor_vcpus }};  # 引用事实变量(CPU核心数)
listen {{ nginx_port }};  # 引用自定义变量
server_name {{ ansible_default_ipv4.address }};

{% if nginx_port == 443 %}  # 条件判断
ssl on;
ssl_certificate /etc/nginx/cert.pem;
{% endif %}
4.2.2 使用模板模块
yaml 复制代码
- name: 部署动态Nginx配置
  hosts: web_servers
  vars:
    nginx_port: 80
  tasks:
    - name: 渲染模板并部署
      template:
        src: ./templates/nginx.conf.j2  # 本地模板文件
        dest: /etc/nginx/nginx.conf     # 目标路径
        mode: 0644

4.3 条件判断(Conditionals):按需执行任务

通过when关键字实现条件执行,适合跨系统、差异化配置场景:

yaml 复制代码
- name: 跨系统安装Nginx
  hosts: all
  tasks:
    # CentOS系统用yum安装
    - name: CentOS安装Nginx
      yum:
        name: nginx
        state: present
      when: ansible_distribution == "CentOS"

    # Ubuntu系统用apt安装
    - name: Ubuntu安装Nginx
      apt:
        name: nginx
        state: present
        update_cache: yes
      when: ansible_distribution == "Ubuntu"

4.4 循环(Loops):批量执行重复任务

通过loop关键字实现循环执行,减少代码冗余:

yaml 复制代码
- name: 批量操作示例
  hosts: web_servers
  tasks:
    # 批量安装多个软件
    - name: 安装Nginx、Redis、Git
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - redis
        - git

    # 批量创建用户(循环字典)
    - name: 创建运维用户
      user:
        name: "{{ item.name }}"
        group: "{{ item.group }}"
        create_home: yes
      loop:
        - { name: "devops", group: "admin" }
        - { name: "test", group: "guest" }

4.5 角色(Roles):Playbook模块化(企业级必备)

当Playbook复杂时,通过Roles将任务、变量、模板按功能拆分,实现模块化复用,适合大型项目。

4.5.1 Roles目录结构
复制代码
web_deploy/
├── inventory.ini
├── site.yml  # 主Playbook
├── roles/
│   ├── nginx/  # Nginx角色
│   │   ├── tasks/       # 任务(main.yml为入口)
│   │   ├── vars/        # 变量
│   │   ├── templates/   # 模板
│   │   ├── handlers/    # 触发器
│   │   └── defaults/    # 默认变量(优先级最低)
│   └── redis/  # Redis角色
│       ├── tasks/
│       └── ...
4.5.2 编写Roles(以nginx角色为例)
  1. 编写任务:roles/nginx/tasks/main.yml
yaml 复制代码
- name: 安装Nginx
  yum:
    name: nginx
    state: present

- name: 部署配置文件
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: restart nginx

- name: 启动Nginx
  service:
    name: nginx
    state: started
    enabled: yes
  1. 编写触发器:roles/nginx/handlers/main.yml
yaml 复制代码
- name: restart nginx
  service:
    name: nginx
    state: restarted
  1. 主Playbook引用Roles:site.yml
yaml 复制代码
- name: 部署Web服务
  hosts: web_servers
  roles:
    - nginx  # 引用nginx角色
    - redis  # 引用redis角色
  1. 执行Roles
bash 复制代码
ansible-playbook -i inventory.ini site.yml

五、第四步:企业级实战案例------服务器初始化自动化

5.1 需求场景

批量初始化10台新服务器,完成以下操作:

  1. 系统初始化(关闭SELinux、配置时区、同步时间);
  2. 安装基础依赖(wget、curl、gcc、firewalld);
  3. 创建运维用户(devops),配置sudo权限;
  4. 关闭无用服务(postfix、bluetooth);
  5. 配置防火墙(开放22、80、443端口)。

5.2 目录结构

复制代码
server_init/
├── inventory.ini
├── site.yml
└── roles/
    └── init/
        ├── tasks/
        │   └── main.yml
        ├── vars/
        │   └── main.yml
        └── handlers/
            └── main.yml

5.3 核心文件编写

5.3.1 Inventory(inventory.ini)
ini 复制代码
[new_servers]
192.168.1.100
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104

[new_servers:vars]
ansible_ssh_user=root
ansible_ssh_port=22
5.3.2 变量文件(roles/init/vars/main.yml)
yaml 复制代码
# 基础依赖包
base_packages:
  - wget
  - curl
  - gcc
  - make
  - firewalld
  - chrony

# 运维用户配置
ops_user: devops
ops_group: admin

# 开放的防火墙端口
firewall_ports:
  - 22/tcp
  - 80/tcp
  - 443/tcp

# 要关闭的无用服务
unwanted_services:
  - postfix
  - bluetooth
5.3.3 任务文件(roles/init/tasks/main.yml)
yaml 复制代码
# 1. 安装基础依赖包
- name: 安装基础依赖包
  yum:
    name: "{{ base_packages }}"
    state: present
    update_cache: yes

# 2. 关闭SELinux
- name: 临时关闭SELinux
  command: setenforce 0
  ignore_errors: yes

- name: 永久关闭SELinux
  lineinfile:
    path: /etc/selinux/config
    regexp: '^SELINUX='
    line: 'SELINUX=disabled'

# 3. 配置系统时区
- name: 设置时区为Asia/Shanghai
  timezone:
    name: Asia/Shanghai

# 4. 同步系统时间
- name: 启动chrony服务
  service:
    name: chrony
    state: started
    enabled: yes

- name: 同步网络时间
  command: chronyc sync
  changed_when: false

# 5. 创建运维用户组和用户
- name: 创建运维用户组
  group:
    name: "{{ ops_group }}"
    state: present

- name: 创建运维用户
  user:
    name: "{{ ops_user }}"
    group: "{{ ops_group }}"
    shell: /bin/bash
    create_home: yes
    home: /home/{{ ops_user }}
    password: "$6$salt$xxxxxxxxxxxx"  # 加密后的密码(可用openssl passwd -6生成)

# 6. 配置sudo权限(无需密码)
- name: 配置devops用户sudo权限
  lineinfile:
    path: /etc/sudoers
    line: "{{ ops_user }} ALL=(ALL) NOPASSWD: ALL"
    validate: "visudo -cf %s"  # 验证sudoers语法

# 7. 关闭无用服务
- name: 关闭无用服务
  service:
    name: "{{ item }}"
    state: stopped
    enabled: no
  loop: "{{ unwanted_services }}"
  ignore_errors: yes  # 服务不存在时忽略错误

# 8. 配置防火墙
- name: 启动firewalld服务
  service:
    name: firewalld
    state: started
    enabled: yes

- name: 开放防火墙端口
  firewalld:
    port: "{{ item }}"
    zone: public
    permanent: yes
    state: enabled
  loop: "{{ firewall_ports }}"
  notify: restart firewalld
5.3.4 触发器(roles/init/handlers/main.yml)
yaml 复制代码
- name: restart firewalld
  service:
    name: firewalld
    state: restarted
5.3.5 主Playbook(site.yml)
yaml 复制代码
- name: 批量初始化新服务器
  hosts: new_servers
  remote_user: root
  roles:
    - init

- name: 验证初始化结果
  hosts: new_servers
  tasks:
    - name: 验证SELinux状态
      command: getenforce
      register: selinux_status
      changed_when: false
      failed_when: selinux_status.stdout != "Disabled"

    - name: 验证运维用户存在
      command: id {{ ops_user }}
      register: user_status
      changed_when: false

    - name: 输出初始化状态
      debug:
        msg: |
          SELinux状态:{{ selinux_status.stdout }}
          运维用户状态:{{ "存在" if user_status.rc == 0 else "不存在" }}
          防火墙端口:{{ firewall_ports }}
      vars:
        ops_user: devops
        firewall_ports: [22/tcp, 80/tcp, 443/tcp]

5.4 执行初始化

bash 复制代码
# 干跑验证
ansible-playbook -i inventory.ini site.yml --check -v

# 实际执行
ansible-playbook -i inventory.ini site.yml -v

六、Ansible自动化配置最佳实践

6.1 目录规范化

复制代码
project/
├── inventory/          # Inventory文件(按环境拆分:dev/test/prod)
│   ├── dev.ini
│   ├── test.ini
│   └── prod.ini
├── playbooks/          # Playbook文件
│   ├── server_init.yml
│   ├── deploy_nginx.yml
│   └── deploy_mysql.yml
├── roles/              # 角色目录
│   ├── init/
│   ├── nginx/
│   └── mysql/
├── vars/               # 全局变量
├── templates/          # 全局模板
└── scripts/            # 自定义脚本

6.2 安全最佳实践

  1. 敏感信息加密 :用Ansible Vault加密密码、密钥等敏感变量:

    bash 复制代码
    # 加密变量文件
    ansible-vault encrypt vars/secret_vars.yml
    # 执行Playbook时解密
    ansible-playbook playbook.yml --ask-vault-pass
  2. 最小权限原则:避免用root执行Playbook,配置普通用户sudo权限;

  3. 禁用危险模块 :生产环境限制使用shell/command模块,优先用专用模块(如yum、service)。

6.3 性能优化

  1. 提高并行数 :修改ansible.cfgforks参数(默认5,可改为50~100);
  2. 关闭事实采集 :无需主机信息时,添加gather_facts: no减少执行时间;
  3. 使用管道模式ansible.cfg中开启pipelining = True,减少SSH连接次数。

6.4 调试技巧

  1. 干跑模式--check参数验证Playbook语法和执行计划;

  2. 详细输出-v/-vvv参数查看执行细节,定位错误;

  3. 任务调试 :用debug模块打印变量,验证逻辑:

    yaml 复制代码
    - name: 调试变量
      debug:
        var: ansible_default_ipv4.address
相关推荐
RPA机器人就选八爪鱼17 小时前
RPA财务机器人选型攻略:5步搭建高性价比自动化体系
大数据·人工智能·机器人·自动化·rpa
Anakki17 小时前
企业级 Elastic Stack 集成架构:Spring Boot 3.x 与 Elasticsearch 8.x 深度实践指南
运维·jenkins·springboot·elastic search
2501_9419820517 小时前
企业微信 RPA 自动化:如何解决 UI 异步渲染导致的操作失效?
自动化·企业微信·rpa
DevOps-IT17 小时前
HTTP状态码(常见 HTTP Status Code 查询)
运维·服务器·网络·网络协议·http
释怀不想释怀17 小时前
Docker(安装软件)
运维·docker·容器
网硕互联的小客服17 小时前
服务器 CPU 温度过高需要进行的物理处理和软件处理有哪些?
运维·服务器
济61717 小时前
linux(第十三期)--filezilla使用方法(实现ubuntu和windows11文件互传)-- Ubuntu20.04
linux·运维·ubuntu
HIT_Weston17 小时前
91、【Ubuntu】【Hugo】搭建私人博客:侧边导航栏(五)
linux·运维·ubuntu
阿巴~阿巴~17 小时前
从不可靠到100%可靠:TCP与网络设计的工程智慧全景解析
运维·服务器·网络·网络协议·tcp/ip·智能路由器