Ansible Playbook 从入门到精通:零基础玩转自动化部署与配置管理

02-Ansible-Playbook 剧本编写


1. Playbook 的结构

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

  • Tasks:任务列表,按顺序执行;

  • Variables:用来存储可变数据的机制,目的是让 Playbook 更灵活、可重用、易维护。也就是 :变量 = 把"硬编码"的值抽出来,变成可以动态替换的占位符;

  • Templates:允许在配置文件中嵌入变量和逻辑,通俗点就是一种动态生成配置文件的机制,它使用 Jinja2 模板引擎,让你可以根据变量、主机信息(facts)、环境差异等,自动生成适合目标主机的配置文件;

  • Handlers:特殊的tasks,仅在被notify触发时执行(看任务执行后的变更),其中notify就相当于改完配置文件后的自动更新;

  • Roles:将相关资源打包成独立的角色,以便下次复用(一个playbook内容包含很多,这时roles就相当于为playbook加了目录,方便快速找到要部署的内容)。

2. Ansible Playbook 示例

下面的示例展示了一个简单的 Playbook,演示了基本的任务执行流程和 Ansible 模块使用。

yaml 复制代码
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    #使用 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=true name=httpd state=started
  handlers:     #handlers中定义的就是任务,此处handlers中的任务使用的是service模块
   - name: restart httpd    #notify和handlers中任务的名称必须一致
     service: name=httpd state=restarted
##Ansible在执行完某个任务之后并不会立即去执行对应的handler,而是在当前play中所有普通任务都执行完后再去执行handler,这样的好处是可以多次触发notify,但最后只执行一次对应的handler,从而避免多次重启。
      

3. 命令行运行 Playbook

在运行 Playbook 时,可以使用一些常用参数来调整执行行为:

bash 复制代码
ansible-playbook test1.yaml  # 运行 playbook
ansible-playbook test1.yaml --syntax-check  # 检查语法
ansible-playbook test1.yaml --list-task  # 查看任务列表
ansible-playbook test1.yaml --list-hosts  # 查看影响的主机
ansible-playbook test1.yaml --start-at-task='install httpd'  # 从指定任务开始执行

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

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

4. 变量和引用

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

yaml 复制代码
- 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:ipv4 copy file
      copy: content="{{ ansible_default_ipv4 }}" dest=/opt/ceshi.txt  #如果目标路径不存在 在copy模块可以自动创建

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

bash 复制代码
ansible-playbook test1.yaml -e "username=nginx"
#在目标主机上创建名为 nginx 的用户。

-e 允许你在运行 ansible-playbook 命令时,从命令行直接传入变量,这些变量可以在 Playbook 中使用。

5. 条件判断 when

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

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

  • 根据主机的 IP 地址来执行任务:

    yaml 复制代码
    //when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务
    ---
    - name: ding shi ren wu
      hosts: all
      remote_user: root
      tasks:
       - name: shutdown host 
         command: /sbin/shutdown -r now #执行这个任务后,远程主机会立即开始重启流程。
         #也可以shutdown -r 20  二十分钟后重启
         
         when:  #当任务为真 才能被执行ansible_default_ipv4.address == "192.168.10.14" 
         #仅当远程主机的默认 IPv4 地址是 "192.168.10.14" 时,才执行当前任务。
         #when指令中的变量名不需要手动加上 {{}}
  • 或根据主机名来执行:

    yaml 复制代码
    when: inventory_hostname == "<主机名>"

6. **迭代:使用with_items或loop **

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

yaml 复制代码
//Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环。

---
- name: play1
  hosts: dbservers
  gather_facts: false #关闭 Facts 收集(不自动获取远程主机信息,加快执行速度)

  tasks: 
    - name: create directories
      file:
        path: "{{item}}"
        state: directory
      with_items:          #等同于 loop:    
        - /tmp/test1
        - /tmp/test2
        #在远程主机上创建 /tmp/test1 和 /tmp/test2 两个目录
    - name: add users
      user: name={{item.name}} state=present groups={{item.groups}}
       #分别引用每个用户的名称和所属组
      with_items:#也可以使用loop
        - name: test1
          groups: wheel
        - name: test2
          groups: root
         # 创建 test1 用户,加入 wheel 组
#创建 test2 用户,加入 root 组


dir文件夹

