ansible playbook
ansible playbooks 是使用ansible简单的配置管理部署系统的基础,使用YAML语法格式的配置文件。每一个playbook中包含一系列的任务。使用ansible playbook可以更方便的管理、维护多态主机。
1、yaml语法
yaml是”YAML Ain't a Markup Language”的缩写,即不是一种标记性语言,它是一种直观的能够被电脑识别的数据序列化格式,是一个可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言。
yaml编写playbook配置文件的规范:
(1)首行以”---”(3个减号)开始,且需顶行首写。
(2)使用#号注释代码。
(3)缩进必须是统一的,不能空格和tab混用
(4)缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的。
(5)YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感。
(6)k/v的值可同行写也可换行写。同行使用:分隔,换行写需要以”-”分隔。
(7)一个完整的代码块功能需最少元素需包括 name: task。
(8)一个name只能包括一个task
2、编写执行ansible playbook
(1)使用ansible playbook安装启动httpd服务
---
#定义主机及主机组
- hosts: test
#定义执行任务的用户
remote_user: root
#编排执行的任务
tasks:
- name: install httpd
yum: name=httpd state=latest
- name: httpd configure
copy: src=/home/dayi123/ansible/httpd.conf dest=/etc/httpd/conf/ backup=yes
when: ansible_distribution_major_version == "6"
notify:
- restart httpd
- name: start httpd
service: name=httpd state=started
#和前面的notify时配合使用的,当配置发生变化时,执行 handlers中的任务
handlers:
- name: restart httpd
service: name=httpd state=restarted
(2)Playbook的主要组成元素
Hosts: 运行指定任务的目标主机,可以是主机,也可以是主机组,支持正则表达式。
Tasks: 任务列表,一个playbook配置文件中只能有一个tasks,一个tasks下可以编排多个任务。
Varniables: 变量
Templates: 模板,使用templates可以针对不同的主机定制不同参数。
Handlers: 由特定条件触发的任务,监控资源改变时才会触发,需要配合notify使用。
Roles: Playbook的按固定目录结构组成
(3)执行playbook
playbook执行时使用”ansible-playbook”命令后跟写好的yaml格式的playbook文件即可,但在执行前最好检查下playbook文件语法是否正确
#检查playbook配置语法是否正确
ansible-playbook web.yaml -C
#执行playbook
ansible-playbook web.yaml
playbook在执行时还可以跟其他的一些选项:
1)指定执行的主机或主机组:
playbook在执行时默认会在据配置文件在”hosts”中定义的主机及主机组上去执行,如果不想在配置文件中指定的主机上去执行,可以使用”--limit”指定主机。
#查看执行时受影响的主机
[root@ansible-server]# ansible-playbook web.yaml --list-hosts
#指定主机或主机组去执行
[root@ansible-server]# ansible-playbook web.yaml --limit test2
2)指定执行playbook的用户
playbook在执行时默认会使用配置文件中”remote_user”指定的用户去执行,如果想使用别的用户去执行,可以使用参数”--remote-user”指定用户去执行。如果使用参数指定的用户没有做ssh安全认证,则可以使用参数”--ask-sudo-pass”在执行命令时根据提示输入密码即可正常执行。
#指定没有做ssh公私钥认证的用户执行playbook
[liuyi@ansible-server ~]$ ansible-playbook web.yaml --sudo --sudo-user=dayi123 --ask
3)执行playbook时传入变量
执行playbook时,如果在”hosts”配置文件中及playbook中定义了变量并在执行时参入变量,则优先使用执行时用参数传入的变量,其次使用playbook中的变量,最后使用”inventory”文件中定义的变量。
在执行playbook时可以使用”-e”选项后跟”key1=value1,key2=value2”的方式传入变量。
#修改所有的http服务的端口为2345
ansible-playbook web.yaml -e "serverport=23456"
4)其他可使用的选项
-i(--inventory=PATH):指定inventory文件,默认文件是/etc/ansible/hosts
-v(--verbose):显示详细的输出,也可使用-vvvv显示精确到每分钟的输出
-f(--forks=NUM):指定并发执行的任务数,默认为5,可根据服务器的性能进行调节
-C(--check):检测模式,playbook中定义的所有任务将在每台远程主机上进行检测,但不执行。
3、ansible template模块
template模块可以将带有参数的配置文件传递到目标地址,可以对文件进行属组属主的修改以及备份。使用了Jinjia2格式作为文件模版(即以”.j2”结尾的文件),进行文档内变量的替换。
(1)template模块选项
选项:
dest 远程节点上用于放置文件位置。
group 设置远程节点上的的template文件的所属用户组
mode 设置远程节点上的template文件权限。类似Linux中chmod的用法
owner 设置远程节点上的template文件所属用户
src 本地Jinjia2模版的template文件位置。
(2)Jinja2语法格式
Jinja2调用变量时使用”{{ 变量名 }}”的格式来引用变量,并可以使用算术运算符(+ - * / % ** )、比较操作符(== >= != <= < > )、逻辑运算符(And or not)和流程表达式(for if when)。
根据hosts文件中定义的变量针对不同的主机修改httpd服务为不同的端口:
#hosts定义的变量
[test]
10.0.0.13 servername=ansible-client01 serverport=6666
10.0.0.14 servername=ansible-client02 serverport=8888
10.0.0.8 servername=ansible-server serverport=9999
#模板文件中定义的变量
[root@ansible-server ansible]# cat httpd.conf.j2 | grep ^Listen
Listen {{ serverport }}
#playbook的配置
---
- hosts: test
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=latest
- name: httpd configure
#文件拷贝到目标主机后任需要修改为httpd.conf格式
template: src=/home/dayi123/ansible/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
handlers:
- name: restart httpd
service: name=httpd state=restarted
使用算术运算符为每个服务的端口号加1:
[root@ansible-server ansible]# cat httpd.conf.j2 | grep ^Listen
Listen {{ serverport+1 }}
判断当系统为centos6时执行某个任务(判断的值可以使用ansible的setup模块抓取):
#当系统为centos6时将配置文件拷贝到远程主机
- name: httpd configure
tags: confighttpd
template: src=/home/dayi123/ansible/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == "6"
判断语句和for循环语句的使用:
#定义httpd服务虚拟主机的端口,定义两个端口,一个普通端口,一个https端口
[root@ansible-server ansible]# cat /etc/ansible/group_vars/test
---
serverport: 80
vports:
- 8080
- 443
#定义基于端口的虚拟主机的模板
[root@ansible-server ansible]# tail -13 httpd.conf.j2
#使用for循环语句
{% for vport in vports %}
<VirtualHost {{ ansible_default_ipv4.address }}:{{ vport }}>
ServerName www.{{ ansible_hostname }}.com
DocumentRoot /var/www/html
#如果没有定义accesslog,则使用默认的日志/var/log/httpd/access_log
{% if accesslog is not defined %}
CustomLog {{ accesslog | default('/var/log/httpd/access_log') }} combined
{% endif %}
<Directory "/var/www/html/">
Require All granted
</Directory>
</VirtualHOst>
{% endfor %}
4、playbook变量
ansible中的变量命名规则与linux操作系统的变量命名规则类似,变量的命名要以英文大小写字母开头,中间可包含下划线或数字。ansible playbook的变量可定义在inventory中,也可在执行playbook时传入或者定义在playbook中。
(1)变量定义在playbook中
变量可以直接定义在playbook中,定义的方法如下:
- hosts: "*"
vars:
- serverport: 999
变量也可以定义在别yaml的文件中,在playbook的配置文件中导入
#定义端口的yaml文件
[root@ansible-server ansible]# cat serverport.yaml
---
serverport: 1024
#在playbook中导入配置文件
---
- hosts: "*"
vars_files:
- serverport.yaml
(2)在inventory中定义变量
inventory文件通常指ansible主机和组的定义文件hosts,定义变量时使用”=”为变量赋值,变量通常定义在主机名的后面或组的下方。
#在inventory(hosts)中定义主机变量
[test]
10.0.0.13 servername=ansible-client01
10.0.0.14 servername=ansible-client02
#在inventory(hosts)中定义组变量
[test:vars]
httpdserver_port=8080
ansible官方并不建议直接在hosts文件中定义变量,执行ansible命令时,ansible会从”/etc/ansible/host_vars/”和”/etc/ansible/group_vars/”目录下读取文件,这两个文件分别为主机的变量定义目录和组的变量定义目录,如果这两个目录不存在,可直接手工创建。这两个目录下定义的变量为以组名或者以主机名为文件名的yaml格式的文件。
#定义”test”组的变量
[root@ansible-server ansible]# cat /etc/ansible/group_vars/test
---
serverport: 8080
(3)在运行playbook时,可使用-e参数或”--extra-vars”传入变量。
5、playbook tags标签
默认情况下,Ansible在执行一个playbook时,会执行playbook中定义的所有任务,使用tags可以给roles、文件、某个单独的任务以及整个playbook 打上标签,然后利用这些标签指定要运行playbook中的某个任务或不执行某个任务。
#给某些任务打上标签
tasks:
- name: install httpd
tags: installhttpd
yum: name=httpd state=latest
- name: httpd configure
tags: confighttpd
template: src=/home/dayi123/ansible/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == "6"
- name: start httpd
tags: reloadhttpd
service: name=httpd state=restarted
执行时跳过某个任务:
#执行时跳过安装
[root@ansible-server ansible]# ansible-playbook web.yaml --skip-tags "installhttpd"
执行时只执行某些任务
#只执行confighttpd和reloadhttpd标签里面的任务
[root@ansible-server ansible]# ansible-playbook web.yaml --tags "confighttpd,reloadhttpd"
6、playbook debug
在使用ansible playbook时,一个playbook中可以包含多个任务,任务执行完,我们并不知道任务的具体执行结果,使用playbook debug可以将某个任务的执行结果或者我们需要的信息打印出来。
参数:
msg:调试输出的消息
var:将某个任务执行的输出作为变量传递给debug模块,debug会直接将其打印输出
verbosity:debug的级别(默认是0级,全部显示)
(1)playbook debug 结合注册变量register打印日志
在playbook运行的过程中,一个任务可以通过”register”注册一个变量来任务运行的结果,同时注册变量的结果也可以通过debug打印出来。
- name: httpd configure
template: src=/home/dayi123/ansible/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
# 定义一个记录执行结果的变量
register: copy_configuer_log
# 将执行结果打印出来
- name: show copy configure log
debug: var=copy_configuer_log
使用msg打印自定义的信息
打印自定义信息,也可以根据ansible setup模块打印出来的信息进行调用。
#打印主机的远程uuid及mac地址。
- name: show host
debug: msg="uuid:{{ ansible_product_uuid }} hostname:{{ ansible_nodename }}"
7、ansible playbook迭代
当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句来指明迭代的元素列表即可。
#使用迭代的方式安装多个软件
- name: yum install
yum: name={{ item }} state=present
with_items:
- git
- curl
#批量添加用户
- name: user add
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'user01',groups: 'dayi123' }
- { name: "user02",groups: 'dayi123' }