m-zhuang

导航

Ansible 自动化工具(剧本 playbook)

一、playbooks 概述

1. playbook 简介

Playbooks 是 Ansible的配置、部署、编排语言,他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合

Playbooks 与 ad-hoc相比,是一种完全不同的运用ansible的方式,是非常之强大的。

简单来说,playbooks是一种简单的配置管理系统与多机器部署系统的基础,与现有的其他系统有不同之处,且非常适合于复杂应用的部署。

playbook是ansible用于配置,部署,和管理被控节点的剧本。

通过playbook的详细描述,执行其中的一系列tasks,可以让远端主机达到预期的状态。playbook就像Ansible控制器给被控节点列出的的一系列to-do-list,而被控节点必须要完成。

也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情

2. playbook 使用场景

执行一些简单的任务,使用ad-hoc命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的ad-hoc命令是不适合的,这时最好使用playbook。

就像执行shell命令与写shell脚本一样,也可以理解为批处理任务,不过playbook有自己的语法格式。

使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用Ansible的过程中,你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成

playbook,之后管理服务器会变得十分简单。

3. playbooks 的组成

playbooks 本身由以下各部分组成

  • Tasks:任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行
  • Variables:变量
  • Templates:模板
  • Handlers:处理器,当changed状态条件满足时,(notify)触发执行的操作
  • Roles:角色

4. yaml 基本语法规则

大小写敏感

使用缩进表示层级关系

缩进时不允许使用tab键、只允许使用空格

缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

5. yaml 关键字

关键字 含义
hosts 定义节点,可以是组:在 Ansible 中,hosts 关键字用于定义执行任务的主机节点,可以是单个主机或主机组。
remote_user 指定以哪个用户身份进行登录:remote_user 关键字用于指定在执行任务时要使用的远程用户身份。
tasks 定义任务:tasks 关键字用于定义要在主机上执行的任务列表。
become:yes 表示切换用户:become 关键字用于表示在执行任务之前要切换到特定用户。
become_user:mysql 表示切换到 mysql 用户,配合上一条使用:become_user 关键字用于指定要切换到的特定用户。
-name 为下面执行的操作起名:在任务列表中,使用 - name 来为每个任务指定一个描述性的名称。

6. yaml 支持的数据结构

在 YAML 中,支持以下三种基本数据结构:

(1)对象(Mapping)

对象是键值对的集合,用于表示复杂的数据结构或属性集。对象使用冒号和缩进来表示键值对关系,键值对之间使用换行分隔。例如:

yamlCopy Codeperson:
  name: John Doe
  age: 30

上述示例中的 person 就是一个对象,包含了 nameage 两个键值对。

(2)数组(Sequence)

数组是一组按次序排列的值,用于表示有序的元素列表。数组使用短横线 - 和缩进来表示每个元素,元素之间使用换行分隔。例如:

yamlCopy Codefruits:
  - apple
  - orange
  - banana

上述示例中的 fruits 是一个数组,包含了三个元素 appleorangebanana

(3)纯量(Scalar)

纯量是单个的、不可再分的值,用于表示简单的数据类型,如字符串、整数、布尔值等。纯量可以直接写在一行中。例如:

yamlCopy Codename: John Doe
age: 30
active: true

上述示例中的 nameageactive 都是纯量。

通过组合和嵌套这些基本数据结构,YAML 可以表达复杂的数据模型和层次结构。这使得 YAML 成为一种方便且易读的数据序列化格式。

二、playbook 操作示例

主机清单

webserver 组:

image-20230830161326473

dbservers 组:

image-20230830161309381

1. 示例:安装 Apache 服务

vim /opt/test1.yuml

---     #yaml文件以---开头,以表明这是一个yaml文件,可省略
- name: first play     #定义一个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,从而避免多次重启。


# 上传 httpd.conf 配置文件到 /opt
cd /opt
rz -E

# 运行playbook
ansible-playbook test1.yaml

# 补充参数:
-k(–ask-pass)	# 用来交互输入ssh密码
-K(-ask-become-pass)	# 用来交互输入sudo密码
-u	# 指定用户
ansible-playbook test1.yaml --syntax-check    #检查yaml文件的语法是否正确
ansible-playbook test1.yaml --list-task       #检查tasks任务
ansible-playbook test1.yaml --list-hosts      #检查生效的主机
ansible-playbook test1.yaml --start-at-task='install httpd'     #指定从某个task开始运行

image-20230830155433888

image-20230830160313858

# 检查yaml文件的语法是否正确
ansible-playbook test1.yaml --syntax-check    

image-20230830160253733

# 检查tasks任务
ansible-playbook test1.yaml --list-task       

image-20230830160452293

# 检查生效的主机
ansible-playbook test1.yaml --list-hosts      

image-20230830160535361

# 指定从某个task开始运行
ansible-playbook test1.yaml --start-at-task='install httpd'     

image-20230830161013415

浏览器访问:http://192.168.23.15

image-20230830161057542

