自动化工具ansible-playbook篇【一】

前言

YAML:是一种非标记语言。是用来写配置文件的语言,非常简洁和强大。
YAML语法和其他语言类似,也可以表达散列表、标量等数据结构。
结构通过空格来展示;序列里配置项通过-来代表;Map里键值用:来分隔;YAML的扩展名为yaml

基本语法规则:
1.大小写敏感
2.使用缩进表示层级关系
3.缩进时不允许使用Tab键,只允许使用空格。
4.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

YAML支持的数据结构:
1.对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
例如:name:Example Developer
键 值
2.数组:一组按次序排列的值,又称为序列(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:lisi
      age:22

实例二

[root@shanan opt]# vim test.yml

- hosts: tests      //被执行的主机组
  vars:   // 变量
    http_port: 80
    max_clients: 200
  user: root
  tasks:  // 任务
  - name: ensure apache is at the latest version     //输出的注释,方便确认执行到哪一步
    yum: pkg=httpd state=latest                  // 执行的模块 yum 以及任务    键值对形式  格式
  - name: write the apache config file       // 任务可以叠加
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

检查逻辑有无错误

[root@shanan opt]# ansible-playbook test.yml --syntax-check

playbook: test.yml

[root@shanan opt]# ansible-playbook test.yml  --list-task

playbook: test.yml

  play #1 (tests): tests	TAGS: []
    tasks:
      ensure apache is at the latest version	TAGS: []
      write the apache config file	TAGS: []
      ensure apache is running	TAGS: []
[root@shanan opt]# ansible-playbook test.yml  --list-hosts

playbook: test.yml

  play #1 (tests): tests	TAGS: []
    pattern: [u'tests']
    hosts (2):
      192.168.100.11
      192.168.100.12

实例三 (常用的命令)

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

备注: 若需要更新。可以直接修改playbook,重新执行即可,会自动跳过已经执行过的步骤。
在目标主机查看结果:

hosts和users介绍

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

编写yml

---     //开始
- hosts: test3
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: lisi
...   //结尾
  

测试正常

[root@shanan opt]# ansible-playbook user.yml --syntax-check

playbook: user.yml
[root@shanan opt]# ansible-playbook user.yml -k
SSH password:

PLAY [test3] **************************************************************************

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

TASK [test connection] ****************************************************************
ok: [192.168.100.10]

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

修改参数,继续测试

- hosts: test3
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: lisi
    - name: touch the books, name is test.txt
      copy: content="this is test" dest=/opt/test.txt  mode=644
      remote_user: lisi

测试:

[root@shanan opt]# ansible-playbook user.yml -k
SSH password:

PLAY [test3] **************************************************************************

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

TASK [test connection] ****************************************************************
ok: [192.168.100.10]

TASK [touch the books, name is test.txt] **********************************************
changed: [192.168.100.10]

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

[root@shanan opt]# ansible test3 -a 'cat /opt/test.txt'
192.168.100.10 | CHANGED | rc=0 >>
this is test

指定远程主机sudo切换用户:

---
- hosts: mysql
  remote_user: root            
  become: yes	               #2.6版本以后的参数,之前是sudo,意思为切换用户运行
  become_user: mysql          #指定sudo用户为mysql ,不指定默认为root
执行playbook时:ansible-playbook ping.yml -K

实例二

play中只要执行命令的返回值不为0,就会报错,tasks停止
修改如下,强制跳过错误,返回成功

 
- hosts: test3
  remote_user: root
  tasks:
   - name: disable selinux
     command: '/sbin/setenforce 0'
   - name: make sure apache is running
     service: name=httpd state=started


[root@shanan opt]# ansible-playbook test3.yml --syntax-check

playbook: test3.yml

[root@shanan opt]# ansible-playbook test3.yml

PLAY [test3] **************************************************************************

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

TASK [disable selinux] ****************************************************************
fatal: [192.168.100.10]: FAILED! => {"changed": true, "cmd": ["/sbin/setenforce", "0"], "delta": "0:00:00.002628", "end": "2021-01-02 11:30:55.529401", "msg": "non-zero return code", "rc": 1, "start": "2021-01-02 11:30:55.526773", "stderr": "/sbin/setenforce: SELinux is disabled", "stderr_lines": ["/sbin/setenforce: SELinux is disabled"], "stdout": "", "stdout_lines": []}

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

play中只要执行命令的返回值不为0,就会报错,tasks停止
修改如下,强制跳过错误,返回成功

- hosts: test3
  remote_user: root
  tasks:
   - name: disable selinux
     command: '/sbin/setenforce 0'
     ignore_errors: True
   - name: make sure apache is running
     service: name=httpd state=started
~

此时发现可以正常执行下面的语句了

[root@shanan opt]# ansible-playbook test3.yml --syntax-check

playbook: test3.yml
[root@shanan opt]# ansible-playbook test3.yml

PLAY [test3] **************************************************************************

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

TASK [disable selinux] ****************************************************************
fatal: [192.168.100.10]: FAILED! => {"changed": true, "cmd": ["/sbin/setenforce", "0"], "delta": "0:00:00.002648", "end": "2021-01-02 11:34:00.752277", "msg": "non-zero return code", "rc": 1, "start": "2021-01-02 11:34:00.749629", "stderr": "/sbin/setenforce: SELinux is disabled", "stderr_lines": ["/sbin/setenforce: SELinux is disabled"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [make sure apache is running] ****************************************************
ok: [192.168.100.10]

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

下面针对不同的目标主机执行不同的任务

- hosts: test2
  remote_user: root
  tasks:
   - name: create nginx group
     group: name=nginx system=yes gid=208
   - name: create nginx user
     user: name=nginx uid=208 group=nginx system=yes
- hosts: test3
  remote_user: root
  tasks:
   - name: copy file to test3
     copy: src=/etc/inittab dest=/opt/inittab.back

执行结果如下:

[root@shanan opt]# ansible-playbook  test4.yml --syntax-check

playbook: test4.yml
[root@shanan opt]# ansible-playbook  test4.yml

PLAY [test2] **************************************************************************

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

TASK [create nginx group] *************************************************************
changed: [192.168.100.12]

TASK [create nginx user] **************************************************************
changed: [192.168.100.12]

PLAY [test3] **************************************************************************

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

TASK [copy file to test3] *************************************************************
changed: [192.168.100.10]

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

验证如下:
[root@shanan opt]# ansible test3 -a 'ls /opt'
192.168.100.10 | CHANGED | rc=0 >>
inittab.back
rh
test.txt

Handlers介绍

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

举例:

- hosts: test3
  remote_user: root
  tasks:
   - name: install httpd package
     yum: name=httpd state=latest
   - name: install configuration file for httpd
     copy: src=/srv/httpd.j2 dest=/etc/httpd/conf/httpd.conf
     notify:
      restart httpd
   - name: start httpd service
     service: enabled=true name=httpd state=started
  handlers:
   - name: restart httpd
     service: name=httpd state=restarted

[root@shanan opt]# ansible-playbook test5.yml --syntax-check
playbook: test5.yml

执行

[root@shanan opt]# ansible-playbook test5.yml

PLAY [test3] **************************************************************************

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

TASK [install httpd package] **********************************************************
ok: [192.168.100.10]

TASK [install configuration file for httpd] *******************************************
ok: [192.168.100.10]

TASK [start httpd service] ************************************************************
changed: [192.168.100.10]

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

也可以使用变量

- hosts: test3
  remote_user: root   //root也可以换成变量使用 name={{test}}  ,执行时加  -e test="user1" 即可引入外部变量       
  vars:
  - package: httpd
  - service: httpd
  tasks:
   - name: install httpd package
     yum: name={{package}} state=latest
   - name: install configuration file for httpd
     copy: src=/srv/httpd.j2 dest=/etc/httpd/conf/httpd.conf
     notify:
       restart httpd
   - name: start httpd service
     service: enabled=true name={{service}} state=started
  handlers:
   - name: restart httpd
     service: name={{service}} state=restarted

执行

[root@shanan opt]# ansible-playbook test6.yml --syntax-check

playbook: test6.yml
[root@shanan opt]# ansible-playbook test6.yml

PLAY [test3] **************************************************************************

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

TASK [install httpd package] **********************************************************
changed: [192.168.100.10]

TASK [install configuration file for httpd] *******************************************
changed: [192.168.100.10]

TASK [start httpd service] ************************************************************
changed: [192.168.100.10]

RUNNING HANDLER [restart httpd] *******************************************************
changed: [192.168.100.10]

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

playbook使用变量的方法:

1.通过ansible命令传递

例如:编辑如下yaml
vi a.yml
---
- hosts: test3
  remote_user: root
  vars:
  - user:
  tasks:
  - name: add new user
    user: name={{user}}
然后执行命令: ansible-playbook a.yml -e "user=testvar"
可以执行命令查看:ansible mysql -m command -a 'tail /etc/passwd'


[root@shanan opt]#  ansible-playbook test7.yml -e "user=testvar"

PLAY [test3] **************************************************************************

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

TASK [add new user] *******************************************************************
changed: [192.168.100.10]

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

[root@shanan opt]# ansible test3 -a 'tail /etc/passwd'
192.168.100.10 | CHANGED | rc=0 >>
saned:x:989:983:SANE scanner daemon user:/usr/share/sane:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
gnome-initial-setup:x:988:982::/run/gnome-initial-setup/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
lisi:x:306:306::/home/lisi:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
testvar:x:1000:1000::/home/testvar:/bin/bash

发现外部变量已经导入进去

2.直接在yaml中定义变量—如上handlers示例

3.直接引用一些变量

如:引用ansible的固定变量

vi test8.yml
---
- hosts: test3
  remote_user: root
  tasks:
   - name: copy file
     copy: content="{{ansible_all_ipv4_addresses}}" dest=/opt/vars.txt
执行命令:ansible-playbook test.yml
[root@shanan opt]# vi test8.yml
[root@shanan opt]# ansible-playbook test8.yml --syntax-check

playbook: test8.yml
[root@shanan opt]# ansible-playbook test8.yml

PLAY [test3] **************************************************************************

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

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

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

去目标主机上查看vars.txt文件内容

[root@shanan opt]# ansible test3 -a 'cat /opt/vars.txt'
192.168.100.10 | CHANGED | rc=0 >>
["192.168.100.10", "192.168.122.1"]

再如:引用主机变量

vi /etc/ansible/hosts
在test3组的主机后面添加如下

  #定义testvar变量的值为100.10
vi test.yml      #添加{{testvar}}主机变量
---
- hosts: mysql
  remote_user: root
  tasks:
   - name: copy file
     copy: content="{{ansible_all_ipv4_addresses}},{{testvar}}" dest=/opt/vars.txt
执行命令:ansible-playbook test.yml

去目标主机上查看vars.txt文件内容,发现变量成功导入
[root@shanan opt]# ansible-playbook test9.yml --syntax-check

playbook: test9.yml
[root@shanan opt]# ansible-playbook test9.yml

PLAY [test3] **************************************************************************

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

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

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

[root@shanan opt]# ansible test3 -a 'cat /opt/vars.txt'
192.168.100.10 | CHANGED | rc=0 >>
([u'192.168.100.10', u'192.168.122.1'], 100.888)

--------条件测试--------

如果需要根据变量、facts(setup)或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,在Playbook中条件测试使用when子句。
在task后添加when子句即可使用条件测试:when子句支持jinjia2表达式或语法,例如:

当检测主机版本为centos 时,将它关机

[root@shanan opt]# vim when.yml
- hosts: test3
  remote_user: root
  tasks:
    - name: "shutdown CentOS"
      command: /sbin/shutdown -h now
      when: ansible_distribution == "CentOS"

[root@shanan opt]# ansible-playbook when.yml

PLAY [test3] **************************************************************************

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

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

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

发现已经被关机了

多条件判断

vi when.yml
---
- hosts: test3
  remote_user: root
  tasks:
    - name: "shut down CentOS 7 systems"
      command: /sbin/shutdown -r now
      when:
        - ansible_distribution == "CentOS"
        - ansible_distribution_major_version == "7"

组条件判断

vi when.yml
---
- hosts: test3
  remote_user: root
  tasks:
    - name: "shut down CentOS 6 and Debian 7 systems"
      command: /sbin/shutdown -t now
      when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or
            (ansible_distribution == "Debian" and ansible_distribution_major_version == "7")
			
## 自定义变量进行条件测试

- hosts: test3
  vars:
    exist: "True"
  tasks:
  - name: creaet file
    command:  touch /tmp/test.txt
    when: exist=="True"
  - name: delete file
    command:  rm -rf /tmp/test.txt
    when: exist=="False"

- hosts: test3
  vars:
    exist: "False"
  tasks:
  - name: creaet file
    command:  touch /tmp/test.txt
    when: exist=="True"
  - name: delete file
    command:  rm -rf /tmp/test.txt
    when: exist=="False"

在这里插入图片描述

root@shanan opt]# vi when1.yml 
[root@shanan opt]# ansible-playbook  when1.yml  --syntax-check

playbook: when1.yml
[root@shanan opt]# ansible-playbook  when1.yml  

PLAY [test3] *******************************************************************************************************************************************

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

TASK [creaet file] *************************************************************************************************************************************
skipping: [192.168.100.10]

TASK [delete file] *************************************************************************************************************************************
[WARNING]: Consider using the file module with state=absent rather than running 'rm'.  If you need to use command because file is insufficient you can
add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [192.168.100.10]

PLAY RECAP *********************************************************************************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210120220847181.png)



# ----------迭代-------------

```go
当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句指明迭代的元素列表即可。例如:
---
- hosts: webserver
  remote_user: root
  tasks:
    - name: "Install Packages"
      yum: name={{ item }} state=latest
      with_items:
        - httpd
        - mysql-server
        - php	

也可以自己定义

- hosts: tests
  remote_user: root
  tasks:
    - name: "Add users"
      user: name={{ item.name }} state=present groups={{ item.groups }}
      with_items:
        - { name: 'test8', groups: 'wheel'}
        - { name: 'test9', groups: 'root'}
~                                             



[root@shanan opt]# !vim
vim test12.yml
[root@shanan opt]# ansible-playbook test12.yml  --syntax-check

playbook: test12.yml
[root@shanan opt]# !vim
vim test12.yml
[root@shanan opt]# ansible-playbook test12.yml 

PLAY [tests] *******************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************
ok: [192.168.100.11]
ok: [192.168.100.12]

TASK [Add users] ***************************************************************************************************************************************
changed: [192.168.100.12] => (item={u'name': u'test8', u'groups': u'wheel'})
changed: [192.168.100.11] => (item={u'name': u'test8', u'groups': u'wheel'})
changed: [192.168.100.12] => (item={u'name': u'test9', u'groups': u'root'})
changed: [192.168.100.11] => (item={u'name': u'test9', u'groups': u'root'})

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

[root@shanan opt]# 

验证:

[root@shanan opt]# ansible tests -m shell -a 'id test8'
192.168.100.12 | CHANGED | rc=0 >>
uid=1001(test8) gid=1001(test8) groups=1001(test8),10(wheel)
192.168.100.11 | CHANGED | rc=0 >>
uid=1000(test8) gid=1000(test8) groups=1000(test8),10(wheel)
[root@shanan opt]# ansible tests -m shell -a 'id test9'
192.168.100.12 | CHANGED | rc=0 >>
uid=1002(test9) gid=1002(test9) groups=1002(test9),0(root)
192.168.100.11 | CHANGED | rc=0 >>
uid=1001(test9) gid=1001(test9) groups=1001(test9),0(root)
[root@shanan opt]# 

Ansible-playbook中普通用户切换到超级管理员root

在日常的运维工作中,编写ansible-playbook时,也许会遇到需要用root用户执行命令的情况。然而,在playbook中该咋写呢?下面开始上干货:

---
- hosts: all
  remote_user: testuser
  gather_facts: No 
  become: yes  #表示是否允许用户切换
  become_method: sudo  #表示切换用户的方式,有su/sudo/pbrun等方式,默认是sudo方式
  become_user: root  #表示要切换到哪个用户,即目标用户
  tasks:
    - name: "create a test dir"
      shell: /bin/sh -c 'mkdir -p /root/testuser' 
注意:默认在/etc/sudoers已经配置了“testuser ALL=(ALL) NOPASSWD: ALL”。

举例,巡检脚本

目的:根据不同的角色主机,执行不同的shell巡检脚本

---
- hosts: gateway    //主机组
  become: yes     //允许 sudo  切换root执行
  tasks:             //任务   
  - name: inspect gateway       //任务名
    script: gateway.sh
    ignore_errors: True     //当返回为0时,以及往下执行
    changed_when: false   //执行正常,以及返回fail , 作用:强制每次重新执行任务

- hosts: Monitor
  become: yes
  tasks:
  - name: Monitor
    script: Monitor.sh
    ignore_errors: True
    changed_when: false

- hosts: ui
  become: yes
  tasks:
  - name: inspect ui
    script: ui.sh {{mysqluser}} {{mysqlpass}}  //变量的使用,如脚本中含有登录mysql检查的内容
    ignore_errors: True
    changed_when: false
...

hosts的配置

在这里插入图片描述

执行

sudo ansible-playbook -i hosts test.yml
收集结果
sudo nohup  ansible -i hosts all -m shell -a " cat /text.txt  " &
vi nohup.out   即可查看结果

推荐一个好用的yml 错误检查工具–网页版

操作简单
http://www.bejson.com/validators/yaml_editor/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值