自动化运维工具——YAML详解

YAML介绍

YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。

YAML Ain’t Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。其特性:

YAML的可读性好
YAML和脚本语言的交互性好
YAML使用实现语言的数据类型
YAML有一个一致的信息模型
YAML易于实现
YAML可以基于流来处理
YAML表达能力强,扩展性好

YAML语法

YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-“来代表,Map里的键值对用”:"分隔。下面是一个示例。YAML是用键值对和缩进来表示的。

基本语法

1、大小写敏感
2、使用缩进表示层级关系
3、缩进时不允许使用Tab键,只能使用空格
4、缩进的空格数且不重要,只要相同层级的元素左侧对其即可

YAML支持的数据结构:

1.对象:键值对的集合,又称为映射(mapping)/哈希(hashes)/字典(dictionary)
例如:

name:Example Developer
         键值
⒉数组:一组按次序排列的值,又称为序列(sequence)/列表(list)例如:-Apple
         -Orange
3.纯量:单个的、不可再分的值
例如:number: 12.30
             sure: true


yaml示例:
name:zhangsan
age:20
name:lisi
age:22
people:
-name:zhangsan
  age:20
  -name:lisiage:22

playbook的组成

Ansible的脚本—playbook剧本
通过task调用ansible的模板将多个play组织在一个
playbook中运行。playbooks本身由以下各部分组成
(1)Tasks:任务,即调用模块完成的某操作;
(2) Variables:变量
(3) Templates:模板
(4)Handlers:处理器,当某条件满足时,触发执行的操作;
(5) Roles:角色。

三要素

剧本的三要素
1、演出的场地
2、演员要到位
3、故事情节

playbook的三要素
1、场地—主机组hosts
2、演员—授权执行的用户 remote user
3、故事情节----执行的任务tasks (调用的是各种ansible模块)

playbook 语法

执行一个playbook

ansible-playbook [yaml文件名]
例如:ansible-playbook ping.yml
参数:-k(-ask-pass)用来交互输入ssh密码
        -K(-ask-become-pass)用来交互输入sudo密码
         -u指定用户
补充命令:
ansible-playbook nginx.yaml --syntax-check #检查yaml文件的语法是否正确
 ansible-playbook nginx.yaml --list-task #检查tasks任务
ansible-playbook nginx.yaml --list-hosts #检查生效的主机
ansible-playbook nginx.yaml --start-at-task='Copy Nginx.conf’ #指定从某个task开始运行

hosts和users介绍

hosts: webserver #指定主机组,可以是一个或多个组。
remote user: root #指定远程主机执行的用户名

[root@server1 ~]# vim ping.yaml  
- hosts: all  #定义主机组
  remote_user: root   #指定root用户 全局变量
  tasks:
   - name: test connection
     ping:
[root@server1 ~]# ansible-playbook ping.yaml --syntax-check  //检查语法

playbook: ping.yaml
[root@server1 ~]# ansible-playbook ping.yaml   //执行

PLAY [all] ************************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]
ok: [192.168.188.20]

TASK [test connection] ************************************************************
ok: [192.168.188.20]
ok: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.188.30             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

指定远程主机sudo切换用户

[root@server1 ~]# vim sudo.yaml
- hosts: webservers
  remote_user: root
  become: yes  //切换用户执行
  become_user: lisi  //指定sudo用户为lisi
  tasks:
   - name: copy text
     copy: src=/etc/fstab dest=/home/lisi/fstab.bak
[root@server1 ~]# ansible-playbook sudo.yaml --syntax-check  //查看语法

playbook: sudo.yaml
[root@server1 ~]# ansible-playbook sudo.yaml   //执行

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
[WARNING]: Module remote_tmp /home/lisi/.ansible/tmp did not exist and was created
with a mode of 0700, this may cause issues when running as another user. To avoid
this, create the remote_tmp dir with the correct permissions manually
ok: [192.168.188.20]

TASK [copy text] ******************************************************************
changed: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

去node1验证
[root@server2 ~]# id lisi
uid=1001(lisi) gid=1001(lisi)=1001(lisi)
[root@server2 ~]# cd /home/lisi/
[root@server2 lisi]# ls
[root@server2 lisi]# ls
fstab.bak

小实验 练练手

实验要求:

安装Apcha
开启Apcha
关闭防火墙
给Apcha主页换成this is Apche

[root@server1 ~]# vim Apcha.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: yum httpd
     yum: name=httpd
   - name: start httpd
     service: name=httpd state=started
   - name: stop firewalld
     service: name=firewalld state=stopped
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[root@server1 ~]# ansible-playbook Apcha.yaml --syntax-check

playbook: Apcha.yaml

[root@server1 ~]# ansible-playbook Apcha.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [yum httpd] ******************************************************************
changed: [192.168.188.30]

TASK [start httpd] ****************************************************************
changed: [192.168.188.30]

TASK [stop firewalld] *************************************************************
ok: [192.168.188.30]

TASK [index.html] *****************************************************************
changed: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.30             : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


node2 验证