2. 示例:定义、引用变量

vim /opt/test2.yaml

---
- name: second play
  hosts: dbservers
  remote_user: root
  vars:                 #定义变量
    - groupname: mysql   #格式为 key: value
    - username: nginx
  tasks:
    - name: create group
      group: name={{groupname}} system=yes gid=123    #使用 {{key}} 引用变量的值
    - name: create user
      user: name={{username}} uid=123 group={{groupname}} 
    - name: copy file
      copy: content="{{ansible_default_ipv4}}" dest=/opt/vars.txt    #在setup模块中可以获取facts变量信息


ansible-playbook test1.yaml


image-20230830163515203

image-20230830163727587

image-20230830163830999

# 在命令行里定义变量
ansible-playbook test1.yaml -e "username=testuser"     

image-20230830164427451

3. 示例:指定远程主机 sudo 切换用户

vim test3.yaml

---
- name: sudo play
  gather_facts: fales
  hosts: dbservers
  remote_user: testuser
  become: yes			# 2.6版本以后的参数,之前是sudo,意思为切换用户运行
  become_user: root		# 指定sudo用户为root


# 设置 testuser 用户密码
ansible dbservers -m shell -a 'echo user123 | passwd --stdin testuser'

# 执行playbook时
ansible-playbook test1.yml -K
user123

image-20230830165844985

image-20230830170930060

image-20230830171045481

4. 示例:when 条件判断

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

when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务

vim /opt/test4.yaml
---
- hosts: all
  remote_user: root
  tasks:
   - name: shutdown host 
     command: /sbin/shutdown -r now
     when: ansible_default_ipv4.address == "192.168.23.15"      
     # when指令中的变量名不需要手动加上 {{}}
     # 或 
     when: inventory_hostname == "<主机名>"
	
ansible-playbook test2.yaml

image-20230830181314137

image-20230830181524699

image-20230830181629648

5. 示例:迭代

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

vim /opt/test5.yaml
---
- name: items_play  # Playbook 的名称,用于标识此 Play 的目的或用途
  hosts: dbservers  # 要执行此 Play 的主机组,可以是主机名、IP地址或主机组名
  gather_facts: false  # 是否收集远程主机的事实信息

  tasks:  # 定义任务列表
    - name: create directories  # 任务名称,用于描述此任务的目的或功能
      file:  # 使用 file 模块来创建目录
        path: '{{item}}'  # 目录的路径,从变量 item 中获取值
        state: directory  # 确保目录存在且是一个目录
      with_items:  # 遍历 item 列表中的每个元素执行任务
        - /tmp/test1  # 第一个目录的路径
        - /tmp/test2  # 第二个目录的路径
      
    - name: add users  # 任务名称,用于描述此任务的目的或功能
      user:  # 使用 user 模块来创建用户
        name: {{item.name}}  # 用户名,从变量 item.name 中获取值
        state: present  # 确保用户存在
        groups: {{item.groups}}  # 用户所属的组,从变量 item.groups 中获取值
      with_items:  # 遍历 item 列表中的每个元素执行任务
        - name: test1  # 第一个用户的用户名
          groups: wheel  # 第一个用户所属的组
        - name: test2  # 第二个用户的用户名
          groups: root  # 第二个用户所属的组
          
          
ansible-playbook test5.yaml

image-20230830191551327

image-20230830191846047

image-20230830192306644

image-20230830192331169

三、Templates 模块

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

1. 准备 .j2 模板文件

先准备一个以 .j2 为后缀的 template 模板文件,设置引用的变量

cp /opt/httpd.conf /opt/httpd.conf.j2

vim /opt/httpd.conf.j2
Listen {{http_port}}				# 42行,修改
ServerName {{server_name}}			# 95行,修改
DocumentRoot "{{root_dir}}"         # 119行,修改
<Directory "{{root_dir}}">			# 131行,配置访问目录权限

image-20230830224407000

image-20230830224449900

image-20230830224531776

image-20230830230851169

2. 修改主机清单

修改主机清单文件,使用主机变量定义一个变量名相同,而值不同的变量

vim /etc/ansible/hosts       
[webservers]
192.168.23.15 http_port=192.168.23.15:80 server_name=www.15server.com:80 root_dir=/etc/httpd/htdocs

[dbservers]
192.168.23.20 http_port=192.168.23.20:80 server_name=www.20server.com:80 root_dir=/etc/httpd/htdocs

image-20230830225004217

image-20230830225032290

3. 编写 playbook

vim /opt/apache.yaml

---
- hosts: all
  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
    - name: create root dir
      file: path=/etc/httpd/htdocs state=directory
    - name: start httpd server
      service: name={{service}} enabled=true state=started
  handlers:
    - name: restart httpd
      service: name={{service}} state=restarted
  
  
  
ansible-playbook apache.yaml

image-20230830232119380

image-20230830232518861

image-20230830232720077

posted on 2023-09-01 16:29  m_zhuang  阅读(115)  评论(0编辑  收藏  举报