【playbook】
playbook 特点
-
playbook 剧本是由一个或多个"play"组成的列表
-
play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的角色。Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作
-
Playbook 文件是采用YAML语言编写的
YAML 语言介绍
YAML:YAML Ain't Markup Language,即YAML不是标记语言。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)
YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者,目前很多最新的软件比较流行采用此格式的文件存放配置信息,如:ubuntu,anisble,docker,kubernetes等
YAML 官方网站:The Official YAML Web Site
ansible 官网: YAML Syntax — Ansible Documentation
YAML 语言特性
- YAML的可读性好
- YAML和脚本语言的交互性好
- YAML使用实现语言的数据类型
- YAML有一个一致的信息模型
- YAML易于实现
- YAML可以基于流来处理
- YAML表达能力强,扩展性好
YAML语法简介
-
在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件的结尾
-
次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
-
使用#号注释代码
-
缩进必须是统一的,不能空格和tab混用
-
缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
-
YAML文件内容是区别大小写的,key/value的值均需大小写敏感
-
多个key/value可同行写也可换行写,同行使用,分隔
-
key后面冒号要加一个空格 比如: key: value
-
value可是个字符串,也可是另一个列表
-
YAML文件扩展名通常为yml或yaml
支持的数据类型
- YAML 支持以下常用几种数据类型:
- 标量:单个的、不可再分的值
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
Playbook 核心组件
一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
-
Hosts 执行的远程主机列表
-
Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task
-
Variables 内置变量或自定义变量在playbook中调用
-
Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
-
Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
-
tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
tips
#查看模块 用ansible-doc 加上 模块名 可以查看模块的使用方法和例子
ansible-doc yum
host 组件
Hosts: playbook 中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用 于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com one.example.com:two.example.com 192.168.1.50
192.168.1.*
Websrvs:dbsrvs #或者,两个组的并集W
ebsrvs:&dbsrvs #与,两个组的交集
webservers:!dbsrvs #在websrvs组,但不在dbsrvs组
remote_user 组件
remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: websrvs
remote_user: root
tasks:
- name: test connection
ping:
remote_user: wang
sudo: yes
#默认sudo为root
sudo_user:wang
#sudo为wang
task列表和action组件
play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。 如果未提供name,则action的结果将用于输出。
task两种格式:
action: module arguments
#示例: action: shell wall hello
module: arguments
#示例: shell: wall hello
注意:shell和command模块后面跟命令,而非key=value
案例(yml文件)
---
# first yaml file
- hosts: web
remote_user: root
gather_facts: no #不收集系统信息,提高执行效率
tasks:
- name: test network connection
ping:
- name: excute command
command: wall "hello world!"
案例1 新建mysql用户
---
- hosts: web
tasks:
- name: create user
user: name=test uid=2000 shell=/sbin/nologin system=yes create_home=no
案例2 安装httpd并启动
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
-name: install httpd
yum: name=httpd
-name: start httpd
service: name=httpd state=started enabled=yes
案例3安装nginx并启动
---
- hosts: web
tasks:
- name: Add repository
yum_repository:
name: epel
description: EPEL YUM repo
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
gpgcheck: no
- name: install nginx
yum: name=nginx state=present
- name: config file
copy: src=/data/nginx.conf dest=/etc/nginx/nginx.conf
- name: web page
copy: src=/data/index.html dest=/usr/share/nginx/html/index.html
- name: start nginx
service: name=nginx state=started enabled=yes
案例4 停止服务,并卸载nginx
---
- hosts: web
tasks:
- name: stop nginx
service: name=nginx state=stopped
- name: remove nginx
yum: name=nginx state=absent
Handlers notify
Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
注意:
-
如果多个task通知了相同的handlers, 此handlers仅会在所有tasks结束后运行一 次。
-
只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
-
handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handler跳过执行,可以使用force_handlers: yes 强制执行handler
例子:
---
- hosts: web
gather_facts: no
tasks:
- name: add group
group: name=nginx state=present
- name: add user
user: name=nginx state=present group=nginx
- name: web page
copy: src=/etc/yum.repos.d/epel.repo dest=/etc/yum.repos.d
- name: install nginx
yum: name=epel-release.noarch
yum: name=nginx state=present
- name: config file
copy: src=/data/nginx.conf dest=/etc/nginx/
notify:
- restart nginx
- name: web page
copy: src=/data/index.html dest=/usr/share/nginx/html
- name: start nginx
service: name=nginx state=started enabled=yes
3.3.5第一个 yml文件
---
#第一个playbook
- hosts: web
tasks:
- name: ping
ping:
- name: wall
shell: wall hello
######辅助设置################
[root@localhost ~]#vim .vimrc
set ai ts=2 sw=2
####################################
##########################检查语法#####################################################
[root@localhost data]#ansible-playbook --help |grep check
#检查语法
[--skip-tags SKIP_TAGS] [-C] [--syntax-check] [-D]
--syntax-check perform a syntax check on the playbook, but do not
-C, --check don't make any changes; instead, try to predict some
differences in those files; works great with --check
ansible-playbook --syntax-check f.yml
ansible-playbook -C f.yml
####################################################################################
############ 运行 #####################
[root@localhost data]#ansible-playbook f.yml
#加playbook
---
#第一个playbook
- hosts: web
gather_facts: no #收集信息,当不使用时可以不收集加快速度
tasks:
- name: ping
ping:
- name: wall
shell: wall hello
- hosts: cloud
tasks:
- name: install httpd
yum:
name: httpd
- name: start httpd
service:
name: httpd
state: started
enabled: yes
playbook 命令
ansible-playbook <filename.yml> ... [options]
--syntax-check #语法检查,可缩写成--syntax, 相当于bash -n
-C --check #模拟执行,只检测可能会发生的改变,但不真正执行操作,dry run
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
-i INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的name
-v -vv -vvv #显示过程
[root@localhost ~]#vim .vimrc
set ai ts=2 sw=2
其中ai:自动换行;ts:tab的字符长度;sw:空格的长度 1 yum安装httpd 2 service 开启服务 3 copy 传一个 主页文件过去 4能访问
---
# this is a test file
- hosts: kg
remote_user: root
gather_facts: no
tasks:
- name: ping
ping:
- name: test
shell: wall hello
#创建用户
- hosts: accp
gather_facts: no
tasks:
- name: create user
user:
name: mysql
shell: /sbin/nologin
system: yes
create_home: no
[root@localhost ~]#ansible-playbook --help
[root@localhost ~]#ansible-playbook --syntax-check hello.yml
#语法检查
playbook: hello.yml
[root@localhost ~]#ansible-playbook -C hello.yml
- hosts: accp
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
- hosts: web
tasks:
- name: install httpd
yum:
name: httpd
- name: config file
copy:
src: files/index.html
dest: /var/www/html
- name: start httpd
service:
name: httpd
state: started
enabled: yes
- name: stop firewalld
service:
name: firewalld
state: stopped
enabled: no
ansible all -m yum -a 'name=httpd state=absent'
#卸载httpd
- hosts: web
remote_user: root
gather_facts: no
tasks:
- name: add group nginx
group:
name: nginx
state: present
- name: add user nginx
user:
name: nginx
state: present
group: nginx
- name: Install Nginx
yum:
name: nginx
state: present
- name: web page
copy:
src: files/index.html
dest: /usr/share/nginx/html/index.html
- name: Start Nginx
service:
name: nginx
state: started
enabled: yes
ignore_errors
如果一个task出错,默认将不会继续执行后续的其它task
利用 ignore_errors: yes 可以忽略此task的错误,继续向下执行playbook其它task
[root@ansible ansible]#cat test_ignore.yml
---
- hosts: websrvs
tasks:
- name: error
command: /bin/false
ignore_errors: yes
- name: continue
command: wall continue
Playbook中使用handlers和notify
Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
注意:
-
如果多个task通知了相同的handlers, 此handlers仅会在所有tasks结束后运行一 次。
-
只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
-
handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handler跳过执行,可以使用force_handlers: yes 强制执行handler
- hosts: web
tasks:
- name: install httpd
yum:
name: httpd
- name: config file
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/
notify: restart httpd
- name: start httpd
service:
name: httpd
state: started
enabled: yes
- name: stop firewalld
service:
name: firewalld
state: stopped
enabled: no
handlers:
- name: restart httpd
service:
name: httpd
state: restarted