【003】Ansible学习笔记-Playbook, YAML语法

【003】Ansible学习笔记-Playbook, YAML语法

  • 一、 命令行方式执行 AD-Hoc 的缺点
  • 二、 什么是 PlayBook
  • 三、 YAML
    • 1 字符串
    • 2 列表
    • 3 字典
    • 示例1-基本写法
    • 示例2 - 变量定义及使用
    • 示例3 - 条件判断
    • 示例4 - handlers
    • 示例5 - 循环
    • 示例6 - tags
    • 示例7 - register
  • 四、 如何写 Playbook
    • 1 Play
    • 2 Play 的属性
    • 3 一个完整剧本
    • 4 tasks 属性中任务的几种写法
    • 5 含有多个Play 的 Playbook 啥样
    • 6 语法校验
    • 7 运行PlayBook
    • 8 测试运行
  • 五、YAML 实例
  • Reference

一、 命令行方式执行 AD-Hoc 的缺点

  1. AD-Hoc只能执行简单的命令。
  2. 执行过的任务不法保留下来,不便于重用。
  3. 对于一些复杂的任务,无法完成。比如多个任务之间存在一定逻辑性或者说有一定依赖性。
    示例:安装 Nginx,配置 Nginx,启动 Nginx 服务一系列操作。

二、 什么是 PlayBook

Playbook 在 Ansible 中称为 剧本。

  • 可以认为它是Ansible 自定义的一门语言。
  • 可以将 Playbook 比作 Linux 中的 shell 脚本。

Playbook 组成

  • Target section

定义将要执行 playbook 的远程主机组

  • Variable section

定义 playbook 运行时需要使用的变量

  • Task section

定义将要在远程主机上执行的任务列表

  • Handler section

定义 task 执行完成以后需要调用的任务

三、 YAML

Playbook遵循YAML 的语法格式。

官方文档:

https://docs.ansible.com/ansible/2.9/reference_appendices/YAMLSyntax.html

  1. YAML 文件的规范
    # 为注释符
    以 .yml 或者 .yaml 结尾
    -- 开始 , 以 ... 结束, 但这不是必须的
  2. 基本语法
    大小写敏感
    使用缩进表示层级关系
    缩进时是使用Tab键还是使用空格一定要达到统一,建议使用空格。
    相同层级的元素必须左侧对齐
    YAML 支持的数据表示形有:
  • 字符串
  • 列表
  • 字典

1 字符串

---
# YAML 中的字符串可以不使用引号,即使里面存在空格的时候,当然了使用单引号和双引号也没有错。
this is a string
'this is a string'
"this is a string"
# YAML 中若一行写不下你要表述的内容,可以进行折行。写法如下:
long_line: |
		Example 1
		Example 2
		Example 3
# 或者
long_line: >
		Example 1
		Example 2
		Example 3
...

2 列表

就是和 shell 中的数组差不多

- red
- green
- blue
...

3 字典

就是一个变量名对应一个变量的值

如何定义: key + 冒号( : ) + 空格 + 值(value), 即 key: value

---
# 如何定义: key + 冒号(:) + 空格 + 值(value), 即 key: value

name: Using Ansible
code: D1234
...

混合结构
用列表和字典的形式描述一个班级的组成

---
class:
  - name: stu1
    num: 001
  - name: stu2
    num: 002
  - name: stu3
    num: 003
...

示例1-基本写法

---
- hosts: webservers
  tasks:
  - name: 创建用户jerry
    user:
      name: jerry
      state: present
  - name: 创建文件/tmp/abc
		  file:
	      path: /tmp/abc
	      owner: jerry
	      mode: 0600
	      state: touch

注意:

hosts参数指定了对哪些主机进行操作;

tasks指定了任务列表,其下面的name参数是任务的ID,在执行过程中会打印出来。

示例2 - 变量定义及使用

---
- hosts: webservers
  gather_facts: false
  vars:
  - user_name: jerry
  - file_name: jerry.txt
  tasks:
  - name: create user "{{ user_name }}"
    user:
       name: "{{ user_name }}"
	     state: present
   - name: create file "/tmp/{{ file_name }}"
     file:
       path: "/tmp/{{ file_name }}"
       state: touch
       owner: "{{user_name}}"

