目录

Ansible-Playbook-保姆级教程从基础配置到-Roles-实战,运维自动化必看

Ansible Playbook 保姆级教程:从基础配置到 Roles 实战,运维自动化必看

前言

在现代IT基础设施管理中,自动化配置管理工具已成为不可或缺的一部分。Ansible作为一款强大的自动化工具,以其简单易用、无需代理的特点受到广泛欢迎。

而Playbook作为Ansible的核心功能,允许用户以YAML格式定义自动化任务,实现基础设施即代码(IaC)的理念。本文将全面介绍Ansible Playbook的编写方法,从基础结构到高级应用,帮助您掌握这一强大工具。

一、Playbook 基础概念

1.1 Playbook 结构概述

Ansible的Playbook是一个包含多个Play的YAML文件,每个Play负责对指定的主机组执行一系列的任务。Playbook通常由以下几个核心组成部分:

  • Tasks(任务):每个任务调用一个模块在目标主机上执行操作
  • Variables(变量):通过定义和使用变量增加Playbook的灵活性和可重用性
  • Templates(模板):通过Jinja2模板动态生成配置文件
  • Handlers(处理器):用于响应任务执行后的变更(由notify触发)
  • Roles(角色):将多个任务、变量、模板、文件和处理程序组织成模块化结构,便于复用

二、Playbook 示例解析

2.1 基础Playbook示例

以下是一个简单的Playbook示例,展示了基本的任务执行流程和Ansible模块的使用方法:

vim test1.yaml

---     #yaml文件以---开头,以表明这是一个yaml文件,可省略
- name: first play1     #定义一个play的名称,可省略
  gather_facts: false    #设置不进行facts信息收集,这可以加快执行速度,可省略
  hosts: webservers    #指定要执行任务的被管理主机组,如多个主机组用冒号分隔
  remote_user: root    #指定被管理主机上执行任务的用户
  tasks:     #定义任务列表,任务列表中的各任务按次序逐个在hosts中指定的主机上执行
   - name: test connection    #自定义任务名称
     ping:     #使用 module: [options] 格式来定义一个任务
   - name: disable selinux
     command: '/sbin/setenforce 0'    #command模块和shell模块无需使用key=value格式
     ignore_errors: True     #如执行命令的返回值不为0,就会报错,tasks停止,可使用ignore_errors忽略失败的任务
   - name: disable firewalld
     service: name=firewalld state=stopped enabled=no   #使用 module: options 格式来定义任务,option使用key=value格式
   - name: install httpd
     yum: name=httpd state=latest
   - name: install configuration file for httpd
     copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf    #这里需要一个事先准备好的/opt/httpd.conf文件
     notify: "restart httpd"    #如以上操作后为changed的状态时,会通过notify指定的名称触发对应名称的handlers操作
   - name: start httpd service
     service: enabled=yes name=httpd state=started
  handlers:     #handlers中定义的就是任务,此处handlers中的任务使用的是service模块
   - name: restart httpd    #notify和handlers中任务的名称必须一致
     service: name=httpd state=restarted

请注意:Ansible在执行完某个任务后并不会立即执行对应的handler,而是在当前play中所有普通任务执行完后再执行handler。这样的好处是可以多次触发notify,但最后只执行一次对应的handler,避免多次重启。

# demo02 安装maridb
---
- name: install mysql
  hosts: dbservers
  tasks:
   - name: install mysql server
     yum:
       name: mariadb,mariadb-server
       state: latest
     become: yes
   - name: start mysql
     service:
       name: mariadb
       state: started
     become: yes

三、Playbook 执行与管理

3.1 命令行运行 Playbook

运行Playbook时,可以使用以下常用参数调整执行行为:

ansible-playbook test1.yaml  # 运行playbook

https://i-blog.csdnimg.cn/direct/662dae4b1828466f9d27f0cab1793555.png

ansible-playbook test1.yaml --syntax-check  # 检查语法
ansible-playbook test1.yaml --list-task  # 查看任务列表

https://i-blog.csdnimg.cn/direct/c6bcc6300f4c435c8bfd488d238e198f.png

ansible-playbook test1.yaml --list-hosts  # 查看影响的主机

https://i-blog.csdnimg.cn/direct/603c80ea9c7847d2807952921b24a810.png

ansible-playbook test1.yaml --start-at-task='install httpd'  # 从指定任务开始执行

https://i-blog.csdnimg.cn/direct/3dae46f82af34634997670f38c2efb05.png

