,1,playbook 简介
- playbook 是由一个或多个“play” 组成的列表
- play 的主要功能在于将事先归并为一组的主机装扮成事先通过 ansible 中的 task 定义好的角色。从根本上来讲,所有的 task 无非是调用 ansible 的一个 module。将多个 play 组织在一个 playbook 中,即可以让它们联同起来按事先编排的机制同时进行。
- playbook 采用 YAML 语法编写
2,playbook 工作流程
3,YAML 介绍
- YAML 是一个可读性高的用来表达资料序列的格式。YAML 参考了其它多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式 RFC2822 等。Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。
- YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种置标语言),
- 特性
- YAML 的可读性好
- YAML 和脚本语言的交互性好
- YAML 使用实现语言的数据类型
- YAML 有一个一致的信息模型
- YAML 易于实现
- YAML 可以基于流来处理
- YAML 表达能力强,扩展性好
- 更多内容及规范参见:www.yaml.org
3.1 YAML 语法简介
- 在单一配置文件中,可用连续三个连字号
---
区分多个配置信息。另外选择性的连续三个点号 ...
用来表示配置文件的结尾
- 次行开始正常写 playbook 的内容,一般建议写明 playbook 的功能
- 使用
#
号注释代码
- 缩进必须是统一的,不能空格和
tab
混用
- 缩进的级别也是必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
- YAML 文件的内容和 Linux 系统大小写判断方式保持一致,是区别大小写的,
key/value
的值均需要大小写敏感
key/value
的值可同行写也可换行写。同行使用 :
分隔
value
可是个字符串,也可是另一个列表
- 一个完整的代码块功能需要最少元素需包括
name: task
- 一个
name
只能包括一个 task
- YAML 文件的扩展名通常为
yml
或 yaml
- List:列表,其所有元素均使用
-
大头
- 示例
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
- Dictionary:字典,通常由多个
key
与 value
构成
- 示例:
---
# An employee record
name: Example Developer
job: Developer
skill; Elite
- 也可以将
key:value
放置于 {} 中进行表示,用 ,
分隔多个 key:value
- 示例
---
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
- YAML的语法和其它高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用
-
来代表,Map 里的键值对用 :
分隔
- 示例
name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age: 13
gender: Female
4,Playbook VS ShellScripts
#!/bin/bash
# 安装 Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp /tmp/vhosts.conf /etc/httpd/conf.d/vhosts.conf
# 启动 Apache,并设置开机自启
service httpd start
chkconfig httpd on
---
- hosts: all
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件 httpd.conf"
copy: scr=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件 vhosts.conf"
copy: scr=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=true
5,playbook 核心元素
- Hosts 执行的远程主机列表
- Tasks 任务集
- Varniables 内置变量或自定义变量在 playbook 中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满座条件方才执行,否则不执行
- tags 标签,指定某条件任务执行,用于选择运行 playbook 中的部分代码。ansible 具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过 tags 跳过此代码片段
- ansible-playbook -t tagsname useradd.yaml
5.1 Hosts:
- playbook 中的每一个 play 的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts 用于指定要执行指定任务的主机,须事先定义在主机清单中
- 可以是如下形式:
one.example.com
one.example.com:two.example.com
192.168.1.120
192.168.1.*
Websrvs:dbsrvs
两个组的并集
Websrvs:&dbsrvs
两个组的交集
webservers:!phoenix
在 websrvs 组,但不在 dbsrvs 组
- 示例
- hosts: websrvs:dbsrvs
5.2 remote_user
- 可用于 Host 和 task 中。也可以通过指定其通过 sudo 的方式在远程主机上执行任务,其可用于 play 全局或某任务;此外,甚至可以在 sudo 时使用 sudo_user 指定 sudo 时切换的用户
- hosts: websrvs
remote_user: root
tasks:
- name: tast connection
ping:
remote_user: test
sudo: yes # 默认sudo 为 root
sudo_suer: wang # sudo 为 wang
5.3 task 列表和 action
- play 的主体部分是 task list、task list 中 的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而上某 playbook 时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正 playbook 后重新执行一次即可
- task 的目的是使用指定的参数指定模块,而在模块参数中可以使用变量。模块执行时幂等的,这意味着多次执行时安全的,因为其结果均一致
- 每个task都应该有其 nam,用于 playbook 的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供 name,则 action 的结果将用于输出
- task:任务列表
- 格式:
- 1,
action: module arguments
- 2,
module: arguments
建议使用
- 注意:shell 和 command 模块后面跟命令,而非
key=value
- 某任务的状态在运行后为 changed 时,可通过
notify
通知给相应的 handlers
- 任务可以通过
tags
打标签,而后可在 ansible-playbook
命令上使用 -t
指定进行调用
- 示例
tasks:
- name: disable selinux
command: /sbin/setenforce 0
- 如果命令或脚本的退出码不为零,可以使用如下方式替代
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
- 或者使用 ignore_errors 来忽略错误信息
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
- 运行 playbook 的方式
ansible-playbook <filename.yml> ... [options]
- 常见选项
--check
只检测可能会发生的改变,但不真正执行操作
--list-hosts
列出运行任务的主机
--limit
主机列表 只针对主机列表中的主机执行
-v
显示过程 -vv -vvvv
更详细
- 示例
ansible-playbook file.yml
ansible-playbook file.yml --check # 只检测
ansible-playbook file.yml --limit websrvs
5.3.1 playbook 示例
---
- hosts:all
remote_user: root
tasks:
- name: create mysql user
user: name=mysql system=yes uid=36
- name: create a group
group: name=httpd system=yes
---
-hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: copy configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
- name: start service
service: name=httpd state=started enabled=yes
5.4 handlers 和 notify 结合使用触发条件
- Handlers 是task列表,这些 task 与前述的 task 并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作
- Notify 此 action 可用于在每个 play 的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify 中列出的操作称为 handler,也即 notify 中调用 handler 中定义的操作
- 示例
---
-hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: copy configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd
- name: start service
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd
service: name=httpd status=restarted
---
- hosts: websrvs
remote_user: root
task:
- name: add group nginx
tags: user
user: name=nginx state=present
- name: add user nginx
user: name=nginx statepresent group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: config
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify:
- Restart Nginx
- Check Nginx Process
handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx Process
shell: killall -0 nginx > /tmp/nginx.log
- tags 见名之意,tags 可以帮助我们对任务进行 “打标签” 的操作,当任务存在标签以后,可以在执行 playbook 时,借助标签,指定执行哪些任务,或者指定不执行哪些任务
- 示例
---
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
tags: install,always
- name: Install configure file
copy: src=file/httpd.conf dest=/etc/httpd/conf/
tags: conf,always
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
- 在调用标签时,也可以一次性指定多个标签,调用多个标签需要用逗号隔开
ansible-playbook --tags install,service httpd.yml
- 在调用标签之前,预览一下 playbook 中都有哪些标签,使用
--list-tags
ansible-playbook --list-tags httpd.yml
- 如果有不想执行的任务,可以使用
--skip-tags
跳过指定的标签
ansible-playbook --skip-tags always httpd.yml
6,Playbook 中变量使用
- 变量名:仅能有字母、数字和下划线组成,且只能以字母开头
- 变量来源:
- 1
ansible setup facts
远程主机的所有变量都可直接调用
- 2 在
/etc/ansible/hosts
中定义
- 普通变量:主机中主机单独定义,优先级高于公共变量
- 公共(组)变量:针对主机组中所有主机定义统一变量
- 3 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value file.yml
- 4 在 playbook 中定义
- 5 在独立的变量YAML文件中定义
- 6 在 role 中定义
- 变量命名
- 变量命名仅能由字母、数字和下划线组成,且只能以字母开头
- 变量定义:
key=value
- 变量调用方式
- 通过
{{ variable_name }}
调用变量,且变量名前后必须有空格,有时用 "{{ variable_name }}"
才生效
- ansible-playbook -e 选项指定
ansible-playbook test.yml -e "hosts=www user=test"
6.1 实例
- 按照不同的方式优先级为:命令行,playbook定义变量文件,playbook定义变量,hosts定义私有变量,hosts定义公共变量
6.1.1 命令行定义
---
- hosts: websrvs
remote_user: root
tasks:
- name: create file
copy: content={{ var }} dest=/tmp/file.txt
# ansible-playbook -e "var=command" testvars.yml
# ansible websrvs -m shell -a 'cat /tmp/file.txt'
192.168.2.132 | CHANGED | rc=0 >>
command
192.168.2.131 | CHANGED | rc=0 >>
command
6.1.2 在 playbook 中定义
6.1.2.1 定义变量文件
---
- hosts: websrvs
remote_user: root
vars_files:
- vars.yml
tasks:
- name: create file
copy: content={{ var.content }} dest=/tmp/file.txt
var:
content: vars.yml
# ansible-playbook testvars.yml
# ansible websrvs -m shell -a 'cat /tmp/file.txt'192.168.2.131 | CHANGED | rc=0 >>
vars.yml
192.168.2.132 | CHANGED | rc=0 >>
vars.yml
6.1.2.2 playbook 中定义变量
---
- hosts: websrvs
remote_user: root
vars:
var: {content: playbook}
tasks:
- name: create file
copy: content={{ var.content }} dest=/tmp/file.txt
# ansible-playbook testvars.yml
# ansible websrvs -m shell -a 'cat /tmp/file.txt'192.168.2.132 | CHANGED | rc=0 >>
playbook
192.168.2.131 | CHANGED | rc=0 >>
playbook
6.1.3 /etc/ansible/hosts
中定义
---
- hosts: websrvs
remote_user: root
tasks:
- name: create file
copy: content={{ var }} dest=/tmp/file.txt
6.1.3.1 定义私有变量
[websrvs]
192.168.2.131 var=hosts_websrvs1
192.168.2.132 var=hosts_websrvs2
# ansible-playbook testvars.yml
# ansible websrvs -m shell -a 'cat /tmp/file.txt'
192.168.2.131 | CHANGED | rc=0 >>
hosts_websrvs1
192.168.2.132 | CHANGED | rc=0 >>
hosts_websrvs2
6.1.3.2 定义公共变量
[websrvs]
192.168.2.131
192.168.2.132
[websrvs:vars]
var=hosts_websrvs_vars
# ansible-playbook testvars.yml
# ansible websrvs -m shell -a 'cat /tmp/file.txt'
192.168.2.131 | CHANGED | rc=0 >>
hosts_websrvs_vars
192.168.2.132 | CHANGED | rc=0 >>
hosts_websrvs_vars
7,批量部署 zabbix-agent
# children 底下为父群组 zabbix-agent 的子群组
# vars底下为群组共同便变量,包括已定义变量和自定义变量
[zabbix-agent:children] # 父群组
test1 # 子群组1
test2 # 子群组2
[test1] # 子群组1
192.168.2.13[0:2] # 远端服务器 IP 列表
[test1:vars] # 子群组1 参数
ansible_ssh_user=root # 远端 ssh 服务器用户
ansible_ssh_pass="test1123" # 远端 ssh 服务器密码
ansible_ssh_port=22 # 远端 ssh 服务器端口
[test2] # 子群组2
192.168.2.10[1:3] # 远端服务器 IP 列表
192.168.2.11{1:3] # 远端服务器 IP 列表
[test2:vars] # 子群组2 参数
ansible_ssh_user=root # 远端 ssh 服务器用户
ansible_ssh_pass="test2123" # 远端 ssh 服务器密码
ansible_ssh_port=22 # 远端 ssh 服务器端口
---
- hosts: zabbix-agent # /etc/ansible/hosts 群组名
gather_facts: no # 跳过检查
remote_user: root # 远端服务器用户
# tasks: # 任务
# - name: judge a file or dir is exits # 判断该文件是否存在
# shell: /etc/zabbix/zabbix_agentd.conf
# ignore_errors: True # 忽略报错
# register: result # 定义变量
- name: ssh-copy # 复制 ssh 公钥到远端主机
authorized_key: user=root key="{{ lookup('file', '/root/.ssh/id_rsa.pub')}}"
tags: # 标签
- sshkey
- name: CentOS6 install zabbix-agent rpm # 安装 zabbix-agent 客户端 rpm 包
yum: name=http://repo.zabbix.com/zabbix/3.0/rhel/6/x86_64/zabbix-agent-3.0.0-2.el6.x86_64.rpm state=present
when: # 判断系统及版本号
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "6"
# - result|failed # 判断该文件不存在
- name: CentOS7 install zabbix-agent rpm
yum: name=http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-agent-3.0.0-1.el7.x86_64.rpm state=present
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "7"
# - result|failed # 判断该文件不存在
- name: configure Server IP # 配置自动注册 zabbix-server 端IP
shell: sed -i 's/Server=.*/Server=192.168.2.160/' /etc/zabbix/zabbix_agentd.conf
- name: configure ServerActive IP # 配置自动注册 zabbix-server 端IP
shell: sed -i 's/ServerActive=.*/ServerActive=192.168.2.160/' /etc/zabbix/zabbix_agentd.conf
- name: configure HostMetadata # 配置自动注册 key/value 值
shell: sed -i 's/# HostMetadata=/HostMetadata=zabbixs/' /etc/zabbix/zabbix_agentd.conf
- name: system configure Hostname # 配置当前服务器的主机名
shell: host=`hostname`;sed -i 's/Hostname=Zabbix server/Hostname='$host'/' /etc/zabbix/zabbix_agentd.conf
- name: start service # 启动 zabbix-agent 服务
service: name=zabbix-agent state=started enabled=true
- 通过编辑 /etc/ansible/ansible.cfg 或者 ~/.ansible.cfg 来实现 跳过ssh首次连接时,提示 是否continue,需要输入yes
[defaults]
host_key_checking = False
export ANSIBLE_HOST_KEY_CHECKING=False