Ansible入门系列--playbook

摘要:
此时,如果您确定它没有更改,则可以跳过这些代码片段ansible playbook ttagsnameuseradd通过标记Yml 6。playbook基本组件Hosts:˃playbook中的每个play都设计为使特定主机能够作为指定用户执行任务。
一、playbook基础
1、playbook是由一个或多个"play"组成的列表
2、play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的角色。
Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作 3、Playbook采用YAML语言编写

  

1、playbook图解

Ansible入门系列--playbook第1张

用户通过ansible命令直接调用yml语言写好的playbook,playbook由多条play组成,每条play都有一个任务(task)相对应的操作,

然后调用模块modules,应用在主机清单上,通过ssh远程连接,从而控制远程主机或者网络设备。

2、YAML介绍

YAML是一个可读性高的用来表达资料序列的格式。
    YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。
    Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者

YAML Ain't Markup Language,即YAML不是XML。
不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)

特性
    YAML的可读性好
    YAML和脚本语言的交互性好
    YAML使用实现语言的数据类型
    YAML有一个一致的信息模型
    YAML易于实现
    YAML可以基于流来处理
    YAML表达能力强,扩展性好

更多的内容及规范参见:http://www.yaml.org

3、YAML语法简介

1、在单一文件中,可用连续三个连字号(---)区分多个文件。
2、另外,还有选择性的连续三个点号( ... )用来表示文件结尾
3、次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
4、使用#号注释代码
5、缩进必须是统一的,不能空格和tab混用
6、缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
7、YAML文件内容是区别大小写的,k/v的值均需大小写敏感
8、多个k/v可同行写也可换行写,同行使用:分隔
9、v可是个字符串,也可是另一个列表[]
10、一个完整的代码块功能需最少元素需包括 name 和 task
11、一个name只能包括一个task
12、YAML文件扩展名通常为yml或yaml

 

4、YAML语法简介

 一般语法

List:列表,其所有元素均使用“-”打头
      列表代表同一类型的元素
示例:
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango

Dictionary:字典,通常由多个key与value构成 键值对
示例:
---
# An employee record
name: Example Developer
job: Developer
skill: Elite

也可以将key:value放置于{}中进行表示,用,分隔多个key:value
示例:
---
# An employee record
{name: Example Developer, job: Developer, skill: Elite}  有空格

  

三种常见的数据交换格式

Ansible入门系列--playbook第2张

 示例:

YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。
其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔
示例
    name: John Smith
    age: 41
    gender: Male
    spouse:
      name: Jane Smith
      age: 37
      gender: Female
    children:
      - name: Jimmy Smith
        age: 17
        gender: Male
      - name: Jenny Smith
        age 13
        gender: Female

  

 

5、Playbook核心元素

Hosts          执行的远程主机列表(应用在哪些主机上)

Tasks          任务集

Variables      内置变量或自定义变量在playbook中调用

Templates模板  可替换模板文件中的变量并实现一些简单逻辑的文件

Handlers和notify结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行

tags标签       指定某条任务执行,用于选择运行playbook中的部分代码。
                ansible具有幂等性,因此会自动跳过没有变化的部分,
                即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。
                此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
                ansible-playbook -t tagsname useradd.yml

 

6、playbook基础组件

Hosts:
    > playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。
      hosts用于指定要执行指定任务的主机,须事先定义在主机清单中

    > 可以是如下形式:
        one.example.com
        one.example.com:two.example.com
        192.168.1.50
        192.168.1.*
    > Websrvs:dbsrvs       或者,两个组的并集
    > Websrvs:&dbsrvs      与,两个组的交集
    > webservers:!phoenix  在websrvs组,但不在dbsrvs组
    示例: - hosts: websrvs:dbsrvs

remote_user: 
    可用于Host和task中。
    也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;
    此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
    - hosts: websrvs
        remote_user: root   (可省略,默认为root)  以root身份连接
      tasks:    指定任务
    - name: test connection
        ping:
        remote_user: magedu
        sudo: yes           默认sudo为root
        sudo_user:wang      sudo为wang
    
task列表和action
    任务列表task:由多个动作,多个任务组合起来的,每个任务都调用的模块,一个模块一个模块执行
    1> play的主体部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,
       即在所有主机上完成第一个任务后,再开始第二个任务

    2> task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。
       模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致

    3> 每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。
       如果未提供name,则action的结果将用于输出

  

