简介
Playbook是由一个或多个“play”组成的列表,可以让它们联同起来按事先编排的机制执行;所谓task无非是调用ansible的一个module,而在模块参数中可以使用变量;模块执行是幂等的,这就意味着多次执行是安全的,因为其结果均一致。
特点
- YAML的可读性好
- YAML和脚本语言的交互性好
- YAML使用实现语言的数据类型
- YAML有一个一致的信息模型
- YAML易于实现
- YAML可以基于流来处理
- YAML表达能力强,扩展性好
核心组件
- Hosts:执行的远程主机列表
- Tasks:任务,由模块定义的操作的列表;
- Varniables:内置变量或自定义变量在playbook中调用
- Templates:模板,即使用了模板语法的文本文件;
- Handlers:和nogity结合使用,为条件触发操作,满足条件方才执行,否则不执行;
- Roles:角色;
官方实例:
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: started
handlers:
- name: restart apache
service:
name: httpd
state: restarted
运行:
-t Tag 指定运行特定的任务
--skip-tags=SKIP_TAGS 跳过指定的标签
--start-at-task=START_AT 从哪个任务后执行
检查语法:--syntac-check
测试运行:--check
handlers 和 notify结合使用触发条件,让playbook在满足一定触发条件时才去执行某条task。
ERROR! Unexpected Exception, this is probably a bug: unhashable type: 'dict'
如何遇到此类问题,是因为dict不可哈希,所以notify在配置下,使用可哈希数据类型即可。
变量
- 变量的来源:
- ansible setup facts远程主机的所有变量都可以用
- 自定义变量
- 优先级:
- 通过命令行指定变量,优先级最高
- 在/etc/ansible/hosts 定义变量,在主机组中的主机单独定义
- 在/etc/ansible/hosts 定义变量,针对主机组中的所有主机集中定义变量
- 在Playbook中定义变量(建议使用这种方法)
[WARNING]: Found variable using reserved name: port
如何遇到此类问题,是因为port为保留的变量名,更改一下变量名即可!
模版
- 文本文件,内部嵌套有模板语言脚本(使用模板语言编写)
- Jinja2 是由python编写的。在我们打算使用基于文本的模板语言时,jinja2是很好的解决方案。yaml是写playbook,jinja2是写配置文件模板的
- 功能:将模板的文件的变量值转换成对应的本地主机的确定值。例如:ansible端写一个内建变量{{ansible_processor_vcpus }},当这个文件被复制到对应主机时会自动生成对应主机 cpu的颗数的结果替换之。
- templates文件必须存放在templates目录下
- yaml文件需要和templates目录平级
- Jinja2语法
字面量:
字符串:使用单引号或双引号;
数字:整数、浮点数;
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:
+, -, *, /, //, %, **
比较操作:
==, !=, >, <, >=, <=
逻辑运算:and, or, not
实例:
[root@node1 templates]# cat nginxconf.j2.bak
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
# listen {{ vhost.listen }}
}
{% endfor %}
worker_processes {{ ansible_processor_vcpus }};
[root@node1 tmp]# cat nginxtemp.yam
- hosts: mageduweb
remote_user: root
vars:
nginx_vhosts:
- web1
- web2
- web3
# nginx_vhosts:
# - listen: 8080
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
条件判断
- name: restart Nginx
service: name=nginx state=restarted
when: ansible_distribution_major_version == "6"
循环迭代
#基于字符串列表
tasks:
- name: create rsyncd file
copy: src={{ item }} dest=/tmp/{{ item }}
with_items:
- a
- b
- c
- d
*with_itmes 嵌套子变量*
#基于字典列表
- hosts: eagleslab
remote_user: root
tasks:
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1' , groups: 'wheel'}
- { name: 'testuser2' , groups: 'root' }
角色
[root@node1 ~]# tree /etc/ansible/roles/
/etc/ansible/roles/
└── http
├── defaults
├── files
├── headlers
├── meta
├── tasks
├── template
└── varsfiles/:存储由copy或script等模块调用的文件;
- tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;
- handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;
- vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;
- templates/:存储由template模块调用的模板文本;
- meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;
- default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
- files目录:存放由copy或script等模块调用的文件;
调用roles:
[root@node1 ~]# cat /etc/ansible/roles/site.yml
- hosts: abc
remote_user: root
roles:
- httpd
实例分析:
[root@node1 ansible]# tree roles/
roles/
├── http
│ ├── defaults
│ │ └── main.yaml
│ ├── files
│ │ └── index.html
│ ├── headlers
│ │ └── main.yaml
│ ├── meta
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ ├── templates
│ │ └── httpd.conf.j2
│ └── vars
│ └── main.yaml
└── site.yaml
[root@node1 roles]# cat site.yaml
- hosts: node2
remote_user: root
# vars:
# httpd_ports: 8080
roles:
- http
[root@node1 http]# cat files/index.html
hello eagleslab!
[root@node1 http]# cat tasks/main.yaml
- name: installed httpd service
yum: name=httpd state=latest
when: ansible_os_family == "RedHat"
- name: start httpd server
service: name=httpd state=restarted
- name: write httpd config
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: config httpd index
copy: src=index.html dest=/var/www/html/index.html
[root@node1 http]# cat templates/httpd.conf.j2 | grep -Ev "^[[:space:]]|^#"
ServerRoot "/etc/httpd"
Listen {{ httpd_ports }}
Include conf.modules.d/*.conf
User apache
Group apache
ServerAdmin root@localhost
<Directory />
</Directory>
DocumentRoot "/var/www/html"
<Directory "/var/www">
</Directory>
<Directory "/var/www/html">
</Directory>
<IfModule dir_module>
</IfModule>
<Files ".ht*">
</Files>
ErrorLog "logs/error_log"
LogLevel warn
<IfModule log_config_module>
</IfModule>
<IfModule alias_module>
</IfModule>
<Directory "/var/www/cgi-bin">
</Directory>
<IfModule mime_module>
</IfModule>
AddDefaultCharset UTF-8
<IfModule mime_magic_module>
</IfModule>
EnableSendfile on
IncludeOptional conf.d/*.conf
[root@node1 http]# cat headlers/main.yaml
- name: restart httpd
service: name=httpd state=restarted
[root@node1 http]# cat vars/main.yaml
httpd_ports: 8000
网友评论