3.2 认证相关参数

如果需要使用SSH密码或sudo密码,可以使用以下选项:

ansible-playbook test1.yaml -k  # 提示输入SSH密码
ansible-playbook test1.yaml -K  # 提示输入sudo密码

四、变量定义与使用

4.1 变量定义方法

变量在Playbook中非常有用,可以通过vars或命令行进行定义:

---
- name: second play
  hosts: dbservers
  remote_user: root
  vars:
    groupname: mysql
    username: nginx
  tasks:
    - name: create group
      group:
        name: "{{ groupname }}"
        system: yes
        gid: 306
    - name: create user
      user:
        name: "{{ username }}"
        uid: 306
        group: "{{ groupname }}"
    - name: copy file
      copy:
        content: "{{ ansible_default_ipv4 }}"
        dest: /opt/vars.txt
# 执行playbook
ansible-playbook test2.yaml

# 验证执行结果
ansible dbservers -a 'id nginx'
ansible dbservers -a 'cat /opt/vars.txt'

https://i-blog.csdnimg.cn/direct/6caefbda90164a878f6b4d31e9612db0.png

4.2 命令行传递变量

变量也可以通过-e参数在命令行中传递:

#  Ansible 的 ​幂等性​(Idempotency)——即 Playbook 可以安全地重复执行而不会产生副作用
ansible-playbook test2.yaml -e 'username=nginx'

https://i-blog.csdnimg.cn/direct/7dc2acfd75194107973bbbaa179a54a5.png

五、条件判断与循环

5.1 条件判断 when

在Ansible中,when指令是唯一通用的条件判断方式。当when指令的值为true时,执行该任务,否则不执行

when用于根据条件执行任务。它的常见用法包括:

  • 根据主机的 IP 地址来执行任务
# when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务。

---
- hosts: all
  remote_user: root
  tasks:
   - name: shutdown host 
     command: /sbin/shutdown -r now  
     when: ansible_default_ipv4.address == "192.168.10.14"  #注意:变量不需要加{{}}

https://i-blog.csdnimg.cn/direct/9832d2a6022745f598470a690809260a.png

  • 或者根据主机名执行任务
# 需要修改/etc/hosts做主机名映射
when: inventory_hostname == "<主机名>"
  • 条件判断when的其他案例
1、判断 内存是否 >=4096 如果大于就安装mariadb
2、判断 cpu 核数 如果是双核 就安装 http
---
- name: when demo
  hosts: all
  gather_facts: true  
  remote_user: root        
  tasks:
    - name: Install MariaDB 
      yum:
        name: mariadb,mariadb-server
        state: present
      when: ansible_memtotal_mb >= 4096 
    - name: Print message if memory insufficient
      debug:
        msg: "Memory is only {{ ansible_memtotal_mb }}MB"
      when: ansible_memtotal_mb < 4096
      
    - name: Install Apache
      yum:
        name: httpd
        state: present
      when: ansible_processor_cores >= 2
    - name: Print message if cores insufficient
      debug:
        msg: "cores is only {{ ansible_processor_cores }}"
      when: ansible_processor_cores < 2

https://i-blog.csdnimg.cn/direct/57b98b3cbc054d24bbaf790fbd803f28.png
https://i-blog.csdnimg.cn/direct/ce2ca5264bde4f4eb4b35761288a5cf2.png

5.2 迭代循环 with_items 和 loop

playbook迭代是指持续修改和优化ansible-playbook 以适应不断变化的运维的需求。 这种迭代提升了自动化任务的效率和准确性。

Ansible支持使用with_itemsloop进行迭代。两者作用相同,loop是较新的推荐用法。

# Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环。

---
- name: demo5.yml
  hosts: dbservers
  remote_user: root
  tasks:
    - name: create directorys
      file:
        path: "{{ item }}"
        state: directory
      loop:    # 等同于with_items:
        - /tmp/test1
        - /tmp/test2
    - name: create users
      user:
        name: "{{ item.name }}"
        state: present
        groups: "{{ item.groups }}"
      loop:
        - name: test1
          groups: wheel
        - name: test2
          groups: root

https://i-blog.csdnimg.cn/direct/4e5a2a825b3a4e6b989626bbbd809296.png
https://i-blog.csdnimg.cn/direct/96950c1df6844235ae0a87a554fe57b5.png

六、模板系统 Templates

6.1 Jinja2 模板引擎