7、Tasks任务列表

两种格式:
    (1) action: module arguments
    (2) module: arguments 建议使用  模块: 参数
    注意:shell和command模块后面跟命令,而非key=value

某任务的状态在运行后为changed时,可通过"notify"通知给相应的handlers

任务可以通过"tags"打标签,可在ansible-playbook命令上使用-t指定进行调用
示例:
tasks:
  - name: disable selinux   描述
    command: /sbin/setenforce 0   模块名: 模块对应的参数

  

8、忽略错误

如果命令或脚本的退出码不为零,可以使用如下方式替代

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true  
    转错为正  如果命令失败则执行 true

或者使用ignore_errors来忽略错误信息
tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True  忽略错误

 

9、运行playbook

 常用选项:-C dry-run   、  --list-hosts、--list-tags、--list-tasks

运行playbook的方式
    ansible-playbook <filename.yml> ... [options]

常见选项
    --check -C       只检测可能会发生的改变,但不真正执行操作 
                     (只检查语法,如果执行过程中出现问题,-C无法检测出来)
                     (执行playbook生成的文件不存在,后面的程序如果依赖这些文件,也会导致检测失败)
    --list-hosts     列出运行任务的主机
    --list-tags      列出tag  (列出标签)
    --list-tasks     列出task (列出任务)
    --limit 主机列表 只针对主机列表中的主机执行
    -v -vv -vvv      显示过程

示例
    ansible-playbook hello.yml --check 只检测
    ansible-playbook hello.yml --list-hosts  显示运行任务的主机
    ansible-playbook hello.yml --limit websrvs  限制主机

  

10、Playbook VS ShellScripts

脚本内容:

#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp /tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
service httpd start
chkconfig httpd on

  

Playbook实现:

---
- hosts: all
  remote_user: root
  
  tasks:
    - name: "安装Apache"
      yum: name=httpd       yum模块:安装httpd
    - name: "复制配置文件"
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/  copy模块: 拷贝文件
    - name: "复制配置文件"
      copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/  
    - name: "启动Apache,并设置开机启动"
      service: name=httpd state=started enabled=yes   service模块: 启动服务 

  

二、playbook实例

1、Playbook 创建用户

---
- hosts: all
  remote_user: root

  tasks:
    - name: create mysql user
      user: name=mysql system=yes uid=36
    - name: create a group
      group: name=httpd system=yes

  

2、安装httpd服务

- hosts: websrvs
  remote_user: root

  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
    - name: start service
      service: name=httpd state=started enabled=yes

  

3、安装nginx服务,并触发重启操作

- hosts: all
  remote_user: root

  tasks:
    - name: add group nginx
      user: name=nginx state=present
    - name: add user nginx
      user: name=nginx state=present group=nginx
    - name: Install Nginx
      yum: name=nginx state=present
    - name: Start Nginx
      service: name=nginx state=started enabled=yes

  以上是正常安装一个nginx服务,当时我们对于需要修改配置文件后重启服务这样的需求,改怎么来满足呢?那就是handlers和notify咯。

handlers和notify结合使用触发条件

Handlers 实际上就是一个触发器
是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作

Notify此action可用于在每个play的最后被触发,
这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也即notify中调用handler中定义的操作

  

- hosts: websrvs
  remote_user: root

  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd  # 名称和下面handlers里面的一致!!!
    - name: ensure apache is running
      service: name=httpd state=started enabled=yes
  
  handlers:
    - name: restart httpd
      service: name=httpd state=restarted

  

三、playbook进阶

1、tags的使用

tage: 添加标签 
可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行
多个动作可以使用同一个标签
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
      tags: install 
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: conf
    - name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes

  

执行:

ansible-playbook –t install,conf httpd.yml   指定执行install,conf 两个标签

  注意:如果多个tags的名称一样,那么这几个task都会被执行。

- hosts: testsrv
  remote_user: root
  tags: inshttpd   针对整个playbook添加tags
  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: rshttpd
      notify: restart httpd
  handlers:
    - name: restart httpd
      service: name=httpd status=restarted

  

2、Playbook中变量的使用

