ansible:playbook详解
概述
playbook是由一个或者多个play
组成的列表。
主要功能是将预定义的一组主机装扮成事先通过ansible中的task定义好的角色。task实际是调用ansible的一个模块,将多个play组织在一个playbook中,即可以让它们联合起来,将事先编排的机制执行预定义的动作。
playbook文件是使用YAML语言编写的。
YAML语言
YAML(Yet another Markup Language,仍是一种标记语言)是一个可读性高的用来表达资料序列的格式。
目前很多软件采用了此格式,如ansible、docker、k8s等。
语法说明
- YAML 的配置文件后缀为
.yml
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
#
表示注释,从这个字符一直到行尾,都会被解析器忽略
数据结构
YAML 支持的数据结构有三种。
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
- 纯量(scalars):单个的、不可再分的值
对象
对象的一组键值对,使用冒号:
结构表示。例如:
name: 'Rohn'
Yaml 也允许另一种写法,将所有键值对写成一个行内对象。例如:
{ hash: { name: 'Steve', foo: 'bar' } }
数组
一组连词线-
开头的行,构成一个数组。例如:
- Cat
- Dog
- Goldfish
纯量
纯量是最基本的、不可再分的值。
纯量的类型:
- 字符串
- 布尔值
- 整数
- 浮点数
- Null
- 时间
- 日期
字符串
- 字符串默认不使用引号表示。
- 如果字符串之中包含空格或特殊字符,需要放在引号之中。
- 单引号和双引号都可以使用,双引号不会对特殊字符转义。
- 单引号之中如果还有单引号,必须连续使用两个单引号转义。
- 字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格。
- 多行字符串可以使用
|
保留换行符,也可以使用>
折叠换行。 +
表示保留文字块末尾的换行,-
表示删除字符串末尾的换行。- 字符串之中可以插入 HTML 标记。
核心元素
元素 | 说明 |
---|---|
hosts | 远程主机列表 |
tasks | 任务集 |
variables | 内置变量或自定义变量,用于playbook中调用 |
templates | 模板 |
handlers和notify | handlers和notify配合使用,由特定条件触发的操作,满足条件则执行,否则不执行 |
tags | 标签 |
hosts
playbook中的每一个play的目的是为了让特定主机以某个指定用户身份执行任务。hosts用于指定要执行指定任务的主机,需事先定义在主机清单中。例如:
- hosts: websrvs:dbsrvs # 或者,两个组的并集
- hosts: websrvs:&dbsrvs # 与,两个组的交集
- hosts: websrvs:!dbsrvs # 在websrvs组,但不在dbsrvs组
remote_user
可以用于host和task中。也可通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户。
task列表和action组件
play的主体部分是task list。task list中有一个或者多个task,各个task按顺序逐个在hosts指定的所有主机上执行、也就是所有主机完成一个task后,再开始下一个task。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
每个task都应该有name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。若未能提供name,则action的结果将用于输出。
task格式有两种:
- action: module arguments
- module: arguments # 推荐使用这种
Tips:shell模块和command的模块后面跟的是命令,而非
key=value
的方式。
其他组件
若有任务的状态在运行后为changed时,可通过notify通知给相应的handlers。
shell脚本和playbook对比
部署Nginx
Shell脚本:
#!/bin/bash
yum -y install nginx
\cp /tmp/nginx.conf /etc/nginx/
\cp /tmp/web.conf /etc/nginx/conf.d/
systemctl enable nginx
nginx -t
systemctl start nginx
playbook实现:
---
- hosts: web_server
remote_user: root
tasks:
- name: "部署nginx"
yum: name=nginx
- name: "复制配置文件"
copy: src=/tmp/nginx.conf dest=/etc/nginx/
- name: "复制配置文件"
copy: src=/tmp/web.conf dest=/etc/nginc/conf.d/
- name: "启动nginx,并设置开机启动"
service: name=nginx state=started enable=yes
playbook命令
语法格式
usage: ansible-playbook [-h] [--version] [-v] [-k]
[--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
[-c CONNECTION] [-T TIMEOUT]
[--ssh-common-args SSH_COMMON_ARGS]
[--sftp-extra-args SFTP_EXTRA_ARGS]
[--scp-extra-args SCP_EXTRA_ARGS]
[--ssh-extra-args SSH_EXTRA_ARGS] [--force-handlers]
[--flush-cache] [-b] [--become-method BECOME_METHOD]
[--become-user BECOME_USER] [-K] [-t TAGS]
[--skip-tags SKIP_TAGS] [-C] [--syntax-check] [-D]
[-i INVENTORY] [--list-hosts] [-l SUBSET]
[-e EXTRA_VARS] [--vault-id VAULT_IDS]
[--ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES]
[-f FORKS] [-M MODULE_PATH] [--list-tasks]
[--list-tags] [--step] [--start-at-task START_AT_TASK]
playbook [playbook ...]
精简为:
ansible-playbook <filename.yml> ... [options]
常用参数
参数 | 说明 |
---|---|
-C | 只检测可能发生的改变,并不真正执行操作 |
--list-hosts | 列出运行任务的主机 |
--list-tags | 列出tag |
--list-taks | 列出task |
--limit | 只针对主机列表中的主机执行 |
-v | 显示过程 |
例子
安装MariaDB
---
#Installing MariaDB Binary Tarballs
- hosts: db_server
remote_user: root
gather_facts: no
tasks:
- name: create group
group: name=mysql gid=27 system=yes
- name: create user
user: name=mysql uid=27 system=yes group=mysql shell=/sbin/nologin home=/data/mysql create_home=no
- name: mkdir datadir
file: path=/data/mysql owner=mysql group=mysql state=directory
- name: unarchive package
unarchive: src=/data/ansible/files/mariadb-10.2.27-linux-x86_64.tar.gz dest=/usr/local/ owner=root group=root
- name: link
file: src=/usr/local/mariadb-10.2.27-linux-x86_64 path=/usr/local/mysql state=link
- name: install database
shell: chdir=/usr/local/mysql ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
- name: config file
copy: src=/data/ansible/files/my.cnf dest=/etc/ backup=yes
- name: service script
shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
- name: start service
service: name=mysqld state=started enabled=yes
- name: PATH variable
copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头。
语法格式
var=value
例如:
db_port=3306
变量调用方式
"{{ variable_name }}"
变量来源
-
ansible 的 setup facts 远程主机的所有变量都可直接调用;
-
通过命令行指定变量,优先级最高:
ansible-playbook -e var=value
-
在playbook文件中定义:
vars: - var1: value1 - var2: value2
-
在独立的变量YAML文件中定义:
- hosts: all vars_files: - vars.yml
-
在
/etc/ansible/hosts
中定义:- 主机(普通)变量:主机组中主机单独定义,优先级高于公共变量;
- 组(公共)变量:针对主机组中所有主机定义同一变量;
-
在role中定义
template模板
模板是一个文本文件,可以作为生成文件的模板,并且模板文件中还可以嵌套jinja语法。
jinja语言
- jinja2 语言使用字面量,有下面形式:
- 字符串:使用单引号或双引号
- 数字:整数,浮点数
- 列表:[item1, item2, ...]
- 元组:(item1, item2, ...)
- 字典:
- 布尔型:true/false
- 算术运算:+, -, *, /, //, %, **
- 比较操作:==, !=, >, >=, <, <=
- 逻辑运算:and,or,not
- 流表达式:For,If,When
流程控制
template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能。
例如:
#temlnginx2.yml
---
- hosts: websrvs
remote_user: root
vars:
nginx_vhosts:
- 81
- 82
- 83
tasks:
- name: template config
template: src=nginx.conf.j2 dest=/data/nginx.conf
#templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}
ansible-playbook -C templnginx2.yml --limit 10.0.0.8
#生成的结果:
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
实例
同步nginx配置文件:
---
- hosts: web_server
remote_user: root
tasks:
- name: "config"
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf