Ansible 自动化运维工具

1. 概述

Ansible 是一个批量管理远程主机的自动化工具,用它可以实现如下功能,极大地提升了运维人员批量管理远程主机的效率:

  • 配置管理。
  • 应用程序部署。
  • 执行一次性批量任务。
  • 将任务编排起来形成一个 playbook,可以多次使用,称之为多节点编排。

特点

  • 无代理架构
    • 通过 SSH(Linux)或 WinRM(Windows)直接管理节点,无需在目标机器上安装客户端。
    • 依赖 Python 环境(默认已内置在大多数 Linux 系统中)。
  • 声明式语言(YAML)
    • 使用易读的 YAML 文件(称为 Playbook)描述自动化任务。
  • 幂等性(Idempotent)
    • 无论执行多少次,Ansible 只会对未达到预期状态的目标进行操作,避免重复变更。
  • 模块化设计
    • 提供数千个内置模块(如 filecopytemplatedocker_container),覆盖常见运维场景。
  • 跨平台支持
    • 可以管理 Linux、Windows、网络设备(如 Cisco、Juniper)和云服务(AWS、Azure、GCP)等。

2. 核心组件

  • Inventory:定义管理的目标主机(支持动态获取)。
  • Playbook:YAML 格式的任务剧本,描述自动化流程。
  • Module:执行具体操作的单元(如安装软件、创建文件)。
  • Role:可复用的任务集合,用于组织复杂的 Playbook。
  • Vault:加密敏感数据(如密码、密钥)。
  • Galaxy:共享和下载社区贡献的 Role 和 Playbook。

3. 安装

# 只需要控制端安装即可
# 红帽系可以安装 epel 源,直接使用 yum 安装
sudo yum install epel-release -y
sudo yum install ansible -y
Bash

配置文件:

  • /etc/ansible/ansible.cfg:主配置文件,配置 ansible 工作特性。
  • /etc/ansible/hosts:主机清单。
  • /etc/ansible/roles:存放角色的目录。

命令文件:

  • /usr/bin/ansible:主程序,临时命令执行工具。
    • ansible -version:查看版本。
    • man ansible:查看帮助。
  • /usr/bin/ansible-doc:配置文档,模块功能查看工具。
  • /usr/bin/ansible-galaxy:下载/上传优秀代码或 Roles 模块的官工具。
  • /usr/bin/ansible-playbook:定制自动化任务,编排剧本工具 。
  • /usr/bin/ansible-pull:远程执行命令的工具。
  • /usr/bin/ansible-vault:文件加密工具。
  • /usr/bin/ansible-console:交互式命令行工具。

4. 配置文件详解

4.1. ansible.cfg 主配置文件

配置文件优先级:

  • ANSIBLE_CONFIG 环境变量。
  • ~/.ansible.cfg
  • /etc/ansible/ansible.cfg

配置项详解:

[defaults]
# 控制主机清单文件路径
inventory = /etc/ansible/hosts
# 库文件存放目录
library = /usr/share/ansible/plugins/modules
# 远程主机临时py文件存放目录
remote_tmp = ~/.ansible/tmp
# 本机的临时执行目录
local_tmp = ~/.ansible/tmp
# 并行进程数(默认 5),被管理的主机数量多时可以适当增大
forks = 5
# Ansible 2.6 之前,远程主机上通过 sudo 提权执行任务时的目标用户(默认为 root)
#sudo_user = root
# 控制是否在执行 sudo 操作时输入密码。
ask_sudo_pass = False
# 控制是否在运行 Playbook 时提示 SSH 登录密码
ask_pass = False
# 远程主机端口,即ssh端口
remote port = 22
# ssh连接的超时时间,单位是秒
timeout = 60
# 主机密钥检查(关闭避免首次连接提示)
host_key_checking = False
# 日志文件路径
log_path = /var/log/ansible.log