变量名:仅能由字母、数字和下划线组成,且只能以字母开头
1、变量来源:
    1> ansible setup facts 远程主机的所有变量都可直接调用 (系统自带变量)
       setup模块可以实现系统中很多系统信息的显示
                可以返回每个主机的系统信息包括:版本、主机名、cpu、内存
       ansible all -m setup -a 'filter="ansible_nodename"'     查询主机名
       ansible all -m setup -a 'filter="ansible_memtotal_mb"'  查询主机内存大小
       ansible all -m setup -a 'filter="ansible_distribution_major_version"'  查询系统版本
       ansible all -m setup -a 'filter="ansible_processor_vcpus"' 查询主机cpu个数
    
    2> 在/etc/ansible/hosts(主机清单)中定义变量
        普通变量:主机组中主机单独定义,优先级高于公共变量(单个主机 )
        公共(组)变量:针对主机组中所有主机定义统一变量(一组主机的同一类别)
    
    3> 通过命令行指定变量,优先级最高
       ansible-playbook –e varname=value
    
    4> 在playbook中定义
       vars:
        - var1: value1
        - var2: value2
    
    5> 在独立的变量YAML文件中定义
    
    6> 在role中定义

2、变量命名:
    变量名仅能由字母、数字和下划线组成,且只能以字母开头

3、变量定义:key=value
    示例:http_port=80

4、变量调用方式:
    1> 通过{{ variable_name }} 调用变量,且变量名前后必须有空格,有时用“{{ variable_name }}”才生效

    2> ansible-playbook –e 选项指定,(外部传入的方式)
       ansible-playbook test.yml -e "hosts=www user=magedu"

5、在主机清单中定义变量,在ansible中使用变量(内部定义后直接使用的方式)
vim /etc/ansible/hosts

#针对单台主机
[appsrvs]
192.168.38.17 http_port=817 name=www 
192.168.38.27 http_port=827 name=web


# 针对一组主机的变量
[appsrvs:vars]
make="-"

6、调用变量
ansible appsrvs -m hostname -a'name={{name}}'  更改主机名为各自被定义的变量 
ansible appsrvs -m hostname -a 'name={{name}}{{mark}}{{http_port}}'  ansible调用变量


7、将变量写进单独的配置文件中引用
vim vars.yml
pack: vsftpd
service: vsftpd

引用变量文件
vars_files:
  - vars.yml 

  变量优先级高低:  命令行优先级最高(-e指定)> playbook里面定义的vars优先级其次 > hosts里面定义给主机的变量 > hosts里面定义给groups:vars的变量

  

变量使用范例

A、-e变量使用

- hosts: websrvs
  remote_user: root
vars:
  - username: user1
  - groupname: group1
tasks:
  - name: create group
    group: name={{ groupname }} state=present
  - name: create user
    user: name={{ username }} state=present

ansible-playbook var.yml
ansible-playbook -e "username=user2 groupname=group2” var2.yml

  

B、setup变量使用

- hosts: websrvs
  remote_user: root
  tasks:
    - name: create log file
      file: name=/var/log/ {{ ansible_fqdn }} state=touch

ansible-playbook var.yml

  

C、playbook变量使用

- hosts: websrvs
  remote_user: root
vars:
  - username: user1
  - groupname: group1
tasks:
  - name: create group
    group: name={{ groupname }} state=present
  - name: create user
    user: name={{ username }} state=present

ansible-playbook var.yml
ansible-playbook -e "username=user2 groupname=group2” var2.yml

  注意:-e变量优先级高于playbook的!

D、主机变量hosts文件变量

主机变量
可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用

示例:
[websrvs]
www1.magedu.com http_port=80 maxRequestsPerChild=808
www2.magedu.com http_port=8080 maxRequestsPerChild=909

组变量
组变量是指赋予给指定组内所有主机上的在playbook中可用的变量

示例:
    [websrvs]
    www1.magedu.com
    www2.magedu.com

    [websrvs:vars]
    ntp_server=ntp.magedu.com
    nfs_server=nfs.magedu.com

普通变量
    [websrvs]
    192.168.99.101 http_port=8080 hname=www1
    192.168.99.102 http_port=80 hname=www2

公共(组)变量
    [websvrs:vars]
    http_port=808
    mark="_"
    [websrvs]
    192.168.99.101 http_port=8080 hname=www1
    192.168.99.102 http_port=80 hname=www2
    ansible websvrs –m hostname –a ‘name={{ hname }}{{ mark }}{{ http_port }}’