Jinja是基于Python的模板引擎。Template类是Jinja的重要组件,可以看作编译过的模板文件,用于生成目标文本,传递Python变量替换模板中的标记。

templates模块通过 jinjia2把变量和固定内容结合,生成最终的配置文件,并可控制权限和属主,用于自动化部署中灵活生成个性化的配置,来提高管理的效率

Jinja2 模板引擎在 Ansible 中用来动态生成文件。例如,在配置 Apache 时,可以使用模板文件来替换动态值。

6.2 模板使用示例

  1. 创建Jinja模板文件 (.j2)
# 准备.j2后缀的template模板文件,设置引用变量
cp /etc/httpd/conf/httpd.conf /opt/httpd.conf.j2

vim /opt/httpd.conf.j2
Listen {{ http_port }}				#42行,修改
ServerName {{ server_name }}			#95行,修改
DocumentRoot "{{ root_dir }}"          #119行,修改
  1. 在主机清单中定义变量
#修改主机清单文件,使用主机变量定义一个变量名相同,而值不同的变量
vim /etc/ansible/hosts  
[webservers]
192.168.10.14 http_port=80 server_name=www.simon.com:80 root_dir=/etc/httpd/htdocs
  1. 使用模板的Playbook
- hosts: webservers
  remote_user: root
  vars:
    service: httpd
  tasks:
    - name: install "{{ service }}"
      yum:
        name: "{{ service }}"
        state: latest
    - name: install configure file
      template:
        src: /opt/httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: 
        - restart httpd
    - name: create root dir
      file:
        path: "{{ root_dir }}"
        state: directory
    - name: start httpd server
      service:
        name: "{{ service }}"
        state: started
        enabled: yes
  handlers:
    - name: restart httpd
      service:
        name: "{{ service }}"
        state: restarted

https://i-blog.csdnimg.cn/direct/8a42904d8dd74630aa9a3825ecde6e38.png
https://i-blog.csdnimg.cn/direct/7447a1b192fe4cfe990ed88686ccd3fc.png

七、Tags 模块

7.1 Tags 的作用

Tags 允许你指定只执行某些特定任务。通过命令行传入 --tags 参数来执行带有特定标签的任务。

这在大型Playbook中特别有用,可以只运行部分任务而不需要执行整个Playbook。

7.2 Tags 使用示例

可以在一个playbook中为某个或某些任务定义“标签”,在执行此playbook时通过ansible-playbook命令使用**–tags**选项能实现仅运行指定的tasks。

playbook还提供了一个特殊的tags为always。作用就是当使用always当tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。

---
- hosts: webservers
  remote_user: root
  tasks:
    - name: touch file1
      file: path=/opt/test1 state=touch
      tags:
        - always  # 始终执行,无论指定哪个tags
    - name: touch file2
      file: path=/opt/test2 state=touch
      tags:
        - only

7.3 执行指定Tags

ansible-playbook webhosts.yaml --tags="only"

特殊标签always的作用是当使用always tags的task时,无论执行哪一个tags,定义有always的tags都会执行。
https://i-blog.csdnimg.cn/direct/09742b912d6542cfb7a0f1276f9094a0.png

# tags=only不会执行
ansible-playbook webhosts.yaml --tags="always"

https://i-blog.csdnimg.cn/direct/4d4ce94896d74bd4812661d1ea71f08b.png

八、Roles 模块

8.1 Roles 概念与优势

随着业务增长,数据中心会有各种不同类型的主机(Web服务器、数据库服务器、开发环境服务器等)。处理这些情况的Ansible playbook会变得庞大复杂。

Roles提供了以下优势

  • 简化剧本管理:将剧本分解为较小的模块后,每个角色处理特定功能,使得整体管理更加清晰。
  • 模块化和重用性:角色可以在不同的项目或场景中反复使用,减少重复代码的编写。
  • 易于维护和扩展:当某个部分的逻辑需要更新时,只需修改相应的角色,而不必修改整个playbook。

Ansible为了层次化、结构化地组织Playbook,使用了角色(roles),roles可以根据层次型结构自动装载变量文件、task以及handlers等。简单来讲,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中,并可以便捷地include它们。roles一般用于基于主机构建服务的场景中,但也可以用于构建守护进程等场景中。

8.2 Roles 目录结构

每个Role都有预定义的目录结构:

roles/
├── web/
│   ├── files/
│   ├── templates/
│   ├── tasks/
│   ├── handlers/
│   ├── vars/
│   ├── defaults/
│   └── meta/
└── db/
    ├── files/
    ├── templates/
    ├── tasks/
    ├── handlers/
    ├── vars/
    ├── defaults/
    └── meta/