#创建文件,循环列表        
 vim demo06.yaml
 ---
 - name: test play
   hosts: webservers
   gather_facts: false  禁用 facts 收集(因为这个任务不需要远程主机的系统信息)
   tasks:  
     - name: create files #创建文件
       file:
          path: "{{item}}" #直接使用路径字符串
          state: touch
       with_items:
          - /tmp/ryf.txt #具体文件路径
          - /tmp/ryc.txt
 
 #创建用户
 ---
 - name: test play
   hosts: webservers
   gather_facts: false
   tasks:
     - name: create users
       user:  #创建用户
          name: "{{item.name}}" #指定要创建的用户名,这里通过循环变量 item.name 获取(值为 ryf)
          groups: "{{item.groups}}"  指定用户所属的组,通过 item.groups 获取(值为 wheel)
          state: present  确保用户存在(如果不存在就创建,存在则不做操作)
       with_items:  定义循环列表
          - name: ryf
            groups: wheel
          - name: ryc
            groups: root
 循环列表中的用户信息,包含用户名 ryf 和所属组 wheel 以及 用户名ryc和所属组 root

7. Templates 模块

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

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

  1. 创建 Jinja 模板文件 (.j2)
bash 复制代码
#先准备一个以 .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.定义变量并在主机清单中指定

ini 复制代码
#修改主机清单文件,使用主机变量定义一个变量名相同,而值不同的变量
vim /etc/ansible/hosts  
(两台机器改两个)
[webservers]
192.168.10.141 http_port=192.168.10.141:80 server_name=www.accp.com root_dir=/var/www/html
  1. Playbook 示例

    yaml 复制代码
    vim demo07.yaml
    ---
    - hosts: webservers
      remote_user: root
      vars:
        package: httpd
        service: httpd
      tasks:
        - name: install httpd package
          yum: name={{ package }} state=latest
    
        - name: install configure file
          template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
          notify:
            - restart httpd
    #重启配置notify
        - name: create root dir
          file: path=/var/www/html
          state=directory
    #看一下这个httpd路径是不是  要创建的目录路径
        - name: start httpd server
          service: name={{ service }} enabled=true state=started
    
      handlers:
        - name: restart httpd
          service: name={{service }} state=restarted

ansible-playbook dome07.yaml --syntax-check

8. Tags 模块

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

yaml 复制代码
\\可以在一个playbook中为某个或某些任务定义"标签",在执行此playbook时通过ansible-playbook命令使用--tags选项能实现仅运行指定的tasks。
playbook还提供了一个特殊的tags为always。作用就是当使用always当tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。
---
- hosts:  # 指定目标主机组(在Ansible inventory中定义)
  remote_user:  # 以root用户身份执行任务
  tasks # 任务列表(按顺序执行)
    - name: Copy hosts file
      copy: src=/etc/hosts dest=/etc/hosts
      tags# 标签:仅当指定该标签时才执行此任务
        - only

    - name: touch file
      file: path=/opt/testhost state=touch  # 使用file模块,在被控节点的/opt目录下创建testhost空文件
      tags:
        - always  # 始终执行
# 标签:无论是否指定标签,始终执行此任务
        
        
       

执行时指定 --tags 参数:

bash 复制代码
ansible-playbook webhosts.yaml --tags="only"

9. Roles 模块

9.1 Roles 概念

Roles 数据中心有各种不同类型的主机。如web服务器、数据库服务器,基于开发环境的服务器。随着时间的推移,具有处理所有这些情况的任务和人员的Ansible playbook将变得庞大而复杂。

1)角色允许将复杂的剧本组织成独立的、更小的剧本和文件

2)角色提供了一种从外部文件加载任务、处理程序和变量的方法

3)角色也可关联和引用静态的文件和模板

4)角色可以编写成满足普通用途需求,并且能被重复利用

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

9.2 roles 内各目录含义解释
  • files: 用来存放由 copy 模块或 script 模块调用的文件。

  • templates: 用来存放 jinjia2 模板,template 模块会自动在此目录中寻找 jinjia2 模板文件。

  • tasks: 此目录应当包含一个 main.yml 文件,用于定义此角色的任务列表,此文件可以使用 include 包含其它的位于此目录的 task 文件。

  • handlers: 此目录应当包含一个 main.yml 文件,用于定义此角色中触发条件时执行的动作。

  • vars: 此目录应当包含一个 main.yml 文件,用于定义此角色用到的变量。

  • defaults: 此目录应当包含一个 main.yml 文件,用于为当前角色设定默认变量。

  • meta: 此目录应当包含一个 main.yml 文件,用于定义此角色的特殊设定及其依赖关系。

Roles 是将 Playbook 组织成模块化的结构,使其易于管理和重用。每个 Role 都有一套预定义的目录结构:

复制代码
roles/
├── web/
│   ├── files/
│   ├── templates/
│   ├── tasks/
│   ├── handlers/
│   ├── vars/
│   ├── defaults/
│   └── meta/
└── db/
    ├── files/
    ├── templates/
    ├── tasks/
    ├── handlers/
    ├── vars/
    ├── defaults/
    └── meta/
