文章目录
- 前言
- 具体实例
- 实例一
- 实例二
- 实例三 (常用的命令)
- hosts和users介绍
- 编写yml
- 测试正常
- 修改参数,继续测试
- 测试:
- 指定远程主机sudo切换用户:
- 实例二
- 下面针对不同的目标主机执行不同的任务
- Handlers介绍
- 举例:
- 执行
- 也可以使用变量
- 执行
- playbook使用变量的方法:
- 1.通过ansible命令传递
- 2.直接在yaml中定义变量---如上handlers示例
- 3.直接引用一些变量
- 如:引用ansible的固定变量
- 去目标主机上查看vars.txt文件内容
- 再如:引用主机变量
- --------条件测试--------
- 当检测主机版本为centos 时,将它关机
- 多条件判断
- 组条件判断
- 也可以自己定义
- Ansible-playbook中普通用户切换到超级管理员root
- 举例,巡检脚本
- 目的:根据不同的角色主机,执行不同的shell巡检脚本
- hosts的配置
- 执行
- 推荐一个好用的yml 错误检查工具--网页版
前言
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
![在这里插入图片描述]()
# ----------迭代-------------
```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/