|
一、playbook简单介绍
playbook是一个非常简单的配置管理和多主机部署系统,可以定制配置,可以按指定操作步骤有序执行,支持同步及异步方式
下面是一个基本的playbook示例
/home/melon/ansible/playbooks/nginx.yml
---
- hosts: webservers
vars:
listenport: 8888
remote_user: root
tasks:
- name: 安装,确保nginx是最新版本
yum: pkg=nginx state=latest
- name: 同步配置文件
template: src=/home/melon/ansible/nginx/nginx.conf dest=/etc/nginx/nginx.conf
notify:
- restart nginx
- name: 确保nginx是运行的
service: name=nginx state=started
handlers:
- name: restart nginx
service: name=nginx state=restarted
上面简单的定制了一个简单的nginx软件包管理,内容包括安装、配置模板、状态管理等
介绍:
第2行 hosts 参数的作用是定义操作的对象,可以是主机或组
第3、4行定义了属于该组的相关变量,可以在模板中进行引用,如在 nginx.conf 配置文件中使用 listen {{ listen_port }}
第5行的 remote_user 为指定远程操作的用户名,默认为 root,支持sudu方式 通过添加sudo:yes(remote_user 在ansible1.4以上的版本才引入)
第6-14行是任务列表,playbook将按定义的配置文件从上到下顺序执行,定义的主机都会执行相同的任务,定义name标签可以增加可读性
8行的功能是安装最新nginx,前面的action(动作)可以是ansible的任意模块,这里是yum模块,参数使用key=value格式
10行中,在playbook中可以通过template模块对本地配置模板文件如nginx.conf进行渲染并同步到目标主机,src 为管理端模板nginx.conf文件存放的位置 dest 为目标主机nginx.conf的文件位置
当目标主机的配置文件发生变化时,就会通知处理程序(Handlers)来触发后续动作,上面为重启nginx服务,是通过Handlers中定义的name来触发的,只会运行一次,比如上面的notify中restart nginx和Handlers中定义的name: restart nginx 保持一致
执行playbook可以通过ansible-playbook命令实现,下面表示启用10个并行进程数执行playbook
ansible-playbook /home/melon/ansible/playbooks/nginx.yml -f 10
二、playbook角色与包含声明
当我们写个非常大的playbook时,还可以把它拆分成多个文件
当多个playbook涉及到复用时,可以将复用的内容剥离出来,写到独立的文件当中,在用到的时候在include进来即可
tasks/test.yml
---
- name: test shell
command: /tmp/test.sh
然后在使用的时候include
tasks:- include: tasks/test.yml
处理程序handlers也一样
handlers/handlers.yml
---
- name: restart nginx
service: name=nginx state=restarted
引入时
handlers:- include: handlers/handlers.yml
角色建立在包含文件之上,抽象后更清晰、可复用。Ansible官方在GitHub上提供了大量的示例供大家参考:https://github.com/ansible/ansible-examples
角色时Ansible定制好的一种标准规范,以不同级别目录层次及文件对角色、变量、任务、处理等进行拆分,为后续功能扩展、可维护性打下基础
下面是一个playbook的目录结构
nginx
├── group_vars
│ ├── all
│ └── webservers
├── hosts
├── roles
│ ├── db
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── my.cnf.j2
│ └── web
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ │ ├── default.conf
│ │ └── nginx.conf
│ └── vars
│ └── main.yml
├── site.retry
└── site.yml
首先是引用文件
site.yml 全局配置文件
---
- name: 部署和配置网络服务器和应用程序代码
hosts: webservers
roles:
- web
- name: 部署mysql数据库和配置
hosts: dbservers
roles:
- db
hosts 主机组定义文件(非必选配置,默认引用/etc/ansible/hosts的参数),如果定义了,执行时要通过"-i file"来调用,如:ansible-playbook -i hosts
[webservers]
192.168.190.131
[dbservers]
192.168.190.133
group_vars 变量定义目录(目录当中的文件名要与组名保持一致,组变量文件定义的变量只作用于该组),all代表所有主机的变量
group_vars/all
---
server_hostname: www.example.com
group_vars/webservers
---
worker_processes:
4
num_cpu:
4
roles 角色功能目录,这里就说web角色
角色web定义了handlers、tasks、templates、vars 4个功能类,分别用来存放处理程序、任务列表、模板、变量的配置文件main.yml(vars/main.yml中定义的变量优先级高于/nginx/group_vars/all)
handlers/main.yml
- name: restart nginx service: name
=nginx state=restarted
templates/nginx.conf(引用定义的变量)
user nginx;
worker_processes {{ worker_processes }};
{
% if num_cpus == 2 %}
worker_cpu_affinity
01 10;
{
% elif num_cpus == 4 %}
worker_cpu_affinity
1000 0100 0010 0001;
{
% else %}
worker_cpu_affinity
1000 0100 0010 0001;
{
% endif %}
...........
tasks/main.yml
- name: 安装最新nginx yum: pkg
=nginx state=latest
- name: 同步配置文件 template: src
=nginx.conf dest=/etc/nginx/nginx.conf notify: restart nginx
- name: 同步配置文件 template: src
=default.conf dest=/etc/nginx/conf.d/default.conf notify: restart nginx
- name: 确保nginx已经启动 service: name
=nginx state=started
运行角色(用-i hosts引用定义的角色)
ansible-playbook -i hosts site.yml -f 10
三、Facts
Facts类似于Saltstack的Grains功能,实时获取远程主机的各种信息
命令
ansible webservers -m setup
192.168.190.131 | SUCCESS => {"ansible_facts": {"ansible_all_ipv4_addresses": ["192.168.190.131","172.17.42.1" ],
"ansible_all_ipv6_addresses": ["fe80::20c:29ff:feb2:95cc","fe80::427:e1ff:fee3:2634" ],
"ansible_architecture": "x86_64","ansible_bios_date": "07/02/2015","ansible_bios_version": "6.00","ansible_cmdline": {"KEYBOARDTYPE": "pc","KEYTABLE": "us","LANG": "en_US.UTF-8","SYSFONT": "latarcyrheb-sun16",
..................
在模板中引用Facts信息
{{ ansible_architecture }}
{{ ansible_cmdline.KEYTABLE }}
本地Facts
当获取的目标信息不能满足我们的功能需求时,我们可以通过本地的Facts来实现,只需要在目标设备/etc/ansible/facts.d 目录定义JSON、INI 或可执行文件的JSON输出,文件扩展名要求使用".fact"
例如在目标机器192.168.190.131上定义3个变量
/etc/ansible/facts.d/test_fact.fact
[general]
max_memory_size
=32
max_user_processes
=3730
open_files
=65535
然后执行命令查看:
ansible webservers -m setup -a "filter=ansible_local"
结果可以看到刚刚我们在192.168.190.131定义的变量
返回的JSON层次结构:test_fact(facts文件名前缀)>general(INI的节名)>key:value(INI的键与值),在模板中的调用方式
{{ ansible_local.test_fact.general.max_memory_size }}
注册变量
变量的另一个用途是将一条命令的运行结果保存到变量中供后面的playbook使用,示例:
- hosts: webservers tasks:
- shell: /var/test.sh register: foo_result
ignore_errors: True
- shell: /usr/test.sh when: foo_result.rc
== 5
上面示例说明:定义一个foo_result变量,变量的值为执行的shell:/var/test.sh的运行结果,ignore_errors: True 为忽略错误,变量注册完成后,playbook就可以在模板使用了,
when: foo_result.rc == 5 表示当执行命令后的resultcode(返回码)等于5时执行上面的命令
条件语句
有时候一个playbook的结果取决于一个变量,或者取决于上一个任务的执行结果,下面介绍When声明
tasks:- name: "when test" command:
/srv/test.sh when: ansible_os_family
== "Debian"
上面例子表示:通过Facts本地变量 ansible_os_family 是否为Debian,为True时将执行上一条语句 command: /srv/test.sh ,为False时该语句不会触发,
- hosts: webservers tasks:
- shell: /var/test.sh register: foo_result
ignore_errors: True
- shell: /usr/test.sh when: foo_result
|failed
- shell: /home/test.sh when: foo_result
|success
- shell: /srv/test.sh when: foo_result
|skipped
when: foo_result|success的意思是当变量foo_result执行结果为成功状态时,将执行/home/test.sh ,其他同理。
循环
有时一个任务会做很多事情,如创建很多用户、安装很多包、或重复轮询特定的步骤,知道某结果条件为止
- name: add user user: name
={{ item }} state=present groups=wheel with_item:
- testuser1- testuser2
####################
- name: add testuser1
user: name=testuser1 state=present groups=wheel
- name: add testuser2
user: name=testuser2 state=present groups=wheel
上面示例上下实现的功能是一样的,上面使用了循环,实现一个批量创建系统用户的功能,with_item会自动循环执行上面的语句,循环的次数为with_item的元素个数,里面的元素会分别替换{{ item }}项
元素还支持字典形式
- name: add tuser user: name
={{ item.name }} state=present groups={{ item.groups }} with_items:
- { name: 'testuser1', groups: 'wheel' }- { name: 'testuser2', groups: 'root' } |
|
|