注意:

name参数对该playbook实现的功能做一个概述,后面执行过程中,会打印 name变量的值 ,可以省略;

gather_facts参数指定了在以下任务部分执行前,是否先执行setup模块获取主机相关信息,这在后面的task会使用到setup获取的信息时用到;

vars参数指定了变量,这里指字一个user变量,其值为test ,需要注意的是,变量值一定要用引号引住;

user提定了调用user模块,name是user模块里的一个参数,而增加的用户名字调用了上面user变量的值。

示例3 - 条件判断

---
- hosts: all
  user: root
  gather_facts: True
  tasks:
  - name: use when
    shell: touch /tmp/when.txt
    when:
    - ansible_fqdn == "host1.qf.com" # 条件判断

注意:

(1)要求多条件同时满足可用and连接或写成列表的形式;

(2)变量要先定义才能进行比较

示例4 - handlers

---
- hosts: all
  vars:
  - user_name: "hello"
  tasks:
  - name: create user
  user:
  name: {{ user_name }}
  state: present
  notify: change owner to file     # notify后面是handler的ID
  handlers:
  - name: change owner to file
    file:
      name: /tmp/a.txt
      owner: {{ user_name }}

说明:

(1)任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;

(2)当所有任务执行完毕后才会执行handlers

以上只有 user 模块真正执行后,才会去调用下面的 handlers 相关的操作,追加内容。所以这种比较适合配置文件发生更改后,需要重启服务的操作。

示例5 - 循环

---
- hosts: lamp
  tasks:
  - name: install lamp packages
    yum: name={{ item }} state=present
    loop:
      - httpd
      - mariadb-server
      - php
      - php-mysql

# 例 2
---
- name: Create two hard links
  file:
  src: '/tmp/{{ item["src"] }}'
  dest: '{{ item["dest"] }}'
  state: hard
  loop:
    - { src: x, dest: y }
    - { src: z, dest: k }

说明:

循环:迭代,需要重复执行的任务;

对迭代项的引用,固定变量名为"item",而后使用 loop 给定要迭代的元素列表

示例6 - tags

有时候我们并不希望所有的任务都执行。 tags可以对任务打标签,我们可以借助标签,指定执行哪些任务,或者不执行哪些任务

---
- hosts: host1
  gather_facts: false
  tasks:
  - name: task1
  file:
   path: /tmp/task1.txt
	   state: touch
  tags:                                                                     # tags写法1
    - t1
    - test
  - name: task2
    file:
      path: /tmp/task2.txt
	    state: touch
   tags: ['t2','test']                                                     # tags写法2
   - name: task3
   file:
     path: /tmp/task3.txt
     state: touch
   tags: t3

说明:

(1) 任务可以有1个或多个标签

(2) 在执行playbook时,可通过 --tags=tag 来指定想要运行的任务

  • –tags=t1,t2 任务中只要有其中任意一个tag都将执行

  • 所有包含有 “always” 标签的任务都将执行

(3) 在执行playbook时,可通过 --skip-tags 明确指定不执行对应的任务,一般和 --tags 配合使用。使用场景如下:

  • 可禁止含 “always” 标签的任务执行

  • 禁止某些特定的任务执行。如任务1和2都有test标签,希望执行所有含test标签的任务,但有t2标签的除外,可使用 --tags=test --skip-tags=t2来实现

(4) 特殊值 tagged, untagged, all

- tagged 配合 --tags 使用,所有有标签的将执行(有 never 标签的除外); 配合 --skip-tags,无标签的将执行

- untagged 与 tagged 相反

- all 配合 --tags 使用,所有任务都将执行(有 never 标签的除外); 配合 --skip-tags,无任务执行

示例7 - register

# 例 1
---
- hosts: 192.168.10.21
	gather_facts: false
	tasks:
  - name: 获取当前日期
		shell: date +%F
		register: day
  - name: 查看变量内容
	debug:
		var: day