[root@server3 ~]# rpm -q httpd
httpd-2.4.6-67.el7.centos.x86_64
[root@server3 ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since 四 2021-01-14 10:07:20 CST; 25s ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 42301 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"

[root@server3 ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

在这里插入图片描述

如果一个hosts执行task失败,整个task就会回滚,请修正playbook错误,然后重新执行

[root@server1 ~]# vim Apcha.yaml
- hosts: webservers
  remote_user: root
  tasks:
   - name: yum httpd
     yum: name=httpd
   - name: start httpd
     service: name=httpd state=started
   - name: stop firewalld
     service: name=firewall state=stopped   //firewalld 少d
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[root@server1 ~]# ansible-playbook Apcha.yaml --syntax-check  //语法正确

playbook: Apcha.yaml

[root@server1 ~]# ansible-playbook Apcha.yaml   //执行  到stop firewalld显示错误  后面不执行

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
changed: [192.168.188.20]

TASK [start httpd] ****************************************************************
changed: [192.168.188.20]

TASK [stop firewalld] *************************************************************
fatal: [192.168.188.20]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}

PLAY RECAP ************************************************************************
192.168.188.20             : ok=3    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   


node1 验证
[root@server2 lisi]# id httpd
id: httpd: no such user
[root@server2 lisi]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since 四 2021-01-14 10:48:41 CST; 1min 18s ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 42757 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"

[root@server2 lisi]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: active (running) since 四 2021-01-14 10:50:29 CST; 16s ago
     Docs: man:firewalld(1)
 Main PID: 42868 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─42868 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

在stop firewalld 下面添加ignore_errors: True(忽略错误,强制返回成功)

[root@server1 ~]# vim Apcha.yaml
- hosts: webservers
  remote_user: root
  tasks:
   - name: yum httpd
     yum: name=httpd
   - name: start httpd
     service: name=httpd state=started
   - name: stop firewalld
     service: name=firewall state=stopped
     ignore_errors: True
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html
[root@server1 ~]# ansible-playbook Apcha.yaml --syntax-check

playbook: Apcha.yaml

[root@server1 ~]# ansible-playbook Apcha.yaml 

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
ok: [192.168.188.20]

TASK [start httpd] ****************************************************************
ok: [192.168.188.20]

TASK [stop firewalld] *************************************************************
fatal: [192.168.188.20]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}
...ignoring

TASK [index.html] *****************************************************************   
changed: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1    //有一条被忽略

Handlers介绍

Handlers也是一些task的列表,和一般的task并没有什么区别。
是由通知者进行的notify,如果没有被notify,则Handlers不会执行,假如被notify了,则Handlers被执行
不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次

1、在playbook直接使用变量

[root@server1 ~]# vim Apcha.yaml 
- hosts: webservers
  remote_user: root
  vars:
   - abc: httpd   //把httpd变成abc
  tasks:
   - name: yum httpd
     yum: name={{abc}}
   - name: start httpd
     service: name={{abc}} state=started
   - name: stop firewalld
     service: name=firewalld state=stopped
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[root@server1 ~]# ansible-playbook Apcha.yaml --syntax-check 

playbook: Apcha.yaml
[root@server1 ~]# ansible-playbook Apcha.yaml 

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
changed: [192.168.188.20]

TASK [start httpd] ****************************************************************
changed: [192.168.188.20]

TASK [stop firewalld] *************************************************************
ok: [192.168.188.20]

TASK [index.html] *****************************************************************
ok: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


2、通过ansible命令传递

[root@server1 ~]# vim Apcha.yaml 
- hosts: webservers
  remote_user: root
  vars:
   - abc:    //空的  在外面用命令设置
  tasks:
   - name: yum httpd
     yum: name={{abc}}
   - name: start httpd
     service: name={{abc}} state=started
   - name: stop firewalld
     service: name=firewalld state=stopped
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[root@server1 ~]# ansible-playbook Apcha.yaml -e 'abc=httpd'  

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
ok: [192.168.188.20]

TASK [start httpd] ****************************************************************
ok: [192.168.188.20]

TASK [stop firewalld] *************************************************************
ok: [192.168.188.20]

TASK [index.html] *****************************************************************
ok: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

3、直接在yaml中定义变量

[root@server1 ~]# vim test.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: copy file
     copy: content="{{ansible_all_ipv4_addresses}}" dest=/opt/addr.txt

[root@server1 ~]# ansible-playbook test.yaml --syntax-check

playbook: test.yaml
[root@server1 ~]# ansible-playbook test.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [copy file] ******************************************************************
changed: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

到node2 验证
[root@server3 ~]# cd /opt/
[root@server3 opt]# ls
addr.txt  rh
[root@server3 opt]# cat addr.txt 
["192.168.122.1", "192.168.188.30"][root@server3 opt]# 

4、直接引用主机变量

[root@server1 ~]# vim /etc/ansible/hosts 
[webservers]
192.168.188.20
[mysql]
192.168.188.30  num="123456"

在这里插入图片描述

[root@server1 ~]# vim test.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: copy file
     copy: content="{{ansible_all_ipv4_addresses}},{{num}}" dest=/opt/num.txt

[root@server1 ~]# ansible-playbook test.yaml --syntax-check

