playbook是剧本的意思,通过 task 调用 ansible 的模块将多个 play 组织在一 个playbook中运行。
playbook各部分组成:
Tasks: 任务,即调用模块完成的某操作
Variables: 变量
emplates: 模板
Handlers: 处理器,当某条件满足时,触发执行的操作
Roles: 角色
playbook yaml语法是换行空两格,-和:后必须空一格
playbook由YMAL语言编写,YAML是一种非标记语言。是用来写配置文件的语言,非常简洁合强大
YAML语法和其他语言类似,也可以表达散列表、标量等数据结构
结构通过空格来展示
序列里配置项通过 - 来表示
Map里的键值用:来分隔
YAML的扩展名为yaml
Playbooks 是 Ansible的配置、部署、编排语言,他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合。
Playbooks 与 ad-hoc相比,是一种完全不同的运用ansible的方式,是非常之强大的。
简单来说,playbooks是一种简单的配置管理系统与多机器部署系统的基础,与现有的其他系统有不同之处,且非常适合于复杂应用的部署。
playbook是ansible用于配置,部署,和管理被控节点的剧本。
通过playbook的详细描述,执行其中的一系列tasks,可以让远端主机达到预期的状态。playbook就像Ansible控制器给被控节点列出的的一系列to-do-list,而被控节点必须要完成。
也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
(1)执行一些简单的任务,使用ad-hoc命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的ad-hoc命令是不适合的,这时最好使用playbook。
(2)就像执行shell命令与写shell脚本一样,也可以理解为批处理任务,不过playbook有自己的语法格式。
(3)使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用Ansible的过程中,你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成playbook,之后管理服务器会变得十分简单。
大小写敏感
使用缩进表示层级关系
缩进时不允许使用tab键、只允许使用空格
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
hosts | 定义接节点,可以是组 |
---|---|
remote_user | 是你以什么身份进行登录 |
tasks | 是你的任务 |
become:yes | 表示切换用户 |
become_user:mysql | 表示切换到mysql用户,配合上一条使用 |
-name: | 为下面执行的操作起名 |
对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes)/ 字典(dictionary)
数组:一组按次序排列的值,又称为序列(sequence)/ 列表(list)
纯量:单个的、不可再分的值
Inventory是Ansible管理主机信息的配置文件,相当于系统HOSTS文件的功能,默认存放在/etc/ansible/hosts
基本命令介绍
ansible-playbook xxx.yaml --syntax-check #检查yaml文件的语法是否正确
ansible-playbook xxx.yaml --list-task #检查tasks任务
ansible-playbook xxx.yaml --list-hosts #检查生效的主机
ansible-playbook xxx.yaml --start-at-task='xxx' #指定从某个task开始运行
- hosts: webserver #指定主机组,可以是一个或多个组
remote_user: root #指定远程主机执行的用户名
参数 | 说明 |
---|---|
-k(-ask-pass) | 用来交互输入ssh密码 |
-K(-ask-become-pass) | 用来交互输入sudo密码 |
-u | 指定用户 |
-e | 引入变量值 |
[root@Ansible opt]#vim test1.yaml
--- #yaml文件以---开头,以表明这是一个yaml文件,可省略
- name: first play #定义一个play的名称,可省略
gather_facts: false #设置不进行facts信息收集,这可以加快执行速度,可省略
hosts: webservers #指定要执行任务的被管理主机组,如多个主机组用冒号分隔
remote_user: root #指定被管理主机上执行任务的用户
tasks: #定义任务列表,任务列表中的各任务按次序逐个在hosts中指定的主机上执行
- name: test connection #自定义任务名称
ping: #使用 module: [options] 格式来定义一个任务
- name: disable selinux
command: '/sbin/setenforce 0' #command模块和shell模块无需使用key=value格式
ignore_errors: True #如执行命令的返回值不为0,就会报错,tasks停止,可使用ignore_errors忽略失败的任务
- name: disable firewalld
service: name=firewalld state=stopped enabled=no #使用 module: options 格式来定义任务,option使用key=value格式
- name: install httpd
yum: name=httpd state=latest
- name: install configuration httpd
copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf #这里需要一个事先准备好的/opt/httpd.conf文件
notify: "restart httpd" #如以上操作后为changed的状态时,会通过notify指定的名称触发对应名称的handlers操作
- name: start httpd service
service: enabled=true name=httpd state=started
handlers: #handlers中定义的就是任务,此处handlers中的任务使用的是service模块
- name: restart httpd #notify和handlers中任务的名称必须一致
service: name=httpd state=restarted
[root@Ansible opt]#ansible-playbook test1.yaml 运行playbook
Play的主体部分是task列表,task列表中的各任务按次序逐个在hosts中指定的主机上执行,即在所有主机上完成第一个任务后再开始第二个任务。
在运行playbook时(从上到下执行),如果一个host执行task失败,整个tasks都会回滚,请修正playbook 中的错误,然后重新执行即可。
Task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量,模块执行时幂等的,这意味着多次执行是安全的,因为其结果一致。
每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个task的。如果没有定义name,‘action’的值将会用作输出信息中标记特定的task。
定义一个task,常见的格式:”module: options” 例如:yum: name=httpd
ansible的自带模块中,command模块和shell模块无需使用key=value格式
[root@Ansible opt]#vim error.yaml
- hosts: webservers
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@Ansible opt]#ansible-playbook error.yaml
[root@Ansible opt]#vim when.yaml
- hosts: webservers
remote_user: root
tasks:
- name: "shutdown CentOS"
command: /sbin/shutdown -h now
when: ansible_distribution == "CentOS"
[root@Ansible opt]#ansible-playbook when.yaml
当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句指明迭代的元素列表即可。
[root@Ansible opt]#vim test3.yaml
---
- name: play1
hosts: dbservers
gather_facts: false
tasks:
- name: create directories
file:
path: "{{item}}"
state: directory
with_items: #等同于 loop:
- /tmp/test1
- /tmp/test2
- name: add users
user: name={{item.name}} state=present groups={{item.groups}}
with_items:
- name: test1
groups: wheel
- name: test2
groups: root
[root@Ansible opt]#ansible-playbook test3.yaml
[root@Ansible opt]#vim test4.yaml
---
- name: test1
hosts: webservers
gather_facts: false
tasks:
- name: create directories
file:
path: "{{item}}"
state: directory
#路径调用变量item,变量值为下面的with_items的内容,一次执行一个有几个值执行几次,state为创建类型为目录
with_items:
- /tmp/test1
- /tmp/test2
- name: create file
file:
path: "{{item}}"
state: touch
#路径调用变量item,变量值为下面的with_items的内容,一次执行一个有几个值执行几次,state为创建类型为文件
with_items:
- /tmp/test1/zz.txt
- /tmp/test2/zt.txt
[root@Ansible opt]#ansible-playbook test4.yaml
先准备一个以 .j2 为后缀的 template 模板文件,设置引用的变量,cp /etc/httpd/conf/httpd.conf /opt/httpd.conf.j2
[root@Ansible opt]#vim httpd.conf.j2
Listen {{http_port}} #42行,修改
ServerName {{server_name}} #95行,修改
DocumentRoot "{{root_dir}}" #119行,修改
#修改完保存退出
修改主机清单文件,使用主机变量定义一个变量名相同,而值不同的变量
[root@Ansible opt]#vim /etc/ansible/hosts
[webservers]
192.168.10.136 http_port=192.168.10.136:80 server_name=www.zzt.com:80 root_dir=/var/www/html
[dbservers]
192.168.10.137 http_port=192.168.10.137:80 server_name=www.zz.com:80 root_dir=/var/www/html
#修改完保存退出
[root@localhost opt]#vim /etc/hosts
192.168.10.136 www.zzt.com
192.168.10.137 www.zz.com
[root@Ansible opt]#vim httpd.yaml
---
- hosts: all
remote_user: root
gather_facts: false
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd
yum: name={{package}} state=latest
- name: con test
template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd
service: name={{service}} state=started
handlers:
- name: restart httpd
service: name={{service}} state=restarted
[root@Ansible opt]#ansible-playbook httpd.yaml
[root@Ansible opt]#vim test01.yaml
---
- hosts: webservers
remote_user: root
gather_facts: false
tasks:
- name: copy hosts
copy: src=/etc/hosts dest=/opt/hosts
tags:
- tags1
- name: touch file
file: path=/opt/testhost state=touch
tags:
- always
[root@Ansible opt]#ansible-playbook test01.yaml
Ansible为了层次化、结构化的组织Playbook,使用角色roles可以根据层次结构自动装载变量文件、task以及handlers等。
roles 内各目录含义解释
●files
用来存放由 copy 模块或 script 模块调用的文件。
●templates
用来存放 jinjia2 模板,template 模块会自动在此目录中寻找 jinjia2 模板文件。
●tasks
此目录应当包含一个 main.yml 文件,用于定义此角色的任务列表,此文件可以使用 include 包含其它的位于此目录的 task 文件。
●handlers
此目录应当包含一个 main.yml 文件,用于定义此角色中触发条件时执行的动作。
●vars
此目录应当包含一个 main.yml 文件,用于定义此角色用到的变量。
●defaults
此目录应当包含一个 main.yml 文件,用于为当前角色设定默认变量。
●meta
此目录应当包含一个 main.yml 文件,用于定义此角色的特殊设定及其依赖关系。
[root@Ansible ~]#mkdir /etc/ansible/roles/ -p
[root@Ansible ~]#mkdir /etc/ansible/group_vars/ -p
[root@Ansible ~]#mkdir /etc/ansible/group_vars/all
[root@Ansible ~]#mkdir /etc/ansible/roles/httpd
[root@Ansible ~]#mkdir /etc/ansible/roles/mysql
files、handlers、tasks、templates、meta、defaults和vars目录,用不到的目录可以创建为空目录,也可以不创建
[root@Ansible ~]#mkdir /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta}
[root@Ansible ~]#mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta}
[root@Ansible ~]#
千万不能自定义文件名
[root@Ansible ~]#touch /etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yml
[root@Ansible ~]#touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yml
[root@Ansible ~]#
[root@Ansible ~]#vim /etc/ansible/site.yml
---
- hosts: webservers
remote_user: root
roles:
- httpd
- hosts: dbservers
remote_user: root
roles:
- mysql
[root@Ansible ~]#cd /etc/ansible/
[root@Ansible ansible]#ansible-playbook site.yml