各目录含义

  • files:存放由copy或script模块调用的文件
  • templates:存放jinjia2模板,template模块自动在此目录寻找模板文件
  • tasks:包含main.yml文件,定义此角色的任务列表
  • handlers:包含main.yml文件,定义触发条件时执行的动作
  • vars:包含main.yml文件,定义此角色用到的变量
  • defaults:包含main.yml文件,为当前角色设定默认变量
  • meta:包含main.yml文件,定义此角色的特殊设定及依赖关系

8.3 使用Roles的步骤

  1. 创建roles目录:
mkdir /etc/ansible/roles/ -p    #yum安装后默认已有
  1. 创建全局变量目录(可选):
mkdir /etc/ansible/group_vars/ -p
touch /etc/ansible/group_vars/all     #文件名自定义,引用时注意
  1. 在roles目录中创建各角色目录:
mkdir /etc/ansible/roles/httpd
mkdir /etc/ansible/roles/mysql
  1. 在每个角色目录中创建子目录:
mkdir /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta}
mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta}
  1. 创建main.yml文件:
touch /etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yml
touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yml
  1. 编写site.yml调用角色:
vim /etc/ansible/site.yml
---
- hosts: webservers
  remote_user: root
  roles:
     - httpd
- hosts: dbservers
  remote_user: root
  roles:
     - mysql
  1. 运行ansible-playbook:
cd /etc/ansible
ansible-playbook site.yml

8.4 Roles 实战案例

8.4.1 创建项目目录

mkdir /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta} -p
mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta} -p
mkdir /etc/ansible/roles/php/{files,templates,tasks,handlers,vars,defaults,meta} -p

https://i-blog.csdnimg.cn/direct/7c8c569bd49e49529855d2576fb0c22a.png

touch /etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yml
touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yml
touch /etc/ansible/roles/php/{defaults,vars,tasks,meta,handlers}/main.yml

https://i-blog.csdnimg.cn/direct/f6d9d44154bf4679850d2effe97b7de5.png

8.4.2 编写httpd模块

vim /etc/ansible/roles/httpd/tasks/main.yml
- name: install apache
  yum:
    name: "{{ pkg }}"
    state: latest
- name: start apache
  service:
    name: "{{ svc }}"
    state: started
    enabled: yes

# 定义变量
vim /etc/ansible/roles/httpd/vars/main.yml
pkg: httpd
svc: httpd

8.4.3 编写mysql模块

vim /etc/ansible/roles/mysql/tasks/main.yml
- name: install mysql
  yum:
    name: "{{ pkg }}"
    state: latest
- name: start mysql
  service:
    name: "{{ svc }}"
    state: started
    enabled: yes

  
vim /etc/ansible/roles/mysql/vars/main.yml
pkg:
  - mariadb
  - mariadb-server
svc: mariadb

8.4.4 编写php模块

vim /etc/ansible/roles/php/tasks/main.yml
- name: install php
  yum:
    name: "{{ pkg }}"
    state: latest
- name: start php
  service:
    name: "{{ svc }}"
    state: started
    enable: yes


vim /etc/ansible/roles/php/vars/main.yml
pkg:
  - php
  - php-fpm
svc: php-fpm

8.4.5 编写roles剧本

vim /etc/ansible/site.yml
---
- hosts: webservers
  remote_user: root
  roles:
   - httpd
   - mysql
   - php

cd /etc/ansible
ansible-playbook site.yml

https://i-blog.csdnimg.cn/direct/2fb0a1326156473e8f8421c08b76d704.png
https://i-blog.csdnimg.cn/direct/6a346a885b7b4e3980b9e977c7958adb.png

总结

Ansible Playbook是自动化配置管理的核心工具,通过YAML格式的声明式语言,使基础设施管理变得简单高效。本文从Playbook基础结构入手,详细介绍了变量使用、条件判断、迭代循环、模板系统、Tags标签和Roles角色等核心功能。

通过合理使用这些功能,您可以创建出结构清晰、可重用性高的自动化脚本,大大提高运维效率。特别是Roles功能,能够将复杂的环境配置模块化,是Ansible在实际生产环境中应用的最佳实践。

掌握Ansible Playbook编写不仅能够提升个人技能,还能为团队带来标准化和自动化的运维流程,是现代运维工程师和开发者的必备技能。