命令行指定变量:
    ansible websvrs –e http_port=8000 –m hostname –a'name={{ hname }}{{ mark }}{{ http_port }}'

  

E、使用文件变量

cat vars.yml
var1: httpd
var2: nginx

cat var.yml
- hosts: web
  remote_user: root
  vars_files:
    - vars.yml
  tasks:
    - name: create httpd log
      file: name=/app/{{ var1 }}.log state=touch
    - name: create nginx log
      file: name=/app/{{ var2 }}.log state=touch
      
hostname app_81.magedu.com  hostname 不支持"_",认为"_"是非法字符
hostnamectl set-hostname app_80.magedu.com  可以更改主机名

  

F、invertory变量

组嵌套
inventory中,组还可以包含其它的组,并且也可以向组中的主机指定变量。
这些变量只能在ansible-playbook中使用,而ansible命令不支持

示例:
    [apache]
    httpd1.magedu.com
    httpd2.magedu.com
    
    [nginx]
    ngx1.magedu.com
    ngx2.magedu.com
    
    [websrvs:children]
    apache
    nginx
    
    [webservers:vars]
    ntp_server=ntp.magedu.com


invertory参数:用于定义ansible远程连接目标主机时使用的参数,而非传递给playbook的变量
    ansible_ssh_host
    ansible_ssh_port
    ansible_ssh_user
    ansible_ssh_pass
    ansbile_sudo_pass

示例:
    cat /etc/ansible/hosts
    [websrvs]
    192.168.0.1 ansible_ssh_user=root ansible_ssh_pass=magedu
    192.168.0.2 ansible_ssh_user=root ansible_ssh_pass=magedu

  

invertory参数:

inventory参数
ansible基于ssh连接inventory中指定的远程主机时,还可以通过参数指定其交互方式;
这些参数如下所示:
ansible_ssh_host
The name of the host to connect to, if different from the alias you wishto give to it.

ansible_ssh_port
The ssh port number, if not 22

ansible_ssh_user
The default ssh user name to use.

ansible_ssh_pass
The ssh password to use (this is insecure, we strongly recommendusing --ask-pass or SSH keys)

ansible_sudo_pass
The sudo password to use (this is insecure, we strongly recommendusing --ask-sudo-pass)

ansible_connection
Connection type of the host. Candidates are local, ssh or paramiko.
The default is paramiko before Ansible 1.2, and 'smart' afterwards which
detects whether usage of 'ssh' would be feasible based on whether
ControlPersist is supported.

ansible_ssh_private_key_file
Private key file used by ssh. Useful if using multiple keys and you don't want to use SSH agent.

ansible_shell_type
The shell type of the target system. By default commands are formatted
using 'sh'-style syntax by default. Setting this to 'csh' or 'fish' will cause
commands executed on target systems to follow those shell's syntax instead.

ansible_python_interpreter
The target host python path. This is useful for systems with more
than one Python or not located at "/usr/bin/python" such as *BSD, or where /usr/bin/python

is not a 2.X series Python. We do not use the "/usr/bin/env" mechanism as that requires the remote user's

path to be set right and also assumes the "python" executable is named python,where the executable might

be named something like "python26".
ansible\_*\_interpreter

Works for anything such as ruby or perl and works just like ansible_python_interpreter.

This replaces shebang of modules which will run on that host.

  

3、模板templates

文本文件,嵌套有脚本(使用模板编程语言编写) 借助模板生成真正的文件
Jinja2语言,使用字面量,有下面形式
    字符串:使用单引号或双引号
    数字:整数,浮点数
    列表:[item1, item2, ...]
    元组:(item1, item2, ...)
    字典:{key1:value1, key2:value2, ...}
    布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When

  

Jinja2介绍

1、字面量

字面量
    1> 表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python对象。如“Hello World”
    双引号或单引号中间的一切都是字符串。
    2> 无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如4242.23
    3> 数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在Python 里, 42 和 42.0 是不一样的

  

 2、算术运算

