playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。
核心元素
- hosts:执行的远程主机列表
- tasks:任务,由模板定义的操作列表
- vars:变量,内置变量或者自定义变量在playboook中调用
- templates:模板,即 使用模板语法的文件;可替换模板中的变量并实现一些简单逻辑的而文件
- handlers:和notify结合使用 ;当某条件满足时,触发执行的操作
- tags:标签,指定某条件下,用于选择运行playbook中的部分代码。Ansible具有幂等性,因此会自动跳过没有变化的部分,有些业务执行比较长,如果确认没有问题就可以通过tags跳过这些片段
- roles:角色
基础组件
-
hosts:playbook中的每个play的目的都是为了让某个或者某些主机在某个指定的用户身份执行任务。hosts用于指定任务的主机,须事先定义在主机清单中
形式如下:
- hosts: websrvs -
remote_user:可用于hosts和tasks中,也可以通过指定sudo的方式在远程主机上执行,其可用于paly全局或某任务;此外甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: 192.168.176.128 remote_user: root -
tasks:任务列表;格式有两种:
action: module argument module: argument建议使用第二种
特别注意:shell和command模块后面跟命令,而非key=value 某任务的状态在运行后changed时,可通过‘notify’通知给相应的handlers 任务可以通过‘tags’打标签,而后可在absible-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
---
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
yaml语法
YAML的语法和其他高阶语言类似并且可以简单表达清单、散列表、标量等数据结构,其结构通过空格来展示。(列表用横杆表示,键值对用冒号分割,键值对里又可以嵌套另外的键值对),YAML文件扩展名通常为.yaml或者.yml;
name: twp #冒号后有空格
age: 31
gender: male
spouse:
name: devil
age: 21
gender: female
children:
- name: xiaobai #横杠后有空格
age: 4
gender: femle
- name: xiaohuang
age: 1
gender: male
playbook的运行方式
ansible-playbook <filename.yaml> ... [options]
常用选项:
--check 只检测可能会发生的改变,但不真正执行操作
--list-hosts 列出运行任务的主机
--limit 主机列表,只针对主机列表中的主机执行
-v 显示过程 -vv -vvv 更详细
ansible-playbook file.yaml --check 只检测
Ansible-playbook file.yaml 执行
Ansible-playbook file.yaml --limit websevs 仅websevs主机执行
handles和notify结合条件使用
Handlers:是task列表,这些task与前述的task并没有本质的区别,用于当关注的资源发生变化时,才会采取一定的操作 Notify:此action被用于每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,尽在所有变化发生后完成一次性的执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。 示例: Handles和notify的使用:
- hosts: httpd
remote_user: root
tasks:
- name: add group apache
group: name=apache gid=180 system=yes
- name: add user apache
user: name=apache uid=180 group=apache system=yes
- name: install httpd package
yum: name=apache
- name: copy vhost.conf file
copy: src=vhost.conf dest=/etc/httpd/conf.d/vhost.conf
notify:
- restart httpd
handlers:
- name: restart httpd #必须和notify中定义的名字一致
service: name=httpd status=restarted enabled=yes
Tags的使用
- hosts: h
remote_user: root
- tasks:
name: install httpd
yum: name=httpd
- name: copy conf file
copy: src=files/vhost.conf dest=/etc/httpd/conf/vhost.conf
tags: conf
- name: start service
tags: service
service: name=httpd state=started enabled=yes
playbook中变量使用
变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头 变量来源:
- ansible setup 模块下的变量都可以使用
- /etc/ansible/hosts中定义的 普通变量:主机组中主机单独定义,优先级高于公共变量 公共组变量:针对主机组中所有的主机定义统一变量
- 通过命令行指定变量,优先级最好 ansible-playbook -e varname=value
- 在playbook中定义 var: var1: value1 var2: value2
- 在role中定义
变量的调用方式
- 通过{{ variable_name }}调用变量,且变量名前后必须有空格,有时候使用”{{ variable_name }}”才能生效
- anible-playbook -e 选项指定 ansible-playbook -e "hosts=httpd user=apache" httpd.yaml
使用变量
- 使用变量文件
# vcat vars.yaml
web01: httpd
web02: nginx
# cat vars.yaml
- hosts: 192.168.176.128
remote_user: root
vars_files:
- vars.yaml
tasks:
- name: create httpd configfile
file: name={{ web01 }}.conf state=touch #默认创建在当前用户下
- name: create nginx configfile
file: name={{ web02 }}.conf state=touch
-
使用setup变量
cat vars.yaml - hosts: 192.168.176.128 remote_user: root tasks: - name: create hosts file file: name=/etc/ansible/{{ ansible_fqdn }} state=touch #{{ ansible_fqdn }}为setup模块中域名的一个内置变量 -
命令行使用变量
# cat vars.yaml - hosts: 192.168.176.128 remote_user: root tasks: - name: install nginx package yum: name={{ nginx }} # ansible-playbook -e nginx=nginx vars.yaml
模板文件templetes
文本文件,嵌套有脚本(使用模板编程语言编写) Jinja2语音,使用 字面量,有下面形式 字符串:使用单引号或者双引号 数字:整数、浮点数 列表:[haha,xixi,hehe,lele] 元组:(haha,xixi,hehe,lele) 字典:{name:wkx,gender:male} 布尔型:true、false 算术运算:+、-、*、/、//、%、** 分别是加减乘除整除求余幂 比较操作:==,!=,>,<,>=,<= 逻辑运算:and,or,not 流表达式:for,if,when
When 条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法格式
cat > vars.yaml << EOF
- hosts: 192.168.176.128
remote_user: root
tasks:
- name: echo 123
command: echo 123
when: ansible_fqdn == "kube-master01"
EOF
迭代嵌套自变量
- hosts: 192.168.176.128
remote_user: root
tasks:
- name: create files
file: name=/opt/ansible/{{ item }}.txt state=touch #创建文件,嵌套变量在下面
when: ansible_fqdn == "kube-master01" #匹配条件,条件满足时执行
with_items:
- xiaobai
- xiaohong
- xiaohuang
- name: install some packages
yum: name={{ item }}
with_items:
- lrzsz
- net-tools
---
- hosts: 192.168.176.128
remote_user: root
tasks:
- name: create test groups
group: name={{ item }}
when: ansible_fqdn == "kube-master01"
with_items:
- xiaobai
- xiaohong
- xiaohuang
- name: cerate test users
user: name={{ item.name }} group={{ item.group }} system=yes
with_items:
- { user: "xiaobai",group: "xiaobai"}
- { user: "xiaohong",group: "xiaohong"}
- { user: "xiaohuang",group: "xiaohuang"}
Playbook中template循环嵌套,跟python模板语言一致;
{% for user in user_list %}
{{ user }};
{% endfor %}
{% if user.userid is defined %}
{{ user.userid }};
{% endif %}
{% if user.username is defined %}
{{ user.username }}
{% endif %}
---
- hosts: web
remote_user: root
vars:
- nginx_ports:
- 80
- 443
tasks:
- name: templete configfile
template: src=/opt/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
cat nginx.conf.j2
{% for port in nginx_ports %}
server {
listen {{ port }}
server_name {{ ansible_fqdn }}
}
{% endfor %}
ansible-playbook安装nginx服务
- hosts: 192.168.176.128
remote_user: root
vars:
- group: nginx
- user: nginx
- package: nginx
- service: nginx
tasks:
- name: add group {{group}}
group: name={{group}} gid=80 system=yes
- name: add user {{user}}
user: name={{user}} uid=80 group={{group}} shell=/sbin/nologin system=yes
- name: install {{package}} package
yum: name={{package}}
- name: create html directory
file: path=/etc/nginx/html state=directory
- name: copy index.html file
copy: src=/opt/ansible/index.html dest=/etc/nginx/html/index.html
- name: templates configfile
template: src=/opt/ansible/nginx.conf.j2 dest=/etc/nginx/nginx.conf mode=644
notify:
- restarted {{service}} service
- name: start {{service}} service
service: name={{service}} state=started enabled=yes
#when: ansible_fqdn="kube-master01"
handlers:
- name: restarted {{service}} service
service: name={{service}} state=restarted