Ansible自动化运维学习之三:yaml语法和playbook写法

备注:文章事例部分代码会出现不对齐的情况,使用时,请注意格式对齐!!

第3章 yaml语法和playbook写法

ansible的playbook采用yaml语法,所以在学习ansible playbook之前,就非常有必要了解并掌握yaml的语法格式,多实践掌握playbook的写法,ansible才能使用得顺畅。

3.1 yaml的语法

以下为playbook的一个实例,说明下yaml的语法:

---
- name: Install Mysql package
  yum: name={{ item }} state=present
  with_items:
   - mysql-server
   - MySQL-python
   - libselinux-python
   - libsemanage-python
#安装mysql服务
- name: Configure SELinux to start mysql on any port
  seboolean: name=mysql_connect_any state=true persistent=yes
  when: ansible_selinux.status == "enabled"

- name: Create Mysql configuration file
  template: src=my.cnf.j2 dest=/etc/my.cnf
  notify:
  - restart mysql   #配置my.cnf并重启mysql服务

- name: Start Mysql Service
  service: name=mysqld state=started enabled=yes

1、yaml文件以 --- 开头,以表明这是一个yaml文件;
2、yaml中使用字符"#"作为注释符,它可以注释整行,也可以注释行内从字符"#"开始的之后的内容;
3、yaml中的字符串通常不需要添加任何引号,即使它包含了某些特殊字符。但是在有些情况下,就必须加引号,以免yaml读取时出错,最常见的是在引用变量的时候要注意使用引号来区分;
4、最后是关于布尔值的书写格式,也即true/false的表达方式。这在playbook中的布尔值类型非常灵活,一般可分为以下两种情况:
A:模块的参数: 这时的布尔值是作为字符串被ansible解析。
它接受如下选项:yes/on/1/true/no/off/0/false,这时被ansible解析。
B:非模块的参数: 这时布尔值被yaml解释器解析。接受不区分大小写的true/yes/on/y/false/no/off/n。例如上面的enabled=yes。

关于布尔值在playbook中的使用建议遵循ansible的官方规范:
模块的布尔参数采用yes/no,非模块的布尔参数采用True/False
playbook基础组件
Hosts:运行执行任务(task)的目标主机
remote_user:在远程主机上执行任务的用户
tasks:任务列表
handlers:任务,与tasks不同的是只有在接受到通知时才会被触发
templates:使用模板语言的文本文件,使用jinja2语法。
variables:变量,变量替换{{ variable_name }}

3.2 列表

列表在playbook中的使用是极为重要的,它是使用"- "(减号加一个或多个空格)作为列表项,也就是json中的数组。例如上面的事例:

  • mariadb-server
  • mariadb
  • MySQL-python
  • libselinux-python
  • libsemanage-python
    上述的列表等价为下列的json列表:
    [
    "mariadb-server",
    "mariadb",
    "MySQL-python",
    "libselinux-python",
    "libsemanage-python"
    ]
    也等价为下列内联形式:
    [mariadb-server,mariadb,MySQL-python,libselinux-python,libsemanage-python]
    具体在ansible playbook中,列表所描述的是局部环境,它不一定要有名称,不一定要从同一个属性开始,只要使用"- ",它就表示圈定一个范围,范围内的项都属于该列表。

    3.3字典

    在playbook中,一般"虚拟性"的内容都可以通过字典的方式书写,而实体化的、动作性的、对象性的内容则应该定义为列表形式
    字典的书写方式如:nginx_port: 80
    而无法写成成key/value格式,且是实体文件,则书写为列表如:- nginx_port.yml

    3.4 分行写

    playbook中有3种方式进行续行:
    (1)在"key: "的后面使用大于号。
    (2)在"key: "的后面使用竖线。这种方式可以像脚本一样写很多行语句。
    (3)多层缩进。
    举例如下:

---     #标识
    - hosts: localhost
      tasks: 
        - shell: echo 2 >>/tmp/test.txt
            creates=/tmp/haha.txt          # 比模块shell缩进更多
        - shell: >                         # 在"key: "后使用大于号
            echo 2 >>/tmp/test.txt
            creates=/tmp/haha.txt
        - shell: |                         # 指定多行命令
            echo 2 >>/tmp/test.txt
            echo 3 >>/tmp/test.txt
          args:
            creates: /tmp/haha.txt

3.5 向模块传递参数

模块的参数一般来说是key=value格式的,有3种传递的方式:
(1)直接写在模块后,此时要求使用"key=value"格式。
(2)写成字典型,即"key: value"。书写要求多层缩进。
(3)使用内置属性args,然后多层缩进定义参数列表。
举例如下:

---   #标识
    - hosts: localhost
      tasks: 
        - yum: name=unix2dos state=installed    # key=value直接传递
        - yum: 
            name: unxi2dos
            state: installed            # "key: value"字典格式传递
        - yum: 
          args:                               # 使用args传递
            name: unix2dos
            state:installed

3.6 playbook和play的关系