Jinja 允许你用计算值。这在模板中很少用到,但为了完整性允许其存在
支持下面的运算符
    +:把两个对象加到一起。
       通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。
       无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2
    -:用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1
    /:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }}
    //:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
    %:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
    *:用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。
       也可以用于重 复一个字符串多次。{{ ‘=’ * 80 }} 会打印 80 个等号的横条
    **:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8

  

3、逻辑操作

比较操作符
== 比较两个对象是否相等
!= 比较两个对象是否不等
> 如果左边大于右边,返回 true
>= 如果左边大于等于右边,返回 true
< 如果左边小于右边,返回 true
<= 如果左边小于等于右边,返回 true

逻辑运算符
对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式
and
    如果左操作数和右操作数同为真,返回 true
or
    如果左操作数和右操作数有一个为真,返回 true
not
    对一个表达式取反(见下)
(expr)
    表达式组

['list', 'of', 'objects']:
一对中括号括起来的东西是一个列表。列表用于存储和迭代序列化的数据。
例如 你可以容易地在 for循环中用列表和元组创建一个链接的列表
    <ul>
    {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'), ('downloads.html',
'Downloads')] %}
        <li><a href="http://t.zoukankan.com/{{ href }}">{{ caption }}</a></li>
    {% endfor %}
    </ul>
    ('tuple', 'of', 'values'):

元组与列表类似,只是你不能修改元组。
如果元组中只有一个项,你需要以逗号结尾它。
元组通常用于表示两个或更多元素的项。更多细节见上面的例子
    {'dict': 'of', 'key': 'and', 'value': 'pairs'}:

Python 中的字典是一种关联键和值的结构。
键必须是唯一的,并且键必须只有一个 值。
字典在模板中很少使用,罕用于诸如 xmlattr() 过滤器之类
    true / false:
    true 永远是 true ,而 false 始终是 false

  

template 的使用

1、模板的位置

template功能:根据模块文件动态生成对应的配置文件
   > template文件必须存放于templates目录下,且命名为 .j2 结尾
   > yaml/yml 文件需和templates目录平级,目录结构如下:
    ./
     ├── temnginx.yml
     └── templates
        └── nginx.conf.j2

  

2、模板的使用

示例:利用template 同步nginx配置文件
准备templates/nginx.conf.j2文件
vim temnginx.yml
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

ansible-playbook temnginx.yml

  

3、模板中使用变量

修改文件nginx.conf.j2 下面行为
worker_processes {{ ansible_processor_vcpus }};

cat temnginx2.yml
- hosts: websrvs
  remote_user: root
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

ansible-playbook temnginx2.yml

  

4、模板中使用算术运算

算法运算:
示例:
    vim nginx.conf.j2
    worker_processes {{ ansible_processor_vcpus**2 }};
    worker_processes {{ ansible_processor_vcpus+2 }};

  

5、模板中使用条件运算

条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,
通过when语句实现,在task中使用,jinja2的语法格式

when语句
    在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
示例:
tasks:
  - name: "shutdown RedHat flavored systems"
    command: /sbin/shutdown -h now
    when: ansible_os_family == "RedHat"  当系统属于红帽系列,执行command模块 
 
when语句中还可以使用Jinja2的大多"filter",
例如要忽略此前某语句的错误并基于其结果(failed或者success)运行后面指定的语句,
可使用类似如下形式:
tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped

此外,when语句中还可以使用facts或playbook中定义的变量

  

示例:
tasks:
  - name: install conf file to centos7
    template: src=nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
    when: ansible_distribution_major_version == "7"
  - name: install conf file to centos6
    template: src=nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
    when: ansible_distribution_major_version == "6"

  

4、迭代

迭代:当有需要重复性执行的任务时,可以使用迭代机制
    > 对迭代项的引用,固定变量名为"item"
    > 要在task中使用with_items给定要迭代的元素列表
    > 列表格式:
         字符串
         字典

A、迭代范例
示例: 创建用户
- name: add several users
  user: name={{ item }} state=present groups=wheel   #{{ item }} 系统自定义变量
  with_items:       # 定义{{ item }} 的值和个数
    - testuser1
    - testuser2

上面语句的功能等同于下面的语句:
- name: add user testuser1
  user: name=testuser1 state=present groups=wheel
- name: add user testuser2
  user: name=testuser2 state=present groups=wheel
  
with_items中可以使用元素还可为hashes
示例:
- name: add several users
  user: name={{ item.name }} state=present groups={{ item.groups }}
  with_items:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }

