zoukankan      html  css  js  c++  java
  • Ansible--Ansible之Playbook

    Ansible之Playbook

    Playbook介绍

    playbook参考文档

    Playbookad-hoc相比,是一种完全不同的运用ansible的方式,类似与saltstackstate状态文件。ad-hoc无法持久使用,playbook可以持久使用。
    playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务

    Playbook核心元素

    • Hosts 执行的远程主机列表
    • Tasks 任务集
    • Varniables 内置变量或自定义变量在playbook中调用
    • Templates 模板,即使用模板语法的文件,比如配置文件等
    • Handlers 和notity结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
    • tags 标签,指定某条任务执行,用于选择运行playbook中的部分代码。

    Playbook语法

    playbook使用yaml语法格式,后缀可以是yaml,也可以是yml

    • 在单一一个playbook文件中,可以连续三个连子号(---)区分多个play。还有选择性的连续三个点好(...)用来表示play的结尾,也可省略。
    • 次行开始正常写playbook的内容,一般都会写上描述该playbook的功能。
    • 使用#号注释代码。
    • 缩进必须统一,不能空格和tab混用。
    • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行实现的。
    • YAML文件内容和Linux系统大小写判断方式保持一致,是区分大小写的,k/v的值均需大小写敏感
    • k/v的值可同行写也可以换行写。同行使用:分隔。
    • v可以是个字符串,也可以是一个列表
    • 一个完整的代码块功能需要最少元素包括 name: task

    一个简单的示例

    # 创建playbook文件
    [root@ansible ~]# cat playbook01.yml
    ---                       #固定格式
    - hosts: 192.168.1.31     #定义需要执行主机
      remote_user: root       #远程用户
      vars:                   #定义变量
        http_port: 8088       #变量
    
      tasks:                             #定义一个任务的开始
        - name: create new file          #定义任务的名称
          file: name=/tmp/playtest.txt state=touch   #调用模块,具体要做的事情
        - name: create new user
          user: name=test02 system=yes shell=/sbin/nologin
        - name: install package
          yum: name=httpd
        - name: config httpd
          template: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
          notify:                 #定义执行一个动作(action)让handlers来引用执行,与handlers配合使用
            - restart apache      #notify要执行的动作,这里必须与handlers中的name定义内容一致
        - name: copy index.html
          copy: src=/var/www/html/index.html dest=/var/www/html/index.html
        - name: start httpd
          service: name=httpd state=started
      handlers:                                    #处理器:更加tasks中notify定义的action触发执行相应的处理动作
        - name: restart apache                     #要与notify定义的内容相同
          service: name=httpd state=restarted      #触发要执行的动作
    
    #测试页面准备
    [root@ansible ~]# echo "<h1>playbook test file</h1>" >>/var/www/html/index.html
    #配置文件准备
    [root@ansible ~]# cat httpd.conf |grep ^Listen
    Listen {{ http_port }}
    
    #执行playbook, 第一次执行可以加-C选项,检查写的playbook是否ok
    [root@ansible ~]# ansible-playbook playbook01.yml
    PLAY [192.168.1.31] *********************************************************************************************
    TASK [Gathering Facts] ******************************************************************************************
    ok: [192.168.1.31]
    TASK [create new file] ******************************************************************************************
    changed: [192.168.1.31]
    TASK [create new user] ******************************************************************************************
    changed: [192.168.1.31]
    TASK [install package] ******************************************************************************************
    changed: [192.168.1.31]
    TASK [config httpd] *********************************************************************************************
    changed: [192.168.1.31]
    TASK [copy index.html] ******************************************************************************************
    changed: [192.168.1.31]
    TASK [start httpd] **********************************************************************************************
    changed: [192.168.1.31]
    PLAY RECAP ******************************************************************************************************
    192.168.1.31               : ok=7    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
    
    
    # 验证上面playbook执行的结果
    [root@ansible ~]# ansible 192.168.1.31 -m shell -a 'ls /tmp/playtest.txt && id test02'
    192.168.1.31 | CHANGED | rc=0 >>
    /tmp/playtest.txt
    uid=990(test02) gid=985(test02) 组=985(test02)
    
    [root@ansible ~]# curl 192.168.1.31:8088
    <h1>playbook test file</h1>

    Playbook的运行方式

    通过ansible-playbook命令运行
    格式:ansible-playbook <filename.yml> ... [options]

    [root@ansible PlayBook]# ansible-playbook -h
    #ansible-playbook常用选项:
    --check  or -C    #只检测可能会发生的改变,但不真正执行操作
    --list-hosts      #列出运行任务的主机
    --list-tags       #列出playbook文件中定义所有的tags
    --list-tasks      #列出playbook文件中定义的所以任务集
    --limit           #主机列表 只针对主机列表中的某个主机或者某个组执行
    -f                #指定并发数,默认为5个
    -t                #指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags)
    -v                #显示过程  -vv  -vvv更详细

    Playbook中元素属性

    主机与用户

    在一个playbook开始时,最先定义的是要操作的主机和用户

    ---
    - hosts: 192.168.1.31
      remote_user: root

    除了上面的定义外,还可以在某一个tasks中定义要执行该任务的远程用户

    tasks: 
      - name: run df -h
        remote_user: test
        shell: name=df -h

    还可以定义使用sudo授权用户执行该任务

    tasks: 
      - name: run df -h
        sudo_user: test
        sudo: yes
        shell: name=df -h

    tasks任务列表

    每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很清楚的辨别是属于哪一个task的,如果没有定义 nameaction的值将会用作输出信息中标记特定的task
    每一个playbook中可以包含一个或者多个tasks任务列表,每一个tasks完成具体的一件事,(任务模块)比如创建一个用户或者安装一个软件等,在hosts中定义的主机或者主机组都将会执行这个被定义的tasks

    tasks:
      - name: create new file
        file: path=/tmp/test01.txt state=touch
      - name: create new user
        user: name=test001 state=present

    Handlers与Notify

    很多时候当我们某一个配置发生改变,我们需要重启服务,(比如httpd配置文件文件发生改变了)这时候就可以用到handlersnotify了;
    (当发生改动时)notify actions会在playbook的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,但是重新启动的操作知会被执行一次。

    [root@ansible ~]# cat httpd.yml 
    #用于安装httpd并配置启动
    ---
    - hosts: 192.168.1.31
      remote_user: root
    
      tasks:
      - name: install httpd
        yum: name=httpd state=installed
      - name: config httpd
        template: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
        notify:
          - restart httpd
      - name: start httpd
        service: name=httpd state=started
    
      handlers:
        - name: restart httpd
          service: name=httpd state=restarted
    
    #这里只要对httpd.conf配置文件作出了修改,修改后需要重启生效,在tasks中定义了restart httpd这个action,然后在handlers中引用上面tasks中定义的notify。

    Playbook中变量的使用

    环境说明:这里配置了两个组,一个apache组和一个nginx组

    [root@ansible PlayBook]# cat /etc/ansible/hosts
    [apache]
    192.168.1.36
    192.168.1.33
    
    [nginx]
    192.168.1.3[1:2]

    命令行指定变量

    执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量

    [root@ansible PlayBook]# cat variables.yml 
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: install pkg
          yum: name={{ pkg }}
    
    #执行playbook 指定pkg
    [root@ansible PlayBook]# ansible-playbook -e "pkg=httpd" variables.yml

    hosts文件中定义变量

    /etc/ansible/hosts文件中定义变量,可以针对每个主机定义不同的变量,也可以定义一个组的变量,然后直接在playbook中直接调用。注意,组中定义的变量没有单个主机中的优先级高。

    # 编辑hosts文件定义变量
    [root@ansible PlayBook]# vim /etc/ansible/hosts
    [apache]
    192.168.1.36 webdir=/opt/test     #定义单个主机的变量
    192.168.1.33
    [apache:vars]      #定义整个组的统一变量
    webdir=/web/test
    
    [nginx]
    192.168.1.3[1:2]
    [nginx:vars]
    webdir=/opt/web
    
    
    # 编辑playbook文件
    [root@ansible PlayBook]# cat variables.yml 
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: create webdir
          file: name={{ webdir }} state=directory   #引用变量
    
    
    # 执行playbook
    [root@ansible PlayBook]# ansible-playbook variables.yml

    playbook文件中定义变量

    编写playbook时,直接在里面定义变量,然后直接引用,可以定义多个变量;注意:如果在执行playbook时,又通过-e参数指定变量的值,那么会以-e参数指定的为准。

    # 编辑playbook
    [root@ansible PlayBook]# cat variables.yml 
    ---
    - hosts: all
      remote_user: root
      vars:                #定义变量
        pkg: nginx         #变量1
        dir: /tmp/test1    #变量2
    
      tasks:
        - name: install pkg
          yum: name={{ pkg }} state=installed    #引用变量
        - name: create new dir
          file: name={{ dir }} state=directory   #引用变量
    
    
    # 执行playbook
    [root@ansible PlayBook]# ansible-playbook variables.yml
    
    # 如果执行时候又重新指定了变量的值,那么会已重新指定的为准
    [root@ansible PlayBook]# ansible-playbook -e "dir=/tmp/test2" variables.yml

    调用setup模块获取变量

    setup模块默认是获取主机信息的,有时候在playbook中需要用到,所以可以直接调用。常用的参数参考

    # 编辑playbook文件
    [root@ansible PlayBook]# cat variables.yml 
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: create file
          file: name={{ ansible_fqdn }}.log state=touch   #引用setup中的ansible_fqdn
    
    
    # 执行playbook
    [root@ansible PlayBook]# ansible-playbook variables.yml

    独立的变量YAML文件中定义

    为了方便管理将所有的变量统一放在一个独立的变量YAML文件中,laybook文件直接引用文件调用变量即可。

    # 定义存放变量的文件
    [root@ansible PlayBook]# cat var.yml 
    var1: vsftpd
    var2: httpd
    
    # 编写playbook
    [root@ansible PlayBook]# cat variables.yml 
    ---
    - hosts: all
      remote_user: root
      vars_files:    #引用变量文件
        - ./var.yml   #指定变量文件的path(这里可以是绝对路径,也可以是相对路径)
    
      tasks:
        - name: install package
          yum: name={{ var1 }}   #引用变量
        - name: create file
          file: name=/tmp/{{ var2 }}.log state=touch   #引用变量
    
    
    # 执行playbook
    [root@ansible PlayBook]# ansible-playbook  variables.yml

    Playbook中标签的使用

    一个playbook文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t选择指定标签执行,还可以通过--skip-tags选择除了某个标签外全部执行等。

    # 编辑playbook
    [root@ansible PlayBook]# cat httpd.yml 
    ---
    - hosts: 192.168.1.31
      remote_user: root
    
      tasks:
        - name: install httpd
          yum: name=httpd state=installed
          tags: inhttpd
    
        - name: start httpd
          service: name=httpd state=started
          tags: sthttpd
    
        - name: restart httpd
          service: name=httpd state=restarted
          tags: 
            - rshttpd
            - rs_httpd
    
    # 正常执行的结果
    [root@ansible PlayBook]# ansible-playbook httpd.yml 
    
    PLAY [192.168.1.31] **************************************************************************************************************************
    
    TASK [Gathering Facts] ***********************************************************************************************************************
    ok: [192.168.1.31]
    
    TASK [install httpd] *************************************************************************************************************************
    ok: [192.168.1.31]
    
    TASK [start httpd] ***************************************************************************************************************************
    ok: [192.168.1.31]
    
    TASK [restart httpd] *************************************************************************************************************************
    changed: [192.168.1.31]
    
    PLAY RECAP ***********************************************************************************************************************************
    192.168.1.31               : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

    1)通过-t选项指定tags进行执行

    # 通过-t指定tags名称,多个tags用逗号隔开
    [root@ansible PlayBook]# ansible-playbook -t rshttpd httpd.yml 
    
    PLAY [192.168.1.31] **************************************************************************************************************************
    
    TASK [Gathering Facts] ***********************************************************************************************************************
    ok: [192.168.1.31]
    
    TASK [restart httpd] *************************************************************************************************************************
    changed: [192.168.1.31]
    
    PLAY RECAP ***********************************************************************************************************************************
    192.168.1.31               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

    2)通过--skip-tags选项排除不执行的tags

    [root@ansible PlayBook]# ansible-playbook --skip-tags inhttpd httpd.yml 
    
    PLAY [192.168.1.31] **************************************************************************************************************************
    
    TASK [Gathering Facts] ***********************************************************************************************************************
    ok: [192.168.1.31]
    
    TASK [start httpd] ***************************************************************************************************************************
    ok: [192.168.1.31]
    
    TASK [restart httpd] *************************************************************************************************************************
    changed: [192.168.1.31]
    
    PLAY RECAP ***********************************************************************************************************************************
    192.168.1.31               : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

    Playbook中模板的使用

    template模板为我们提供了动态配置服务,使用jinja2语言,里面支持多种条件判断、循环、逻辑运算、比较操作等。其实说白了也就是一个文件,和之前配置文件使用copy一样,只是使用copy,不能根据服务器配置不一样进行不同动态的配置。这样就不利于管理。
    说明:
    1、多数情况下都将template文件放在和playbook文件同级的templates目录下(手动创建),这样playbook文件中可以直接引用,会自动去找这个文件。如果放在别的地方,也可以通过绝对路径去指定。
    2、模板文件后缀名为.j2

    循环参考

    示例:通过template安装httpd

    1)playbook文件编写

    [root@ansible PlayBook]# cat testtmp.yml 
    #模板示例
    ---
    - hosts: all
      remote_user: root
      vars:
        - listen_port: 88    #定义变量
    
      tasks:
        - name: Install Httpd
          yum: name=httpd state=installed
        - name: Config Httpd
          template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf    #使用模板
          notify: Restart Httpd
        - name: Start Httpd
          service: name=httpd state=started
          
      handlers:
        - name: Restart Httpd
          service: name=httpd state=restarted

    2)模板文件准备,httpd配置文件准备,这里配置文件端口使用了变量

    [root@ansible PlayBook]# cat templates/httpd.conf.j2 |grep ^Listen
    Listen {{ listen_port }}

    3)查看目录结构

    # 目录结构
    [root@ansible PlayBook]# tree .
    .
    ├── templates
    │   └── httpd.conf.j2
    └── testtmp.yml
    
    1 directory, 2 files

    4)执行playbook,由于192.168.1.36那台机器是6的系统,模板文件里面的配置文件是7上面默认的httpd配置文件,httpd版本不一样(6默认版本为2.2.15,7默认版本为2.4.6),所以拷贝过去后启动报错。下面使用playbook中的判断语句进行处理;此处先略过

    [root@ansible PlayBook]# ansible-playbook testtmp.yml 
    
    PLAY [all] ******************************************************************************************
    
    TASK [Gathering Facts] ******************************************************************************
    ok: [192.168.1.36]
    ok: [192.168.1.32]
    ok: [192.168.1.33]
    ok: [192.168.1.31]
    
    TASK [Install Httpd] ********************************************************************************
    ok: [192.168.1.36]
    ok: [192.168.1.33]
    ok: [192.168.1.32]
    ok: [192.168.1.31]
    
    TASK [Config Httpd] *********************************************************************************
    changed: [192.168.1.31]
    changed: [192.168.1.33]
    changed: [192.168.1.32]
    changed: [192.168.1.36]
    
    TASK [Start Httpd] **********************************************************************************
    fatal: [192.168.1.36]: FAILED! => {"changed": false, "msg": "httpd: Syntax error on line 56 of /etc/httpd/conf/httpd.conf: Include directory '/etc/httpd/conf.modules.d' not found
    "}
    changed: [192.168.1.32]
    changed: [192.168.1.33]
    changed: [192.168.1.31]
    
    RUNNING HANDLER [Restart Httpd] *********************************************************************
    changed: [192.168.1.31]
    changed: [192.168.1.32]
    changed: [192.168.1.33]
    
    PLAY RECAP ******************************************************************************************
    192.168.1.31               : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.1.32               : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.1.33               : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.1.36               : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

    template之when

    when语句参考

    条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句执行,在task中使用jinja2的语法格式、
    when语句:
    task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法。

    类似这样:

    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语句完善上面的httpd配置

    1)准备两个配置文件,一个centos6系统httpd配置文件,一个centos7系统httpd配置文件。

    [root@ansible PlayBook]# tree templates/
    templates/
    ├── httpd6.conf.j2     #6系统2.2.15版本httpd配置文件
    └── httpd7.conf.j2     #7系统2.4.6版本httpd配置文件
    
    0 directories, 2 files

    2)修改playbook文件,通过setup模块获取系统版本去判断。setup常用模块

    [root@ansible PlayBook]# cat testtmp.yml 
    #when示例
    ---
    - hosts: all
      remote_user: root
      vars:
        - listen_port: 88
    
      tasks:
        - name: Install Httpd
          yum: name=httpd state=installed
        - name: Config System6 Httpd
          template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf
          when: ansible_distribution_major_version == "6"   #判断系统版本,为6便执行上面的template配置6的配置文件
          notify: Restart Httpd
        - name: Config System7 Httpd
          template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf
          when: ansible_distribution_major_version == "7"   #判断系统版本,为7便执行上面的template配置7的配置文件
          notify: Restart Httpd
        - name: Start Httpd
          service: name=httpd state=started
    
      handlers:
        - name: Restart Httpd
          service: name=httpd state=restarted

    3)执行playbook

    [root@ansible PlayBook]# ansible-playbook testtmp.yml
    
    PLAY [all] ******************************************************************************************
    
    TASK [Gathering Facts] ******************************************************************************
    ok: [192.168.1.31]
    ok: [192.168.1.32]
    ok: [192.168.1.33]
    ok: [192.168.1.36]
    
    TASK [Install Httpd] ********************************************************************************
    ok: [192.168.1.32]
    ok: [192.168.1.33]
    ok: [192.168.1.31]
    ok: [192.168.1.36]
    
    TASK [Config System6 Httpd] *************************************************************************
    skipping: [192.168.1.33]
    skipping: [192.168.1.31]
    skipping: [192.168.1.32]
    changed: [192.168.1.36]
    
    TASK [Config System7 Httpd] *************************************************************************
    skipping: [192.168.1.36]
    changed: [192.168.1.33]
    changed: [192.168.1.31]
    changed: [192.168.1.32]
    
    TASK [Start Httpd] **********************************************************************************
    ok: [192.168.1.36]
    ok: [192.168.1.31]
    ok: [192.168.1.32]
    ok: [192.168.1.33]
    
    RUNNING HANDLER [Restart Httpd] *********************************************************************
    changed: [192.168.1.33]
    changed: [192.168.1.31]
    changed: [192.168.1.32]
    changed: [192.168.1.36]
    
    PLAY RECAP ******************************************************************************************
    192.168.1.31               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    192.168.1.32               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    192.168.1.33               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    192.168.1.36               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

    template之with_items

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

    示例1:通过with_items安装多个不同软件

    编写playbook

    [root@ansible PlayBook]# cat testwith.yml 
    # 示例with_items
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: Install Package
          yum: name={{ item }} state=installed   #引用item获取值
          with_items:     #定义with_items
            - httpd
            - vsftpd
            - nginx

    上面tasks写法等同于:

    ---
    - hosts: all
      remote_user: root
      tasks:
        - name: Install Httpd
          yum: name=httpd state=installed
        - name: Install Vsftpd
          yum: name=vsftpd state=installed
        - name: Install Nginx
          yum: name=nginx state=installed

    示例2:通过嵌套子变量创建用户并加入不同的组

    1)编写playbook

    [root@ansible PlayBook]# cat testwith01.yml 
    # 示例with_items嵌套子变量
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: Create New Group
          group: name={{ item }} state=present
          with_items: 
            - group1
            - group2
            - group3 
    
        - name: Create New User
          user: name={{ item.name }} group={{ item.group }} state=present
          with_items:
            - { name: 'user1', group: 'group1' } 
            - { name: 'user2', group: 'group2' } 
            - { name: 'user3', group: 'group3' }

    2)执行playbook并验证

    # 执行playbook
    [root@ansible PlayBook]# ansible-playbook testwith01.yml
    
    # 验证是否成功创建用户及组
    [root@ansible PlayBook]# ansible all -m shell -a 'tail -3 /etc/passwd'
    192.168.1.36 | CHANGED | rc=0 >>
    user1:x:500:500::/home/user1:/bin/bash
    user2:x:501:501::/home/user2:/bin/bash
    user3:x:502:502::/home/user3:/bin/bash
    
    192.168.1.32 | CHANGED | rc=0 >>
    user1:x:1001:1001::/home/user1:/bin/bash
    user2:x:1002:1002::/home/user2:/bin/bash
    user3:x:1003:1003::/home/user3:/bin/bash
    
    192.168.1.31 | CHANGED | rc=0 >>
    user1:x:1002:1003::/home/user1:/bin/bash
    user2:x:1003:1004::/home/user2:/bin/bash
    user3:x:1004:1005::/home/user3:/bin/bash
    
    192.168.1.33 | CHANGED | rc=0 >>
    user1:x:1001:1001::/home/user1:/bin/bash
    user2:x:1002:1002::/home/user2:/bin/bash
    user3:x:1003:1003::/home/user3:/bin/bash

    template之for if

    通过使用forif可以更加灵活的生成配置文件等需求,还可以在里面根据各种条件进行判断,然后生成不同的配置文件、或者服务器配置相关等。

    示例1

    1)编写playbook

    [root@ansible PlayBook]# cat testfor01.yml 
    # template for 示例
    ---
    - hosts: all
      remote_user: root
      vars:
        nginx_vhost_port:
          - 81
          - 82
          - 83
    
      tasks:
        - name: Templage Nginx Config
          template: src=nginx.conf.j2 dest=/tmp/nginx_test.conf

    2)模板文件编写

    # 循环playbook文件中定义的变量,依次赋值给port
    [root@ansible PlayBook]# cat templates/nginx.conf.j2 
    {% for port in nginx_vhost_port %}
    server{
         listen: {{ port }};
         server_name: localhost;
    }
    {% endfor %}

    3)执行playbook并查看生成结果

    [root@ansible PlayBook]# ansible-playbook testfor01.yml
    
    # 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
    [root@linux ~]# cat /tmp/nginx_test.conf 
    server{
         listen: 81;
         server_name: localhost;
    }
    server{
         listen: 82;
         server_name: localhost;
    }
    server{
         listen: 83;
         server_name: localhost;
    }

    示例2

    1)编写playbook

    [root@ansible PlayBook]# cat testfor02.yml 
    # template for 示例
    ---
    - hosts: all
      remote_user: root
      vars:
        nginx_vhosts:
          - web1:
            listen: 8081
            server_name: "web1.example.com"
            root: "/var/www/nginx/web1"
          - web2:
            listen: 8082
            server_name: "web2.example.com"
            root: "/var/www/nginx/web2"
          - web3:
            listen: 8083
            server_name: "web3.example.com"
            root: "/var/www/nginx/web3"
    
      tasks:
        - name: Templage Nginx Config
          template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

    2)模板文件编写

    [root@ansible PlayBook]# cat templates/nginx.conf.j2 
    {% for vhost in nginx_vhosts %}
    server{
         listen:    {{ vhost.listen }};
         server_name:    {{ vhost.server_name }};
         root:   {{ vhost.root }}; 
    }
    {% endfor %}

    3)执行playbook并查看生成结果

    [root@ansible PlayBook]# ansible-playbook testfor02.yml
    
    # 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
    [root@linux ~]# cat /tmp/nginx_vhost.conf 
    server{
         listen:    8081;
         server_name:    web1.example.com;
         root:   /var/www/nginx/web1; 
    }
    server{
         listen:    8082;
         server_name:    web2.example.com;
         root:   /var/www/nginx/web2; 
    }
    server{
         listen:    8083;
         server_name:    web3.example.com;
         root:   /var/www/nginx/web3; 
    }

    示例3

    for循环中再嵌套if判断,让生成的配置文件更加灵活

    1)编写playbook

    [root@ansible PlayBook]# cat testfor03.yml 
    # template for 示例
    ---
    - hosts: all
      remote_user: root
      vars:
        nginx_vhosts:
          - web1:
            listen: 8081
            root: "/var/www/nginx/web1"
          - web2:
            server_name: "web2.example.com"
            root: "/var/www/nginx/web2"
          - web3:
            listen: 8083
            server_name: "web3.example.com"
            root: "/var/www/nginx/web3"
    
      tasks:
        - name: Templage Nginx Config
          template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

    2)模板文件编写

    # 说明:这里添加了判断,如果listen没有定义的话,默认端口使用8888,如果server_name有定义,那么生成的配置文件中才有这一项。
    [root@ansible PlayBook]# cat templates/nginx.conf.j2 
    {% for vhost in nginx_vhosts %}
    server{
         {% if vhost.listen is defined %}
         listen:    {{ vhost.listen }};
         {% else %}
         listen: 8888;
         {% endif %}
         {% if vhost.server_name is defined %}
         server_name:    {{ vhost.server_name }};
         {% endif %}
         root:   {{ vhost.root }}; 
    }
    {% endfor %}

    3)执行playbook并查看生成结果

    [root@ansible PlayBook]# ansible-playbook testfor03.yml
    
    # 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
    [root@linux ~]# cat /tmp/nginx_vhost.conf 
    server{
              listen:    8081;
              root:   /var/www/nginx/web1; 
    }
    server{
              listen: 8888;
              server_name:    web2.example.com;
              root:   /var/www/nginx/web2; 
    }
    server{
              listen:    8083;
              server_name:    web3.example.com;
              root:   /var/www/nginx/web3; 
    }

    上面三个示例的图片展示效果

    例一

    例二

    例三

  • 相关阅读:
    linux进程间通信之消息队列
    本地安装discuz x2.5(论坛站)程序
    缩小IO/CPU瓶颈:linux平台加速编译速度的几种方法
    php mcrypt
    Nginx工作原理和优化、漏洞。
    Linux下两种TCP网络服务器实现方式:循环服务&并发服务
    version `GLIBC_2.14' not found 解决方法.
    Flex Ant自动构建
    函数传指针和传引用
    JEECG 列表行编辑模式下实现文本的xheditor富文本框编辑器
  • 原文地址:https://www.cnblogs.com/yanjieli/p/10969299.html
Copyright © 2011-2022 走看看