9.3 在一个 playbook 中使用 roles 的步骤:
  1. 创建以 roles 命名的目录:

    bash 复制代码
    mkdir /etc/ansible/roles/ -p    #yum装完默认就有
  2. 创建全局变量目录(可选):

    yaml 复制代码
    mkdir /etc/ansible/group_vars/ -p
    touch /etc/ansible/group_vars/all     #文件名自己定义,引用的时候注意
  3. 在 roles 目录中分别创建以各角色名称命令的目录,如 httpd、mysql:

    yaml 复制代码
    mkdir /etc/ansible/roles/httpd
    mkdir /etc/ansible/roles/mysql
  4. 在每个角色命令的目录中分别创建files、handlers、tasks、templates、meta、defaults和vars目录,用不到的目录可以创建为空目录,也可以不创建:

    复制代码
    mkdir /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta}
    mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta}
  5. 在每个角色的 handlers、tasks、meta、defaults、vars 目录下创建 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
  6. 修改 site.yml 文件,针对不同主机去调用不同的角色:

    复制代码
    vim /etc/ansible/site.yml
    ---
    - hosts: webservers
      remote_user: root
      roles:
         - httpd
    - hosts: dbservers
      remote_user: root
      roles:
         - mysql
  7. 运行 ansible-playbook:

    复制代码
    cd /etc/ansible
    ansible-playbook site.yml
9.4 案列
9.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

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

tree roles/

9.4.2 编写httpd模块
复制代码
vim /etc/ansible/roles/httpd/tasks/main.yml
- name: install apache
  yum: name={{pkg}} state=latest
 # 确保安装最新版本(若已安装则更新到最新
- name: start apache
  service: enabled=true name={{svc}} state=started   # 设置开机自启 # 确保服务处于启动状态(若已停止则启动)
 
//定义变量:可以定义在全局变量中,也可以定义在roles角色变量中,一般定义在角色变量中
vim /etc/ansible/roles/httpd/vars/main.yml
pkg: httpd
svc: httpd
9.4.3 编写mysql模块
复制代码
vim /etc/ansible/roles/mysql/tasks/main.yml
- name: install mysql
  yum: name={{pkg}} state=latest
- name: start mysql
  service: enabled=true name={{svc}} state=started
  
vim /etc/ansible/roles/mysql/vars/main.yml
pkg:
  - mariadb
  - mariadb-server
svc: mariadb
9.4.4 编写php模块
复制代码
vim /etc/ansible/roles/php/tasks/main.yml
- name: install php
  yum: name={{pkg}} state=latest
- name: start php-fpm
  service: enabled=true name={{svc}} state=started

vim /etc/ansible/roles/php/vars/main.yml
pkg:
  - php
  - php-fpm
svc: php-fpm
9.4.5 编写roles
复制代码
vim /etc/ansible/site.yml
#site.yml 自定义  #放主机名、用户、模块
---
- hosts: webservers
  remote_user: root
  roles:
   - httpd
   - mysql
   - php


cd /etc/ansible
ansible-playbook site.yml

roles 把剧本分解成多个较小的模块 每个角色各司其职 用什么功能就去相对应的模块

创建七个文件夹(files\tasks\vars\templates\handlers\defaults\depencies) 他们的功能就是ansible下边模块的功能(command\shell\cron\user\group\copy\file\hostname\ping\yum\service/systomd\scriipt\setup)

roles #site.yml 自定义 #放主机名、用户、模块

相关推荐
小虾米vivian2 小时前
dmetl5 web管理平台 监控-流程监控 看不到运行信息
linux·服务器·网络·数据库·达梦数据库
老蒋新思维2 小时前
创客匠人:从个人IP到知识变现,如何构建可持续的内容生态?
大数据·网络·人工智能·网络协议·tcp/ip·创客匠人·知识变现
老蒋新思维2 小时前
创客匠人洞察:从“个人品牌”到“系统物种”——知识IP的终极进化之路
网络·人工智能·网络协议·tcp/ip·重构·创客匠人·知识变现
lin张2 小时前
Ansible学习总结:从基础命令到Playbook实战
网络·学习·ansible
我是小邵2 小时前
“域名托管”和“SSL 证书缺失”是什么关系?
网络·网络协议·ssl
Henry Zhu1232 小时前
VPP中ACL源码详解第六篇:多核和性能优化实现以及调试与观测
运维·网络·网络协议·计算机网络·性能优化
qq_150841992 小时前
搭建一个基于星空组网的免费虚拟局域网
网络
厦门辰迈智慧科技有限公司2 小时前
电子界桩的技术原理和功能特点
安全·自动化·电子界桩·智能电子界桩
技术小甜甜2 小时前
[Python实战] 告别浏览器驱动烦恼:用 Playwright 优雅实现网页自动化
开发语言·python·自动化