ansible的循环机制还有更多的高级功能,具体请参见官方文档
http://docs.ansible.com/playbooks_loops.html 

  

- name: 使用ufw模块来管理哪些端口需要开启
  ufw:
  rule: “{{ item.rule }}”
  port: “{{ item.port }}”
  proto: “{{ item.proto }}”
  with_items:
    - { rule: 'allow', port: 22, proto: 'tcp' }
    - { rule: 'allow', port: 80, proto: 'tcp' }
    - { rule: 'allow', port: 123, proto: 'udp' }

- name: 配置网络进出方向的默认规则
  ufw:
  direction: "{{ item.direction }}"
  policy: "{{ item.policy }}"
  state: enabled
  with_items:
    - { direction: outgoing, policy: allow }
    - { direction: incoming, policy: deny }

  

5、循环

{% for vhost in nginx_vhosts %}

server {    #重复执行server代码
listen {{ vhost.listen | default('80 default_server') }};

{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }};
{% endif %}

{% if vhost.root is defined %}
root {{ vhost.root }};
{% endif %}

{% endfor %}

  

1、范例

// temnginx.yml
---
- hosts: testweb
  remote_user: root
  vars:      # 调用变量
    nginx_vhosts:
      - listen: 8080  #列表 键值对


//templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}  
server {
  listen {{ vhost.listen }}
}
{% endfor %}

生成的结果
server {
  listen 8080
}

  

2、范例

// temnginx.yml
---
- hosts: mageduweb
  remote_user: root
  vars:
    nginx_vhosts:
      - web1
      - web2
      - web3
  tasks:
    - name: template config
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

// templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
    listen {{ vhost }}
}
{% endfor %}

生成的结果:
server {
    listen web1
}
server {
    listen web2
}
server {
    listen web3
}

  

免责声明:文章转载自《Ansible入门系列--playbook》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇lisp安装使用[蓝牙] 3、 剖析BLE心率检测工程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python代码编写规范,你真的会吗?

前言 本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。作者:yangjiajia123456  最近两年的工作都是和运维相关,有时运维人员也会写一些python程序,但基本上都没有遵循相应的代码规范,一向粗暴,能用就行,既不考虑可读性也不考虑可维护性,作为一个开发人员有时候看他们写代码就...

Git连接GitHub仓库详解

创建SSH Key 1.注册GitHub账号。 2.创建SSH Key。windows + R键同时按,打开运行命令窗口,输入.进入家目录。 看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果有(那就奇了怪了!),一般第一次使用是没有的,真有的话可以直接跳过下面的命令。 打开命令行,执行命令:ssh-keygen -t rsa -C...

centos下面配置key登录

centos下需要配置使用key登录,并且要禁止root登录 下面的操作都是用root来设置的 1.添加新用户 例如用户名leisiyuan useradd leisiyuan 2.设置密码 passwd leisyuan 3.给新用户添加到root权限组 运行visudo命令,找到root ALL=(ALL) ALL,在下面添加一行 ,然后保存即可 le...

Gitlab项目用ssh克隆

Gitlab项目用ssh克隆 1、 新建一个文件夹并用git bash here 打开 2、 在git bash here 输入命令行 ssh-keygen –t rsa –C“邮箱名” 3、 4、 出来提示.ssh在哪里的路径,回车两次 5、 在显示的路径中找到.ssh ,在.ssh中找到id_rsa.pub 6、 复制里面所有代码,到gitlab中se...

ssh-keygen生成公钥私钥

  最近公司要求使用跳板机连接服务器,导致原有的用户名/密码连接部署方式无法使用,故使用ssh-keygen生成公钥私钥进行免密登录;   1.说明:   '客户端'指的是你所使用的本地机器;   '服务端'指的是远程你要连接的机器;   2.在服务端生成公钥、私钥命令: ssh-keygen -t rsa   一路回车即可,以root账号为例,该命令将...

Nginx报错:Sorry, the page you are looking for is currently unavailable. Please try again later.

查看了进程, nginx, php-fpm都在运行, 排除程序错误, 那么就是配置的问题了. 一个可能的错误, 是由于配置中的fastcgi_pass 配置错了 错误的配置如下 server { listen 80; server_name localhost; #charset koi8-r; #a...