[privilege_escalation]
# 是否默认提权
become = True
# 提权方法(sudo/su/pbrun 等)
become_method = sudo
# 提权用户(默认 root)
become user = root
# 控制是否在执行需要提权(如 sudo 或 su)的任务时,提示用户输入密码
# False(默认):不提示密码,直接尝试提权(需预先配置免密提权)
# True:强制交互式提示用户输入提权密码
become_ask pass = False
Bash

4.2. 控制主机清单

主机清单有两种形式:

  • 静态 inventory:指的是使用控制端主机的 /etc/ansible/hosts 文件记录被管 理主机的连接信息。
  • 动态 inventory:一个可执行程序,Ansible 会创建一个子进程执行该程序,然后从该子进程的标准输出获取主机清单。因此,可以用任何语言编写动态 Inventory 程序,只要该程序满足 Ansible 的规范即可。

静态主机清单配置示例:

# 一台主机单独配置
192.168.71.13 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='xxx'

# 多台主机组成一个组,一个组里可以只容纳一台机器,也可以容纳多台机器
[web01]
192.168.71.13 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='xxx'

[web_group1]
192.168.71.14 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='xxx' 
192.168.71.15 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='xxx'

# 端口采用默认端口 22 可以省略
192.168.71.13 ansible_ssh_user=root ansible_ssh_pass='xxx'

# 远程主机需要登录的用户名与使用 ansible 的用户名相同时可以省略
192.168.71.13 ansible_ssh_pass='xxx'

# 如果用户名相同,且使用秘钥登录,则可以只指定IP或可解析的主机名
192.168.71.13

# 也可为组指定变量
[web01]
192.168.71.13
[web01:vars]
ansible_ssh_user=root
ansible_ssh_port=22
ansible_ssh_pass='xxx'
ansible_ssh_private_key_file=/root/.ssh/id_rsa

# 也可以将各个小组整合为一个大组
[www:children]
web01
web_group1
Bash

5. 执行任务的两种模式

5.1. Ad-Hoc 模式(临时命令)

特点:

  • 单次执行:快速运行简单任务,无需编写 Playbook。
  • 适合场景
    • 批量执行临时命令(如检查服务状态、重启服务)。
    • 快速验证模块功能。

语法:

ansible <主机组或主机> -m <模块名> -a "<模块参数>" [选项]

# 匹配主机清单支持逻辑运算
# 或  ':'
ansible 'group1:group2:192.168.71.15' -m ping  # 存在于 group1 或 group2 中的主机或者是主机 192.168.71.15
# 与  ':&'
ansible 'group1:&group2' -m ping  # 在 group1 组并且也在 group2 组内的主机
# 非  ':!'
ansible 'group2:!group1' -m ping  # 存在于 group2 但不存在于 group1,注意一定要用单引号
Bash

示例:

# 检查所有主机的磁盘空间
ansible all -m shell -a "df -h"

# 批量安装 Nginx(使用 apt 模块)
ansible web_servers -m apt -a "name=nginx state=present"

# 重启多台主机的服务
ansible db_servers -m service -a "name=mysql state=restarted"
Bash

5.2. Playbook 模式(剧本模式)

特点

  • 持久化任务:通过 YAML 文件定义多步骤任务,可重复执行。
  • 适合场景
    • 复杂部署(如安装配置全套应用)。
    • 需要幂等性(多次执行结果一致)的任务。
    • 版本控制和团队协作。

结构与层次

一个 Playbook 由多个 Play 组成,每个 Play 包含:

  • Hosts:定义目标主机或主机组(来自 Inventory)。
  • Tasks:具体执行的操作(调用模块)。
  • Variables:变量(动态配置)。
  • Handlers:触发任务(如服务重启)。
  • Roles(可选):复用任务集合。

框架示例

---
- name: Play 1 - Configure Web Servers  # Play 描述
  hosts: web_servers                    # 目标主机组
  become: yes                           # 提权                  
  vars:                                 # 变量定义
    http_port: 80
  tasks:                                # 任务列表
    - name: Install Nginx
      apt: name=nginx state=latest
    - name: Copy Custom Config
      copy:
        src: ./nginx.conf
        dest: /etc/nginx/nginx.conf
      notify: Restart Nginx            # 触发 Handler,默认情况下仅在任务执行成功,并且远程主机发生变动的情况下才会执行 notify。
  
  # handlers 只有当其他任务通过 notify 显式调用时才会执行。
  # 无论被通知多少次,Handlers 只在所有普通任务执行完成后运行一次。
  handlers:
    - name: Restart Nginx
      service: name=nginx state=restarted
      

