目录
一、YAML语言概述
1.YAML介绍(playbook采用YAML格式配置文件)
- YAML:是一种非标记语言。用来配置文件的语言,非常简洁和强大
- YAML语法和其他语言类似,也可以表达散列表、标量等数据结构
- 结构通过空格来展示;序列里配置项通过-来代表;Map里键值用:来分隔
- YAML的扩展名为yaml
2.YAML基本语法
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- ’#’.表示注释
3.YAML支持的数据类型
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
- 纯量(scalars):单个的、不可再分
二、Playbook剧本
1.Playbook介绍
通过task调用ansible的模块将多个play组织在一个playbook中运行。playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。
2.Playbook核心元素
- Tasks:任务,即调用模块完成的某操作
- Variables:变量
- Templates:模板
- Handlers:处理器,当某条件满足时,触发执行的操作
- Roles:角色
3.一个完整的playbook主要构成
- 1.主机组hosts
- 2.授权执行的用户remote_user
- 3.执行的任务tasks(调用的是各种ansible模块)
4.横杆的作用
短横杠(-):
表示一个整体关系,通常用于一段完整的playbook开头、定义的变量名前、单条任务的开头(任务名name前)
一个playbook脚本内可同时有多个剧本,以开头的短横杠定义为一个剧本,例:
- hosts: webservers
...
- hosts: mysql
...
若使用三个短横杠(—)独占一行,则表示以上内容为一个单独文件,以下内容为另一个单独文件,互不干扰,例:
- hosts:webservers
...
---
- hosts:mysql
...
5 playbook脚本执行
语法格式
ansible-playbook [yaml文件名]
示例
ansible-playbook httpd.yaml
参数:
-k(-ask-pass):用来交互输入ssh密码
-k(-ask-become-pass):用来交互输入sudo密码
-u:指定用户
–syntax-check:检查yaml文件的语法是否正确
–list-task:检查tasks任务
–list-hosts:检查生效的主机
–start-at-task=’ 任务名(name)’:指定从某个task开始运行
三、 hosts和users介绍
在playbook中的每一个play都可以选择在哪些服务器和以什么用户完成,hosts一行可以是一个主机组、主机、多个主机,中间以冒号分隔,可使用通配模式。其中remote_user表示执行的用户账号。
[root@ansible ~]# vivi demo.yaml
- hosts: apache #指定主机组,可以是一个或多个组。
remote_user: root #指定远程主机执行的用户名
tasks:
- name: test connection
ping:
remote_user: root
[root@ansible ~]# ansible-playbook demo.yaml -k ## 执行playbook-k(–ask-pass) 用来交互输入ssh密码
SSH password:
PLAY [apache] ************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************
ok: [192.168.10.20]
TASK [test connection] ***************************************************************************************
ok: [192.168.10.20]
PLAY RECAP ***************************************************************************************************
192.168.10.20 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
指定远程主机sudo切换
[root@ansible ~]# cat sudo.yaml
- hosts: apache
remote_user: root
become: yes #2.6版本以后的参数,之前是sudo,意思为切换用户运行
become_user: apache #指定sudo用户为apache
ansible-playbook sudo.yaml -k ## 执行playbook -k(–ask-pass) 用来交互输入ssh密码
四、tasks列表和action
1:Play的主体部分是task列表,task列表中的各任务按次序逐个在hosts中指定的主机上执行,即在所有主机上完成第一个任务后再开始第二个任务。
在运行playbook时(从上到下执行),如果一个host执行task失败,整个tasks都会回滚,请修正playbook 中的错误,然后重新执行即可。
Task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量,模块执行时幂等的,这意味着多次执行是安全的,因为其结果一致。
2:每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个task的。如果没有定义name,‘action’的值将会用作输出信息中标记特定的task。
3:定义一个task,常见的格式:”module: options” 例如:yum: name=httpd
4:ansible的自带模块中,command模块和shell模块无需使用key=value格式
[root@ansible ~]# vi http.yaml ## yum安装apache服务并为其提供一个主页
- hosts: apache
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started
- name: stop firewalld
service: name=firewalld state=stopped
- name: touch index
copy: content="this is my apache" dest=/var/www/html/index.html
[root@ansible ~]# ansible-playbook apache.yaml
PLAY [apache] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.10.20]
TASK [install httpd] ***********************************************************
changed: [192.168.10.20]
TASK [start httpd] *************************************************************
changed: [192.168.10.20]
TASK [stop firewalld] **********************************************************
ok: [192.168.10.20]
TASK [touch index] *************************************************************
ok: [192.168.10.20]
PLAY RECAP *********************************************************************
192.168.10.20 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
回滚举例:
Firewalld写为Firewall来模拟错误,验证回滚,若发生错误,将会回滚到错误发生前,和游戏中的回档类似
执行到stop Firewalld的时候会反馈报错信息,并停止下一步操作,回滚到错误发生之前,访问网页也是没有主页展示的
play中只要执行命令的返回值不为0,就会报错,tasks停止,可以添加下面
ignore_errors: True #忽略错误,强制返回成功
[root@ansible ~]# vi http.yaml
- hosts: apache
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started
- name: stop firewalld
service: name=firewall state=stoppped
ignore_errors: True #忽略错误,强制返回成功
- name: touch index
copy: content="this is my apache" dest=/var/www/html/index.html
[root@ansible ~]# ansible-playbook apache.yaml
PLAY [apache] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.10.20]
TASK [install httpd] ***********************************************************
changed: [192.168.10.20]
TASK [start httpd] *************************************************************
changed: [192.168.10.20]
TASK [stop firewalld] **********************************************************
fatal: [192.168.10.20]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}
...ignoring
TASK [touch index] *************************************************************
ok: [192.168.10.20]
PLAY RECAP *********************************************************************
192.168.10.20 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
## 成功了五个,修改了两个,跳过了一个
五、Handlers和notify介绍
- andlers也是一些task的列表,和一般的task并没有什么区别。
- 是由通知者进行的notify,如果没有被notify,则Handlers不会执行,假如被notify了,则Handlers被执行
- 不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次
[root@ansible ~]# vi http.yaml
- hosts: apache
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: install configuration file for httpd
copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: restart httpd
service: name=httpd state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
## 执行到notify的restart httpd时会先执行下面的handlers,handlers执行完了会返回notify继续执行,并且下面的handlers不会再执行了
六、引用变量
1.vars: 添加变量
[root@ansible ~]# vi http.yaml
- hosts: apache
remote_user: root
vars:
- package: httpd ## vars下方可以添加变量
- service: httpd
tasks:
- name: install httpd
yum: name={{package}} ## {{}}引用变量
- name: start httpd
service: name={{service}} enabled=true state=started
2.直接引用Ansible变量,ansible自带的固有变量
ansible_all_ipv4_addresses 获取IP
[root@ansible ~]# vi ipadress.yaml
- hosts: apache
remote_user: root
tasks:
- name: copy file
copy: content="{{ansible_all_ipv4_addresses}}" dest=/opt/ip.txt
常用ansible固定变量:
ansible_all_ipv4_addresses:ipv4地址
ansible_distribution:系统类型
ansible_distribution_major_version:系统版本
3.引用主机变量
在组的主机后面添加变量
[root@ansible ~]# vi /etc/ansible/hosts
[apache]
192.168.10.20 test="this is a test file"
[mysql]
192.168.10.30
- hosts: apache
remote_user: root
tasks:
- name: copy file
copy: content="{{test}}" dest=/opt/test.txt
[root@ansible ~]# ansible apache -a 'cat /opt/test.txt'
192.168.10.20 | CHANGED | rc=0 >>
this is a test file
4.条件语句跟变量
执行playbook的时候可以用-e 来引用变量
- hosts: apache
remote_user: root
tasks:
- name: copy file
copy: content="{{test2}}" dest=/opt/test2.txt
[root@ansible ~]# ansible-playbook ipadress.yaml -e test2="anotherone"
[root@ansible ~]# ansible apache -a 'cat /opt/test2.txt'
192.168.10.20 | CHANGED | rc=0 >>
anotherone
七、 条件判断
when的值是一个条件表达式,如果条件判断成立,这个task就执行,如果判断不成立,则task不执行
如果需要根据变量、facts(setup)或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,在Playbook中条件测试使用when子句。
1.普通条件判断
在task后添加when子句即可使用条件测试:when子句支持jinjia2表达式或语法,例如:
- hosts: apache
remote_user: root
tasks:
- name: shutdown
command: /sbin/shutdown -h now
when: ansible_distribution=="Centos"
## 当系统是Centos系统时就会执行关机指令
2.多条件判断
- hosts: apache
remote_user: root
tasks:
- name: shutdown
command: /sbin/shutdown -h now
when:
- ansible_distribution=="Centos"
- ansible_distribution_major_version=="7"
## 当系统是CentOS系统,并且版本号为7才会执行关机语句,两项都满足
3.组条件判断
- hosts: apache
remote_user: root
tasks:
- name: shutdown Centos6 Centos7
command: /sbin/shutdown -h now
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or (ansible_distribution == "CentOS" ansible_distribution_major_version == "7")
八、迭代
有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句指明迭代的元素列表即可。
1.单个需要迭代的内容
- hosts: apache
remote_user: root
tasks:
- name: install packages
yum: name={{ item }} state=latest
with_items:
- httpd
- php
## 依次安装httpd 和php这两服务
2.多个需要迭代的内容(自己定义item变量)
- hosts: webservers
remote_user: root
tasks:
- name: add user
user: name={{item.name}} uid={{item.uid}}
with_items:
- {name:'zhangsan' uid:'1001'}
- {name:'lisi' uid:'1002'}
- {name:'wangwu' uid:'1003'}
九、tags模块
在一个playbook中,如果我们只想执行某一个task或多个task时可使用tags标签,执行playbook时只执行定义tags标签的任务
示例:
只执行了copy hosts任务,copy log任务未执行
[root@ansible ~]# vi cpfile.yaml
- hosts: 192.168.20.10
remote_user: root
tasks:
- name: copy hosts
copy: src=/etc/hosts dest=/opt/hosts.bak
tags:
- only #自定义标签名
- name: copy log
copy: src=/var/log/messages dest=/opt/log.bak
ansible-playbook cpfile.yaml --tags="only" ##执行playbook,加上tags参数并指定执行的tags标签,将只执行带有此标签的任务
特定标签名:always
当tags的标签名为always时,无论执行哪一个tags时,定义为always的任务都必须被执行
[root@ansible ~]# vi cpfile.yaml
- hosts: 192.168.20.10
remote_user: root
tasks:
- name: copy hosts
copy: src=/etc/hosts dest=/opt/hosts.bak
tags:
- only #自定义标签名
- name: copy log
copy: src=/var/log/messages dest=/opt/log.bak
tags:
- always
[root@ansible ~]# ansible-playbook cpfile.yaml --tags="only"
##此时所有任务都被执行
十、roles
roles能够根据层次性结构自动装载变量文件、task以及handlers等。简单说,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中,并可以便捷的include它
在/etc/ansible/中默认存在一个空目录roles,可在里面创建各种需要装载的文件
1.roles内各目录含义
- files: 用来存放由copy模块或script模块调用的文件
- templates: 用来存放jinjia2模板,templates模块会自动在此目录中寻找jinjia2模板文件
- tasks: 此目录包含一个main.yaml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件
- handlers: 此目录包含一个main.yaml文件,用于定义此角色中触发条件时执行的动作
- vars: 此目录包含一个main.yaml文件,用于定义此角色用到的变量
- defaults: 此目录包含一个main.yaml文件,用于为当前角色设定默认变量
- meta: 此目录包含一个main.yaml文件,用于定义此角色的特殊设定及其依赖关系
角色目录: 在roles目录下的直接目录,自定义目录名,存放以上所有的功能目录
2.使用roles步骤
1.创建全局变量目录
[root@ansible ~]# mkdir -p /etc/ansible/group_vars
[root@ansible ~]# touch /etc/ansible/group_vars/all_vars #文件名自定义,用于引用,里面可设置全局变量
2.创建角色目录
[root@ansible ~]# mkdir -p /etc/ansible/roles/httpd
3.在角色目录下创建所有功能目录
[root@ansible ~]# mkdir -p /etc/ansible/roles/httpd/{file,templates,tasks,handlers,vars,defaults,meta}
4.在需要main.yaml文件的目录下创建
[root@ansible ~]# touch etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yaml
5.按需要在功能目录内添加内容
如:
tasks在main.yaml内写入任务
templates内加入jinjia2模板
…
6. 编辑playbook并调用角色
[root@ansible ~]# vi server.yaml
- hosts: webservers
remote_user: root
roles:
- httpd
- mysql #可调用多个角色目录
[root@ansible ~]# ansible-playbook server.yaml #正常执行
十一、总结
playbook是由一个或多个模块组成的,使用多个不同的模块,完成一件事情。需要熟练掌握ansible中各个模块对应的功能以及YAML的语法规则。
缩进: YAML使用一个固定的缩进风格表示层级结构,每个缩进由两个空格组成, 不能使用tabs;
冒号: 以冒号结尾的除外,其他所有冒号后面所有必须有空格;
短横线: 表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表;