- ---
- - hosts: localhost
- remote_user: root
- tasks:
- - name: create user
- user: name={{ item }} state=present
- with_items:
- - zabbix
- - admin
执行结果:

示例二:循环中使用register注册变量
- - hosts: localhost
- remote_user: root
- tasks:
- - command: echo {{ item }}
- with_items: [ 0, 2, 4, 6, 8, 10 ]
- register: num
- - debug: msg="{% for i in num.results %} {{i.stdout}} {% endfor %}"
注意,将with_items迭代后的结果注册为变量时,其注册结果也是列表式的,且其key为"results"。具体的结果比较长,可以使用debug模块的var或msg参数观察变量的结果。以上示例运行结果如下:

2.with_dict迭代字典
使用"with_dict "可以迭代字典项。迭代时,使用"item.key"表示字典的key,"item.value"表示字典的值。
示例一:
- ---
- - hosts: localhost
- remote_user: root
- tasks:
- - debug: msg="{{ item.key }} / {{ item.value }}"
- with_dict: { ip: 10.1.210.51, hostname: app52, gateway: 10.1.210.1}
以上示例中字典是已经存在了,除此之外字典可以来源于变量、facts等。例如使用facts进行迭代
- ---
- - hosts: localhost
- remote_user: root
- tasks:
- - debug: msg="{{item.key}} / {{item.value}}"
- with_dict: "{{ ansible_cmdline }}"
使用include简化playbook
如果将所有的play都写在一个playbook中,很容易导致这个playbook文件变得臃肿庞大,且不易读。因此,可以将多个不同任务分别写在不同的playbook中,然后使用include将其包含进去即可。include可以导入两种文件:导入task文件、导入playbook。
示例:创建task.yml任务列表
- vim task.yml
- - name: task1
- debug: msg="exec task1"
- - name: task2
- debug: msg="exec task2"
在目标playbook中倒入任务
- ---
- - hosts: 10.1.210.51
- remote_user: root
- tasks:
- - include: task.yml
执行playbook:

示例2:直接导入其他playbook,不过在ansible2.8将移除,2.8中将使用import_playbook
- ---
- - hosts: 10.1.210.51
- remote_user: root
- tasks:
- - include: task.yml
- - include: test_when.yml
- - include: test_with.yml
四、roles(角色)介绍
简介
roles 就字面上来说有角色、作用的意思,但它的全名其实是 Playbooks Roles,我们可把它当成是 playbooks 的延伸使用,可以降低 playbooks 的复杂性,更可以增加 playbooks 的可用性。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。
使用场景
- 同时安装多个不同的软件如:LNMP环境
- 不同服务器组需要安装不同服务
- 复杂的playbook,使用role可以具有阅读性
目录结构
一个角色中目录包含以下目录:
- files:用来存放由copy模块或script模块调用的文件。
- templates:用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
- tasks:此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。
- handlers:此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。
- vars:此目录应当包含一个main.yml文件,用于定义此角色用到的变量。
- defaults:此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。
- meta:此目录应当包含一个main.yml文件,用于定义此角色的元数据信息。
例如:一个nginx角色的目录结构可以是:
- .
- └── nginx
- ├── default
- ├── files
- ├── handlers
- ├── meta
- ├── tasks
- ├── templates
- └── vars
多个role目录:
- ├── httpd #http role
- │ ├── default
- │ ├── files
- │ ├── handlers
- │ ├── meta
- │ ├── tasks
- │ ├── templates
- │ └── vars
- └── nginx #nginx role
- ├── default
- ├── files
- ├── handlers
- ├── meta
- ├── tasks
- ├── templates
- └── vars
演示:使用role安装nginx
一、创建对应的目录结构:
- [root@app52 ~]# mkdir -pv roles/nginx/{files,templates,vars,tasks,handlers,meta,default}
- mkdir: 已创建目录 "roles"
- mkdir: 已创建目录 "roles/nginx"
- mkdir: 已创建目录 "roles/nginx/files"
- mkdir: 已创建目录 "roles/nginx/templates"
- mkdir: 已创建目录 "roles/nginx/vars"
- mkdir: 已创建目录 "roles/nginx/tasks"
- mkdir: 已创建目录 "roles/nginx/handlers"
- mkdir: 已创建目录 "roles/nginx/meta"
- mkdir: 已创建目录 "roles/nginx/default”
二、定义变量
- [root@app52 ~]# vi roles/nginx/vars/main.yml
- pkg_name: nginx #安装包名称
- listen_port: 80 #监听端口
三、编写任务
这里可以把任务模块化,最后在main.yml包含它们
- [root@app52 ~]# vi roles/nginx/tasks/yum.yml
- - name: install epel
- yum: name=epel-release state=present
- - name: install nginx pkg
- yum: name={{ pkg_name }} state=present
- [root@app52 ~]# vi roles/nginx/tasks/copy.yml
- - name: copy nginx.conf
- template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- - name: copy index.html
- copy: src=index.html dest=/var/www/html/
- notify: reload
- [root@app52 ~]# vi roles/nginx/tasks/start_service.yml
- - name: start nginx
- service: name=nginx state=restarted
- [root@app52 ~]# vi roles/nginx/tasks/main.yml
- - include: yum.yml
- - include: copy.yml
- - include: start_service.yml
四、准备配置文件以及index.html
- #index.html
- [root@app52 ~]# vi roles/nginx/files/index.html
- <h1>Hello wd</h1>
-
- #配置文件模版
- [root@app52 ~]# vi roles/nginx/templates/nginx.conf.j2
- user nginx;
- worker_processes {{ ansible_processor_vcpus }}; #使用cpu个数作为woeker数量
- error_log /var/log/nginx_error.log crit;
- pid /var/run/nginx.pid;
- include /usr/share/nginx/modules/*.conf;
- worker_rlimit_nofile 65535;
- events {
- worker_connections 1024;
- }
- http {
- include mime.types;
- default_type application/octet-stream;
- sendfile on;
- keepalive_timeout 65;
- gzip on;
- server
- {
- listen {{ listen_port }};
- server_name {{ ansible_all_ipv4_addresses[0] }} ; #使用IP地址作为server name
- root /var/www/html ;
- access_log /var/log/access.log;
- error_log /var/log/error.log;
- }
- }
五、编写handlers
如果在task中使用了notify,则就需要写对应的handlers,上述我使用了reload这个handler,所以这里需要定义:
- [root@app52 ~]# vi roles/nginx/handlers/main.yml
- - name: reload
- service: name=nginx state=reloaded
六、在角色同级目录编写playbook引入角色
- [root@app52 ~]# vi roles/install_nginx.yml
- - hosts: web #指定使用role的主机或主机组
- remote_user: root #指定用户
- roles: #使用的role,可以有多个
- - nginx
最后的目录结构为:
- [root@app52 ~]# tree roles/
- roles/
- ├── install_nginx.yml
- └── nginx
- ├── default
- ├── files
- │ └── index.html
- ├── handlers
- │ └── main.yml
- ├── meta
- ├── tasks
- │ ├── copy.yml
- │ ├── main.yml
- │ ├── start_service.yml
- │ └── yum.yml
- ├── templates
- │ └── nginx.conf.j2
- └── vars
- └── main.yml
- 8 directories, 9 files
七、运行playbook并测试

如红色部分,curl测试nginx 安装成功。