一个playbook中可以包含多个play。每个play都至少包含有tasks和hosts这两项。
而需要注意的是,在有些时候play中使用了role,playbook内容看上去没有tasks,实际是因为role本身就已经整合playbook,此时没有task并不是语法错误。但如果没有使用role的时候,playbook就必须得包含hosts和tasks两项。

3.7 playbook中什么时候使用引号

playbook中定义的大都是些列表和字典内容。在绝大多数时候,都不需要使用引号,但有两个特殊情况需要考虑使用引号。
(1)出现大括号"{}"时;
(2)出现冒号加空格时": "。
大括号之所以要使用引号包围,是因为不使用引号时会被yaml解析成内联字典,导致语法解析错误或未按实际逻辑执行。

    ---   #标识
        - hosts: localhost
          tasks:
            - shell: 'echo "{{inventory_hostname}}: haha"'
              register: hello
            - debug: 'msg="{{hello.stdout}}: heihei"'

3.8 playbook中template的使用

3.8.1 template

模块中的变量经常会使用到服务器本身的内置变量,我们可以使用setup模块来寻找自己需要的变量名称:

#如查找远程服务器主机名:
[root@centos130 lnmp]# ansible 192.168.8.131 -m setup  -a 'filter="ansible_fqdn"'
192.168.8.131 | SUCCESS => {
    "ansible_facts": {
        "ansible_fqdn": "centos131"
    }, 
    "changed": false
}

#查找远程服务器的cpu核心数:
[root@centos130 lnmp]# ansible 192.168.8.131 -m setup  |grep "cpu"
        "ansible_processor_vcpus": 1,

#查看远程服务器的操作系统类型:
[root@centos130 lnmp]# ansible 192.168.8.131 -m setup  |grep "ansible_os_family"
        "ansible_os_family": "RedHat",

关于模块templates使用介绍:
1、模块为文件、文件、可嵌套有脚本;
2、该模块使用Jinja2语言,有下面这些形式:
(1)字符串:使用单引号或双引号
(2)数字:整数、浮点数
(3)列表:[item1,item2,...]
(4)无组:(item1,item2,...)
(5)字典:{key1:value1,key2:value2,...}
(6)布尔型:true/false
3、算术运算:+,-,*,/,//(取整),%(取余),**(幂)
4、比较操作:==,!=,<,<=,>,>=
5、逻辑运算:and,or,not
6、表达式:for,if,when

注意:template模块只能在ansible-playbook中使用。

举例介绍nginx的worker进程默认是auto,这里修改为服务器cpu核心数的2次方,同时nginx的端口从hosts主机清单中获取:

#修改nginx.conf模块文件
[root@centos130 ansible]# cat template/nginx.conf.j2
....
user nginx;
worker_processes {{ ansible_processor_vcpus**2 }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
....
    server {
        listen       {{ nginx_port }} default_server;
        listen       [::]:{{ nginx_port }} default_server;
.....

#修改hosts主机清单配置
[root@centos130 ansible]# cat hosts
[web]
192.168.8.131 nginx_port

#编写ansible-playbokk
[root@centos130 ansible]# cat testtemp.yml
--- #标识

- hosts: web
  remote_user: root

  tasks:
  - name: install package
     yum: name=nginx

    - name:copy template
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
        notify: restart service

    - name: start service
      service: name=nginx state=started enabled=yes

  handlers:
  - name: restart service
    service: name=nginx state=restarted

#测试执行:
[root@centos130 ansible]# ansible-playbook -i hosts -C testtemp.yml
#也可以直接使用-e参数命令行中添加变量:
[root@centos130 ansible]# ansible-playbook -i hosts -e "http_port=99" testtemp.yml

3.8.2 when的使用

1、条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法格式
2、when语句,在task后添加when子句即可使用条件测试

#例如:
tasks:
- name: shutdown RedHat flavored system
  command: /sbin/shutdown -h now
    when: ansible_os_family == "RedHat"

举例介绍nginx的配置文件,根据操作系统版本的不同,使用不同的nginx.conf模块文件:

#修改nginx.conf模块文件
[root@centos130 ansible]# ls template/
nginx.conf6.j2 nginx.conf7.j2

#编写ansible-playbokk
[root@centos130 ansible]# cat testwhen.yml
--- #标识

- hosts: all
  remote_user: root

  tasks:
  - name: install package
     yum: name=nginx

    - name:copy template for centos7
      template: src=nginx.conf7.j2 dest=/etc/nginx/nginx.conf
        when: ansible_distribution_major_version == "7"
        notify: restart service

    - name:copy template for centos6
      template: src=nginx.conf6.j2 dest=/etc/nginx/nginx.conf
        when: ansible_distribution_major_version == "6"
        notify: restart service

    - name: start service
      service: name=nginx state=started enabled=yes

  handlers:
  - name: restart service
    service: name=nginx state=restarted

#测试执行:
[root@centos130 ansible]# ansible-playbook -i hosts -C testwhen.yml

猜你喜欢

转载自blog.51cto.com/8355320/2474181