playbook: test.yaml
[root@server1 ~]# ansible-playbook test.yaml

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [copy file] ******************************************************************
changed: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


去node2验证
[root@server3 opt]# ls
addr.txt  num.txt  rh
[root@server3 opt]# cat num.txt 
([u'192.168.122.1', u'192.168.188.30'], 123456)[root@server3 opt]# 

条件测试

[root@server1 ~]# vim when.yaml

- hosts: mysql
  remote_user: root
  tasks:
   - name: "shutdown CentOS"
     command: /sbin/shutdown -h now
     when: ansible_distribution == "CentOS"   //判断系统CentOS



[root@server1 ~]# ansible-playbook when.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [shutdown CentOS] ************************************************************
fatal: [192.168.188.30]: FAILED! => {"msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.188.30 port 22: Connection refused"}

PLAY RECAP ************************************************************************
192.168.188.30             : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

多条件判断

[root@server1 ~]# vim when.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: "shut down CentOS 7 systems"
     command: /sbin/shutdown -r now
     when:
      - ansible_distribution == "CentOS"   //判断CentOS系统
      - ansible_distribution_major_version == "7"   //7版本


[root@server1 ~]# ansible-playbook when.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [shut down CentOS 7 systems] *************************************************
fatal: [192.168.188.30]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Shared connection to 192.168.188.30 closed.", "unreachable": true}

PLAY RECAP ************************************************************************
192.168.188.30             : ok=1    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   

组条件判断

[root@server1 ~]# vim when.yaml 
- hosts: mysql
  remote_user: root
  tasks:
   - name: "shut down CentOS 7 systems"
     command: /sbin/shutdown -r now
     when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or (ansible_distribution == "Debian " and ansible_distribution_major_version == "7")  //判断你的系统是CentOS 版本是6 或者系统是Debian 7

[root@server1 ~]# ansible-playbook when.yaml --syntax-check

playbook: when.yaml
[root@server1 ~]# ansible-playbook when.yaml 

迭代

当有需要重复性执行的任务时,可以使用迭代机制

[root@server1 ~]# vim yum.yaml
- hosts: all
  remote_user: root
  tasks:
   - name: install httpd tomcat
     yum: name={{item}}
     with_items:
      - httpd
      - tomcat
[root@server1 ~]# ansible-playbook yum.yaml --syntax-check

playbook: yum.yaml
[root@server1 ~]# ansible-playbook yum.yaml 
LAY [all] ************************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]
ok: [192.168.188.20]

TASK [install httpd tomcat] *******************************************************
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via 
squash_actions is deprecated. Instead of using a loop to supply multiple items and
 specifying `name: "{{item}}"`, please use `name: ['httpd', 'tomcat']` and remove 
the loop. This feature will be removed in version 2.11. Deprecation warnings can 
be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via 
squash_actions is deprecated. Instead of using a loop to supply multiple items and
 specifying `name: "{{item}}"`, please use `name: ['httpd', 'tomcat']` and remove 
the loop. This feature will be removed in version 2.11. Deprecation warnings can 
be disabled by setting deprecation_warnings=False in ansible.cfg.
changed: [192.168.188.20] => (item=[u'httpd', u'tomcat'])
changed: [192.168.188.30] => (item=[u'httpd', u'tomcat'])

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@server2 ~]# rpm -q httpd
httpd-2.4.6-67.el7.centos.x86_64
[root@server2 ~]# rpm -q tomcat
tomcat-7.0.76-2.el7.noarch

[root@server3 ~]# rpm -q httpd
httpd-2.4.6-67.el7.centos.x86_64
[root@server3 ~]# rpm -q tomcat
tomcat-7.0.76-2.el7.noarch


也可以自己定义

[root@server1 ~]# vim user.yaml

- hosts: all
  remote_user: root
  tasks:
  - name: "users"
    user: name={{ item.name }} state=present groups={{ item.groups }}
    with_items:
      - { name: 'song', groups: 'root' }
      - { name: 'shufeng', groups: 'wheel' }
[root@server1 ~]# ansible-playbook user.yaml --syntax-check

playbook: user.yaml
[root@server1 ~]# ansible-playbook user.yaml

PLAY [all] ************************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]
ok: [192.168.188.30]

TASK [users] **********************************************************************
changed: [192.168.188.30] => (item={u'name': u'song', u'groups': u'root'})
changed: [192.168.188.20] => (item={u'name': u'song', u'groups': u'root'})
changed: [192.168.188.30] => (item={u'name': u'shufeng', u'groups': u'wheel'})
changed: [192.168.188.20] => (item={u'name': u'shufeng', u'groups': u'wheel'})

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   




[root@server2 ~]# id song
uid=1002(song) gid=1002(song)=1002(song),0(root)
[root@server2 ~]# id shufeng
uid=1003(shufeng) gid=1003(shufeng)=1003(shufeng),10(wheel)



[root@server3 ~]# id song
uid=1003(song) gid=1003(song)=1003(song),0(root)
[root@server3 ~]# id shufeng
uid=1004(shufeng) gid=1004(shufeng)=1004(shufeng),10(wheel)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值