# 例 2
---
- hosts: 192.168.10.21
	gather_facts: false
	vars:
	- foo: "bar"
	tasks:
	- name: 获取当前星期
		shell: date +%w
		register: week_day
  - name: 星期三在/tmp目录下创建记录日期的文件a.txt
		shell: date > /tmp/a.txt
		when: week_day.stdout == "3"

四、 如何写 Playbook

1 Play

由于Playbook 是由一个或者多个Play组成,那么如果我们熟悉Play 的写法,就自然掌握了我们这章的PlayBook。

那如何定义一个Play

1、每一个Play 都是以短横杠开始的
2、每一个Play 都是一个YAML 字典格式

根据上面两条Play 的规则,一个 Play 应该是类似如下的样子

---
- name: shark
  hosts: all
...

由于一个Playbook 是由一个或者多个Play构成, 那么一个含有多个Play的Playbook 结构上应该是如下的样子


# 一个含有3个Play 的伪PlayBook构成
- name: create a user
  hosts: nginx
  key3: value3
- name: copy  a file to webNginx
  hosts: webNginx
  key3: value3

2 Play 的属性

以上一小节中的Play为基础, Play中的每一个key, key1、key2、key3等;这些key在PlayBook中被定义为Play的属性。这些属性都具有特殊的意义,我们不能随意的自定义Play 的属性。那么Ansible本身都支持哪些Play属性呢

常用属性

  • name 属性, 每个play的名字
  • hosts 属性, 每个play 涉及的被管理节点,同命令行执行时候的 主机匹配模式
  • tasks 属性, 每个play 中具体要完成的任务,以列表的形式表达
  • become 属性,如果需要提权,则加上become 相关属性
  • become_user 属性, 若提权的话,提权到哪个用户上
  • remote_user属性,指定连接用户。若不指定,则默认使用当前执行 ansible Playbook 的用户

playbook 变形记

3 一个完整剧本

根据上一小节中介绍的真实的属性,一个含有一个Play 的 Playbook 应该是如下的样子

---
- name: the first play example
  hosts: all
  remote_user: root
  tasks:
    - name: install nginx package
      yum: name=nginx state=present
    - name: copy nginx.conf to remote server
      copy: src=nginx.conf dest=/etc/nginx/nginx.conf
    - name: start nginx server
      service:
        name: nginx
        enabled: true
        state: started

4 tasks 属性中任务的几种写法

以启动 nginx 服务,并增加开机启动为例

# 一行的形式:
service: name=nginx enabled=true state=started

# 多行写成字典的形式:
service:
  name: nginx
  enabled: true
  state: started

5 含有多个Play 的 Playbook 啥样

---
- name: manage web servers
  hosts: webNginx
  remote_user: root
  tasks:
    - name: install nginx package
      yum: name=nginx state=present
    - name: copy nginx.conf to remote server
      copy: src=nginx.conf dest=/etc/nginx/nginx.conf
    - name: start nginx server
      service:
        name: nginx
        enabled: true
        state: started
- name: manager db servers
  hosts: webNginx
  tasks:
    - name: update database confg
      copy: src=my.cnf dest=/etc/my.cnf

6 语法校验

ansible-playbook myplaybook.yml --syntax-check

7 运行PlayBook

ansible-playbook myplaybook.yml

8 测试运行

会执行完整个PlayBook ,但是所有Task中的行为都不会在远程服务器上执行,所有执行都是模拟行为。

ansible-playbook myplaybook.yml -C
// -C 为大写的字母 C

五、YAML 实例

取ansible setup中的uuid

ansible webservers -m setup 

---
- hosts: webservers
  tasks:
  - name: uuid
    shell: echo "{{ ansible_device_links['uuids']['dm-0'][0] }}" >> /tmp/facts.txt

Reference

Ansible-02-Playbook by shark_西瓜甜

————————————————
版权声明:本文为CSDN博主「shark_西瓜甜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_22648091/article/details/117201019

你可能感兴趣的:(Linux,Ansible学习笔记,学习,linux,运维)