- name: Play 2 - Deploy Database      # 另一个 Play
  hosts: db_servers
  tasks:
    - name: Install MySQL
      yum: name=mysql-server state=present
Bash

Playbook 构成详解参考文档

Playbook 执行基础语法:

ansible-playbook [选项] <playbook.yml>
# <playbook.yml> 指定要执行的 Playbook 文件路径(YAML 格式)。

# 示例:
ansible-playbook deploy_nginx.yml
Bash

6. 常用模块介绍

6.1. 查看模块

# 列出所有模块
ansible-doc -l

# 查看模块详细文档
ansible-doc <module_name>

# 显示模块的简化版参数列表(仅参数名和简要说明,无详细描述或示例)
ansible-doc -s <module_name>
Bash

6.2. 远程命令模块

command 模块

# 默认模块,远程执行命令
ansible web01 -m command -a 'free -m'

# 不支持特殊字符
ansible web01 -m command -a "ifconfig eth0 | awk 'NR==2 {print \$2}'"
web01 | FAILED | rc=1 >>
|: Unknown host
ifconfig: `--help' gives usage information.non-zero return code
Bash

shell 模块

ansible web01 -m shell -a 'free -m'

# 支持特殊字符
ansible web01 -m shell -a "ifconfig eth0 | awk 'NR==2 {print \$2}'"
web01 | CHANGED | rc=0 >>
10.0.0.7
Bash

scripts 模块

# 远程执行脚本
ansible web_group -m script -a 'xxx.sh'
Bash

6.3. 软件管理模块

yum 模块

# 在详细文档中搜索EXAMPLES可以搜索到示例
ansible-doc yum
# 示例
EXAMPLES:

- name: Install the latest version of Apache
  ansible.builtin.yum:
    name: httpd
    state: latest

- name: Install Apache >= 2.4
  ansible.builtin.yum:
    name: httpd>=2.4
    state: present

- name: Install a list of packages (suitable replacement for 2.11 loop deprecation warning)
  ansible.builtin.yum:
    name:
      - nginx
      - postgresql
      - postgresql-server
    state: present

- name: Install a list of packages with a list variable
  ansible.builtin.yum:
    name: "{{ packages }}"
  vars:
    packages:
    - httpd
    - httpd-tools
Bash

常用参数:

  • yum.name:要安装的软件包名字,可以指定版本。软件包可以是远程主机本地的,也可以是一个 URL 地址。
    • 示例:
# 安装本地的 rpm 包
ansible 192.168.71.13 -m yum -a 'name=/tmp/zabbix-release-4.0-2.el7.noarch.rpm state=present disable_gpg_check=yes'
# disable_gpg_check=yes 跳过GPG签名验证(适用于未签名的包或信任的本地包)
# Playbook 形式
---
- name: Install Zabbix repository RPM with disabled GPG check
  hosts: 192.168.71.13  # 目标主机IP或主机组
  become: yes           # 使用sudo权限

  tasks:
    - name: Install Zabbix repository package
      ansible.builtin.yum:
        name: /tmp/zabbix-release-4.0-2.el7.noarch.rpm
        state: present
        disable_gpg_check: yes


# 使用 URL 地址
ansible 192.168.71.13 -m yum -a 'name=https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-release-4.0-2.el7.noarch.rpm state=present disable_gpg_check=yes' 
Bash
  • yum.state:
    • latest:没有安装则安装最新版,安装过则更新到最新版。使用 latest 时 name 则不指定版本。
    • present:没有安装则安装,安装过则不更新维持原版本。
    • absent:安装过则卸载。

yum_repository 模块

用于管理 YUM/DNF 软件仓库(Repository) 的模块,核心作用是自动化地添加、修改或删除系统的 YUM 仓库配置。

# 添加一个自定义仓库
- name: Add EPEL repository
  yum_repository:
    name: epel
    description: EPEL YUM repo
    baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
    gpgcheck: yes
    gpgkey: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8
    enabled: 1

# 禁用某个仓库
- name: Disable a repository
  yum_repository:
    name: old_repo
    enabled: no

# 完全移除仓库
- name: Remove a repository
  yum_repository:
    name: deprecated_repo
    state: absent


 
# 为远程主机添加 nginx 仓库
ansible web_group -m yum_repository -a 'name=nginx.repo description="nginx stable repo" baseurl="http://nginx.org/packages/centos/7/$basearch/" enabled=1 gpgcheck=0 file=nginx state=present'
 
# 参数介绍
name=nginx.repo  # 定义仓库的 唯一标识符(即 .repo 文件中的 [repository_id] 段名)。
# 示例:
[nginx.repo]  # <-- 这里由 name 参数控制
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
enabled=1
gpgcheck=0

# 指定仓库配置文件的物理文件名
file=nginx # 创建的文件名为 nginx.repo。
Bash

6.4. 文件管理模块

copy 模块

作用:将本地文件上传到远程主机。

ansible-doc copy
EXAMPLES:
- name: Copy file with owner and permissions
  copy:
    src: /srv/myfiles/foo.conf
    dest: /etc/foo.conf
    owner: foo
    group: foo
    mode: '0644'
    backup: yes
    content: '# This file was moved to /etc/other.conf'
    follow: yes
 
src         # 源文件路径(控制机上的文件)
dest        # 目标路径(远程主机上的文件)
owner       # 设置文件所有者
group       # 设置文件所属组
mode        # 设置文件权限
backup      # 是否备份同名文件
content     # 输入字符串,直接将其内容写入 dest(忽略 src 文件)
follow      # 是否跟踪源文件的符号链接(yes 会复制链接指向的实际文件,no 直接复制链接本身)
Bash

示例:

# 推送文件到远程主机
ansible web01 -m copy -a 'src=/root/nginx.repo dest=/etc/yum.repos.d/'
 
# 推送文件到远程主机,并授权
ansible web01 -m copy -a 'src=/root/nginx.repo dest=/etc/yum.repos.d/ mode=600'
 
# 推送文件到远程主机,并授权属主属组
 ansible web01 -m copy -a 'src=/root/nginx.repo dest=/etc/yum.repos.d/ owner=xxx group=xxx'
 
# 推送文件并备份: 目标主机若存在该文本并且内容与源传过来的不一致,则将目标主机的该文件备份
ansible web01 -m copy -a 'src=/root/nginx.repo dest=/etc/yum.repos.d/ backup=yes'
 
# 直接将内容写入文件
ansible web01 -m copy -a 'content="1111111" dest=/tmp/1.txt'
Bash

file 模块

作用:操作远程主机文件。

ansible-doc file

EXAMPLES:
- name: Change file ownership, group and permissions
  file:
    src: /file/to/link/to
    path: /etc/foo.conf
    owner: foo
    group: foo
    mode: '0644'
    state: link
    recurse: yes
 
path        # 创建的文件或目录的地址
owner       # 文件或目录的属主
group       # 文件或目录的属组
mode        # 文件或目录的权限
state
    link        # 创建软链接
        src     # 源文件
        dest    # 软链接的名字
    touch       # 创建文件
    directory   # 创建目录
    absent      # 删除,目录,文件,软链接
recurse     # 递归授权
Bash

示例:

# 相当于在远程机器上执行:mkdir /code
ansible web01 -m file -a 'path=/code state=directory'
 
# 相当于在远程机器上执行:mkdir /code && chown nginx:nginx /code
ansible web01 -m file -a 'path=/code state=directory owner=nginx group=nginx'
 
# 递归创建目录,不需要加任何参数
ansible web01 -m file -a 'path=/code/wordpress/wp-content/pic state=directory'
 
# 递归授权目录,需要加 recurse=yes
ansible web01 -m file -a 'path=/code/ state=directory owner=nginx group=nginx recurse=yes'

# 创建文件
ansible web01 -m file -a 'path=/tmp/1.txt state=touch'
 
# 创建文件并授权
ansible web01 -m file -a 'path=/tmp/1.txt state=touch owner=nginx group=nginx'

# 创建软连接(源文件或目录必须存在)
ansible web01 -m file -a 'src=/tmp/aaa dest=/tmp/bbb state=link'
ansible web01 -m file -a 'src=/tmp/1.txt dest=/tmp/1.ln state=link'
Bash

get_url 模块

作用:从远程 URL 下载文件。

ansible-doc get_url

EXAMPLES:
- name: Download foo.conf
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    mode: '0440'
    checksum: sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
 
url         # 文件下载地址
dest        # 文件存放路径
mode        # 文件下载后授权
checksum    # 验证文件
    sha256  # 加密方式
Bash

示例:

# 下载网站上的文件
ansible web01 -m get_url -a 'url=http://10.0.0.7/1.txt dest=/tmp'
 
# 下载时验证文件
ansible web01 -m get_url -a 'url=https://www.egonlin.com/static/img/xingganheguan.gif dest=/tmp checksum=md5:8732bc18d78503fe4879fee530115a4e' # md5 值与文件对不上,会报错
Bash

6.5. 服务管理模块

systemd 模块

ansible-doc systemd

EXAMPLES:
- name: Make sure a service is running
  systemd:
    state: started
    name: httpd
 
name: nginx         # 服务名字
state:
    started         # 启动服务
    stopped         # 停止服务
    restarted       # 重启服务
    reloaded        # 重载服务
enabled: yes        # 开机自启
Bash

示例:

# 关闭服务
ansible web01 -m systemd -a 'name=nginx state=stopped'
 
# 启动服务
ansible web01 -m systemd -a 'name=nginx state=started'
Bash

6.6. 用户管理模块

user 模块

ansible-doc user

EXAMPLES:
- name: Add the user 'johnd' with a specific uid and a primary group of 'admin'
  user:
    name: johnd
    comment: John Doe
    uid: 1040
    group: admin
    shell: /bin/bash
    state: absent
    remove: yes
    create_home: false
 
name        # 用户名字
comment     # 用户备注
uid         # 用户id
group       # 用户所在的组名字
shell
    /bin/bash   # 用户可以登录
    /sbin/nologin   # 用户不需要登录
state
    absent      # 删除用户
    present     # 创建用户
remove          # 移除家目录
create_home     # 是否创建家目录
    true        # 创建家目录
    false       # 不创建家目录
Bash

示例:

# 创建用户,指定组(组必须存在否则报错),不需要登录,有家目录
ansible web01 -m user -a 'name=www uid=666 group=www shell=/sbin/nologin create_home=true'
 
# 删除用户并移除家目录
ansible web01 -m user -a 'name=www state=absent remove=yes'
 
# 注意:
## 1.当组的名字与用户名字相同时,删除用户组也会被删除
## 2.当组的名字与用户名字相同时,而组下面还有其他用户,则删除用户时不会删除同名组
Bash

group 模块

ansible-doc group

EXAMPLES:
- name: Ensure group "somegroup" exists
  group:
    name: somegroup         # 组名字
    state: 
        present             # 创建组
        absent              # 删除组
    gid: 666                # 指定组id
Bash

示例:

# 创建用户组
ansible web01 -m group -a 'name=www gid=666 state=present'
 
# 删除用户组
ansible web01 -m group -a 'name=www gid=666 state=absent'
Bash

6.7. 其他模块

7. Playbook 高级用法

7.1. Playbook 条件语句

在 Ansible Playbook 中,条件语句(Conditionals)通过 when 关键字实现,允许根据变量、Facts 或任务结果动态控制任务执行。当表达式的结果返回的是false,便会跳过本次的任务。

  • Facts:在 Ansible 中,Facts 是自动化任务执行时从目标主机动态收集的 系统信息,包括硬件配置、操作系统、网络设置等关键数据。它们以变量的形式存在,为 Playbook 提供实时上下文。
  • 运行 ansible <host> -m setup 可查看完整信息。

示例:

- hosts: group3
  tasks:
    - name: Install httpd
      yum:
        name: httpd
        state: present
      when: ansible_distribution == "Rocky"
 
    - name: Install nginx
      yum:
        name: nginx
        state: present
      when: ansible_distribution == "CentOS"
YAML

条件语句中可以使用运算符:

  • and / or:逻辑与/或
  • == / !=:等于/不等于
  • > / < / >= / <=:数值比较
  • in / not in:包含判断

7.2. Playbook 循环语句

在 Ansible 2.5 版本中新增语法 loop 循环,等价于 with_list。大多数时候, with_xxx 的循环都可以通过一定的手段转换成 loop 循环,
所以从 Ansible 2. 5版本之后,原来经常使用的with_items循环都可以尝试转换成loop。

示例:

- hosts: group1
  tasks:
    - name: httpd and crond are running
      service:
        name: "{{ item }}"  # item是固定的变量名
        state: restarted
      loop:
        - crond
        - httpd
        

# 也可以将 loop 循环列表赋值给一个变量,然后在循环中引用        
# cat /workspace/my_vars.yaml
test_services:
  - crond
  - httpd
 
# cat install_pkgs.yml 
- hosts: group1
  vars_files:
    - /workspace/my_vars.yaml
  tasks:
    - name: postfix and crond are running
      service:
        name: "{{ item }}"
        state: started
      loop: "{{ test_services }}"
YAML

7.3. Playbook 标签

标签(Tags)是Ansible中一个非常有用的功能,它允许您对Playbook中的任务进行标记,从而可以选择性地执行特定任务,而不是运行整个Playbook。

作用:

  • 选择性执行:只运行带有特定标签的任务。
  • 任务分组:将相关任务逻辑分组。
  • 跳过任务:排除特定标签的任务。
  • 提高效率:减少不必要的任务执行时间。

示例:

# 为任务添加标签
tasks:
  - name: Install Apache
    yum:
      name: httpd
      state: present
    tags:
      - webserver
      - installation
      
      
# 为整个Play添加标签
- hosts: webservers
  tags: webserver
  tasks:
    - name: Install Apache
      yum:
        name: httpd
        state: present
YAML

查看 Playbook 定义的所有标签

ansible-playbook playbook.yml --list-tags
Bash

使用标签运行 Playbook

# 运行单个标签
ansible-playbook playbook.yml --tags "webserver"

# 运行多个标签
ansible-playbook playbook.yml --tags "webserver,installation"

# 跳过特定标签
ansible-playbook playbook.yml --skip-tags "debug"
Bash

7.4. Playbook jinja2 模版

Jinja2 是 Ansible 默认使用的模板引擎,它允许您在配置文件中动态插入变量、使用控制结构和过滤器,从而生成动态内容。

引用变量语法:

{{ EXPR }} 引用变量值,模版文件与剧本文件中都可以用该语法引用变量
Bash

逻辑判断语法:

# Jinja2模板判断语法
# 条件判断
{% if EXPR %}
{% elif EXPR %}
{% else %}
{% endif %}

# 示例:
{% if ansible_os_family == "RedHat" %}
# RHEL/CentOS specific configuration
...
{% elif ansible_os_family == "Debian" %}
# Debian/Ubuntu specific configuration
...
{% else %}
# Default configuration
...
{% endif %}
Bash

循环语法:

# Jinja2模板循环语法
# 循环表达式
{% for i in EXPR %}
{% endfor %}

# 示例:
{% for user in users %}
User {{ user.name }} has UID {{ user.uid }}
{% endfor %}
Bash

具体使用示例:

keepalived 配置文件示例:

# 参考正常配置
global_defs {
    router_id lb01
}
vrrp_instance VI_1 {
    state BACKUP        
    interface eth0
    virtual_router_id 50
    priority 100
    advert_int 1
    authentication {    
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3
    }
}
Bash

keepalived 配置文件 jinja2 模版:

# 编写 jinja2 模版配置文件
# keepalived.j2
global_defs {
    router_id {{ ansible_fqdn }}
}
vrrp_instance VI_1 {
{% if ansible_fqdn == "lb01" %}
    state MASTER
    priority 100
{% else %}
    state BACKUP
    priority 90
{% endif %}
    interface eth0
    virtual_router_id 50
    advert_int 1
    authentication {  
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3
    }
}
Bash

Playbook 引用 jinja2 模版:

# keepalived.yml 
- hosts: lb_server
  tasks:
    - name: Install keepalived Server
      yum:
        name: keepalived
        state: present
 
    - name: Config keepalived Server
      template:
        src: /workspace/keepalived.j2
        dest: /etc/keepalived/keepalived.conf
 
    - name: Start keepalived Server
      systemd:
        name: keepalived
        state: started
Bash

7.5. Playbook 重用与解耦

在 Ansible 中实现 Playbook 的重用与解耦是提高自动化代码可维护性和可扩展性的关键。下面介绍两种实现方式:

7.5.1. 使用 include 引用

使用 inclulde_tasks 引入存放 task 的文件:

# 将不同的 task 放入不同的文件,单独的 task 文件不能运行
# /play1.yml
- name: task1
  copy:
    content: "111"
    dest: "/tmp/1.txt"
 
# /play2.yml 
- name: task2
  copy:
    content: "222"
    dest: "/tmp/2.txt"


# 使用 inclulde_tasks 引入
- hosts: group5
  tasks:
    - include_tasks: /play1.yml
    - include_tasks: /play2.yml
Bash

使用 import_playbook 引入剧本文件:

# 每一个 playbook 文件都可以单独运行
- import_playbook: ./base.yml
- import_playbook: ./nginx.yml
- import_playbook: ./php.yml
- import_playbook: ./wordpress.yml
- import_playbook: ./mariadb.yml
Bash

7.5.2. 角色 (Roles)

通过使用 roles,你可以将复杂的设置和操作流程封装在一个统一的文件夹下,进而实现代码的复用和模块化。例如你要部署负载均衡、web服务器、nfs、数据库,那你可以创建四个 role 每个 role 都组织管理了好了各自需要的所有元素(包括任务、变量、handler、 文件等)的目录结构。

创建角色结构语法:

ansible-galaxy init my_role
Bash

结构示例:

ansible-galaxy init first_role
 
tree first_role/
first_role/       # 角色名称,或者叫项目名
├── README.md
├── defaults      # 默认的变量(优先级很低)
│   └── main.yml
├── files         # 存放文件,使用copy模块时自动获取
├── handlers      # 存放触发器的配置
│   └── main.yml
├── meta          # 依赖的服务,执行该项目时先执行其他的项目
│   └── main.yml
├── tasks         # 默认执行的playbook
│   └── main.yml
├── templates     # 存放jinja2模板,使用template模块时自动获取
├── tests
│   ├── inventory
│   └── test.yml
└── vars          # 存放变量
    └── main.ymlroles/
└── my_role/
    ├── defaults/    # 低优先级变量
    ├── vars/        # 高优先级变量
    ├── tasks/       # 主任务文件
    ├── handlers/    # 处理器
    ├── templates/   # 模板文件
    ├── files/      # 静态文件
    └── meta/       # 依赖声明
Bash

同时,使用 roles 时也可以引入其他 roles,roles 依赖关系存储在 roles 目录中meta/main.yml 文件中。示例如下:

vim /etc/ansible/roles/wordpress/meta/main.yml
dependencies:
  - { role: nginx }
  - { role: php }
 
# dependencies 指定依赖关系
# 当运行当前角色时,Ansible 会首先自动执行 nginx 和 php 角色
# 执行顺序为声明顺序(先 nginx 后 php)
# 这两个角色必须存在于 roles/ 目录或通过 ansible-galaxy 安装
Bash

playbook 中使用 roles 语法:

- hosts: webservers
  roles:
    - role: my_role
Bash

8. Ansible Playbook 项目示例

上一篇
下一篇