Ansible之playbook拓展

  一、handlers和notify结合使用触发条件

  handlers同tasks是属同级,相当于一个特殊任务列表,这些任务同前文说的tasks里的任务没有本质的不同,用于当关注的资源发生变化时,才会采取一定的操作。notify此action可用于在每一个play的最后被触发,这样可避免多次有改变发生时都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作,在notify中列出的操作称为handler,换句话说当所关注的资源发生变化时notify将调用handlers中定义的操作。其中notify所在任务就是被监控的任务资源变化的任务,notify可以调用多个handlers定义的操作,一个handlers里可以定义很多任务。

---
- hosts: websers
  remote_user: root

  tasks:
    - name: create apache group
      group: name=apache gid=80 system=yes
    - name: create apache user
      user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html 
    - name: install httpd
      yum: name=httpd
    - name: copy config file
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd service

    - name: start httpd service
      service: name=httpd state=started enabled=yes

  handlers:
    - name: restart httpd service
      service: name=httpd state=restarted   

  说明:notify后指定的名称必须要和handlers里的任务名称相同,如不同handlers所定义的任务将不会执行,相当于没有notify调用handlers里的任务。

  在某些情况下,我们可能同时需要调用多个handlers,或者需要使用handlers其他handlers,ansible可以很简单的实现这些功能,如下所示

  1)调用多个handlers

---
- hosts: websers
  remote_user: root

  tasks:
    - name: create apache group
      group: name=apache gid=80 system=yes
    - name: create apache user
      user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html 
    - name: install httpd
      yum: name=httpd
    - name: copy config file
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
      notify: 
        - restart httpd service
        - check httpd process

    - name: start httpd service
      service: name=httpd state=started enabled=yes

  handlers:
    - name: restart httpd service
      service: name=httpd state=restarted
    - name: check httpd process                                                                                      
      shell: /usr/bin/killall -0 httpd &> /tmp/httpd.log

  说明:调用多个handlers我们需要在notify中写成列表的形式,同样我们被触发的任务名称需要同handlers里的被调用的任务名称完全相同

  2)handlers调用handlers

---
- hosts: websers
  remote_user: root

  tasks:
    - name: create apache group
      group: name=apache gid=80 system=yes
    - name: create apache user
      user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html 
    - name: install httpd
      yum: name=httpd
    - name: copy config file
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd service

    - name: start httpd service
      service: name=httpd state=started enabled=yes

  handlers:
    - name: restart httpd service
      service: name=httpd state=restarted
      notify: check httpd process                                                                                    
    - name: check httpd process
      shell: /usr/bin/killall -0 httpd &> /tmp/httpd.log

  说明:handlers调用handlers,则直接在handlers中使用notify选项就可以。

在使用handlers我们需要注意一下几点:

  1)handlers只有在其所在任务被执行时才会被运行,handlers定义的任务它不会像task任务那样,自动会从上至下依次执行,它只会被notify所在的任务发生状态改变时才会触发handlers 的任务执行,如果一个任务中定义了notify调用handlers,但由于条件的判断等原因,该任务尚未执行,那么notify调用的handlers同样也不会执行。

  2)handlers只会在play的末尾运行一次;如果想要在一个playbook的中间运行handlers,则需要使用meta模块来实现,如:-mate: flush_handlers

  二、playbook中变量的使用

ansible中变量的命名规范同其他语言或系统中变量命名规则非常类似。变量名以英文大小写字母开头,中间可以包含下划线和数字,ansible变量的来源有很多,具体有以下几点:

  1)ansible setup模块,这个模块可以从远程主机上获取很多远程主机的基本信息,它所返回的所有变量都可以直接调用,有关setup说明请参考本人博客https://www.cnblogs.com/qiuhom-1874/p/11853512.html

  2)在/etc/ansible/hosts中定义,此文件是ansible执行名时默认加载的主机清单文件,在里面除了可定义我们要管理的主机外,我们还可以定义针对单个主机定义单独的变量,我们把针对单独某一台主机定义的变量叫做普通变量(也可叫做主机变量);还有一种变量它不是针对单独一个主机,它针对某一个组里的所有主机,我们把这种变量叫做公共组变量。主机清单中定义的变量优先级是普通变量高于公共变量。

    2.1)主机变量,可以在主机清单中定义主机时为其添加主机变量以便于在playbook中使用,如下所示

[websers]
192.168.0.128 http_port=80 maxRequestsPerChild=808
192.168.0.218 http_port=81 maxRequestsPerChild=909

    2.2)主机组变量,组变量是指定赋予给指定组内所有主机上的在playbook中可使用的变量,如下所示

[websers]
192.168.0.128 http_port=80 
192.168.0.218 http_port=81 
[websers:vars]
maxRequestsPerChild=909

  3)通过命令行指定变量(-e指定变量赋值,可以说多个但需要用引号引起或者一个变量用一个-e指定赋值),这种在命令行指定的优先级最高。如下所示

ansible-playbook -e 'package_name1=httpd package_name2=nginx' test_vars.yml

  4)在playbook中定义变量,最常见的定义变量的方法是使用vars代码块,如下所示

---
- hosts: websers
  remote_user: root
  vars:
    - abc: xxx 
    - bcd: aaa  

  5)在独立的变量yml文件中定义,在playbook中使用vars_files代码块引用其变量文件,如下所示

[root@test ~]#cat vars.yml 
---
package_name1: vsftpd
package_name2: nginx
[root@test ~]#cat test_vars.yml 
---
- hosts: websers
  remote_user: root
  vars_files:
    - vars.yml
  tasks:
    - name: install package1
      yum: name={{ package_name1 }}
    - name: install package2
      yum: name={{ package_name2 }}
[root@test ~]#

  6)在role中定义,这个后续说到角色在做解释

  变量的调用方式:第一种在playbook中使用变量需要用“{{}}”将变量括起来,表示括号里的内容是一个变量,且前后必须有空格,有时用“{{  variable_name }}"才生效;第二种是ansible-playbook -e 选项指定其变量,ansible-playbook -e "hosts=www user=xxxx" test.yml

  在主机清单中定义变量的方法虽然简单直观,但是当所需要定义的变量有很多时,并且被多台主机使用时,这种方法显得非常麻烦,事实上ansible的官方手册中也不建议我们把变量直接定义到hosts文件中;在执行ansible命令时,ansible会默认会从/etc/ansible/host_vars/和/etc/ansible/group_vars/两个目录下读取变量定义文件,如果/etc/ansible/下没有以上这两个目录,我们可以手动创建,并且可以在这两个目录下创建与hosts文件中的主机名或主机组同名的文件来定义变量。比如我们要给192.168.0.218 这个主机定义个变量文件,我们可以在/etc/ansible/host_vars/目录下创建一个192.168.0.218的空白文件,然后在文件中以ymal语法来定义所需变量即可。如下所示

[root@test ~]#tail -6 /etc/ansible/hosts 
## db-[99:101]-node.example.com
[websers]
192.168.0.128 
192.168.0.218 
[appsers]
192.168.0.217
[root@test ~]#cat /etc/ansible/host_vars/192.168.0.218 
---
file1: abc
file2: bcd
[root@test ~]#cat test.yml 
---
- hosts: 192.168.0.218
  remote_user: root
  
  tasks:
    - name: touch file1
      file: name={{ file1 }} state=touch
    - name: toch file2
      file: name={{ file2 }} state=touch
[root@test ~]#ansible-playbook test.yml 

PLAY [192.168.0.218] ************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218]

TASK [touch file1] **************************************************************************************************
changed: [192.168.0.218]

TASK [toch file2] ***************************************************************************************************
changed: [192.168.0.218]

PLAY RECAP **********************************************************************************************************
192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   

[root@test ~]#ansible 192.168.0.218 -m shell -a 'ls -l /root'
192.168.0.218 | SUCCESS | rc=0 >>
总用量 12
-rw-r--r--. 1 root   root    0 11月 17 16:49 abc
-rw-r--r--. 1 root   root    0 11月 17 16:49 bcd
drwxr-xr-x. 2 qiuhom root 4096 11月 11 19:18 scripts
drwxr-xr-x. 3 qiuhom root 4096 11月 11 19:28 test
-rw-r--r--. 1 root   root   57 11月 13 19:15 test_cron_file

[root@test ~]#

  说明:可看到我们定义在/etc/ansible/host_vars/下的主机变量文件中的变量生效了。

同理,我们要想针对某个组的主机定义一些变量,我们只需要在/etc/ansible/group_vars/目录下创建与主机清单中的主机组同名的文件即可。

  三、使用高阶变量

  对于普通变量,例如由ansible命令行设定的,hosts文件中定义的以及playbook中定义的和变量文件中定义的,这些变量都被称为普通变量或者叫简单变量,我们可以在playbook中直接用双大括号加变量名来读取变量内容;除此以外ansible还有数组变量或者叫做列表变量,如下所示:

[root@test ~]#cat vars.yml 
---
packages_list:
  - vsftpd
  - nginx
[root@test ~]#

  列表定义完成后我们要使用其中的变量可以列表名加下标的方式去访问,有点类似shell脚本里的数组的使用,如下所示

[root@test ~]#cat test.yml 
---
- hosts: 192.168.0.218
  remote_user: root
  
  vars_files:
    - vars.yml
  tasks:
    - name: touch file
      file: name={{ packages_list[0] }} state=touch
    - name: mkdir dir
      file: name={{ packages_list[1] }} state=directory
[root@test ~]#

  说明:我们要使用列表中的第一个元素变量,我们可以写成vars_list[0],使用第二个变量则下标就是1,依此类推

[root@test ~]#ansible *218 -m shell -a 'ls -l /root'
192.168.0.218 | SUCCESS | rc=0 >>
总用量 12
-rw-r--r--. 1 root   root    0 11月 17 16:49 abc
-rw-r--r--. 1 root   root    0 11月 17 16:49 bcd
drwxr-xr-x. 2 qiuhom root 4096 11月 11 19:18 scripts
drwxr-xr-x. 3 qiuhom root 4096 11月 11 19:28 test
-rw-r--r--. 1 root   root   57 11月 13 19:15 test_cron_file

[root@test ~]#ansible-playbook test.yml 

PLAY [192.168.0.218] ************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218]

TASK [touch file] ***************************************************************************************************
changed: [192.168.0.218]

TASK [mkdir dir] ****************************************************************************************************
changed: [192.168.0.218]

PLAY RECAP **********************************************************************************************************
192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   

[root@test ~]#ansible *218 -m shell -a 'ls -l /root'
192.168.0.218 | SUCCESS | rc=0 >>
总用量 16
-rw-r--r--. 1 root   root    0 11月 17 16:49 abc
-rw-r--r--. 1 root   root    0 11月 17 16:49 bcd
drwxr-xr-x. 2 root   root 4096 11月 17 17:23 nginx
drwxr-xr-x. 2 qiuhom root 4096 11月 11 19:18 scripts
drwxr-xr-x. 3 qiuhom root 4096 11月 11 19:28 test
-rw-r--r--. 1 root   root   57 11月 13 19:15 test_cron_file
-rw-r--r--. 1 root   root    0 11月 17 17:23 vsftpd

[root@test ~]#

  说明:可看到我们创建的文件和目录在目标主机已经生成

上面的用法是典型的python列表的用法,在python中读取列表中的元素就是用下标的表示来读取相应的元素的值。接下我们将介绍另外一种更为复杂的变量,它类似python中的字典概率,但比字典的维度要高,更像是二维字典。ansible内置变量ansible_eth0就是这样一种,它用来保存远端主机上面eth0接口的信息,包括ip地址和子网掩码等。如下所示

[root@test ~]#cat test.yml     
---
- hosts: 192.168.0.218
  remote_user: root
  
  tasks:
    - debug: var=ansible_eth0 
[root@test ~]#ansible-playbook test.yml 

PLAY [192.168.0.218] ************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218]

TASK [debug] ********************************************************************************************************
ok: [192.168.0.218] => {
    "ansible_eth0": {
        "active": true, 
        "device": "eth0", 
        "features": {
            "fcoe_mtu": "off [fixed]", 
            "generic_receive_offload": "on", 
            "generic_segmentation_offload": "on", 
            "highdma": "off [fixed]", 
            "large_receive_offload": "off [fixed]", 
            "loopback": "off [fixed]", 
            "netns_local": "off [fixed]", 
            "ntuple_filters": "off [fixed]", 
            "receive_hashing": "off [fixed]", 
            "rx_checksumming": "on", 
            "rx_vlan_filter": "on [fixed]", 
            "rx_vlan_offload": "on [fixed]", 
            "scatter_gather": "on", 
            "tcp_segmentation_offload": "on", 
            "tx_checksum_fcoe_crc": "off [fixed]", 
            "tx_checksum_ip_generic": "on", 
            "tx_checksum_ipv4": "off", 
            "tx_checksum_ipv6": "off", 
            "tx_checksum_sctp": "off [fixed]", 
            "tx_checksum_unneeded": "off", 
            "tx_checksumming": "on", 
            "tx_fcoe_segmentation": "off [fixed]", 
            "tx_gre_segmentation": "off [fixed]", 
            "tx_gso_robust": "off [fixed]", 
            "tx_lockless": "off [fixed]", 
            "tx_scatter_gather": "on", 
            "tx_scatter_gather_fraglist": "off [fixed]", 
            "tx_tcp6_segmentation": "off", 
            "tx_tcp_ecn_segmentation": "off", 
            "tx_tcp_segmentation": "on", 
            "tx_udp_tnl_segmentation": "off [fixed]", 
            "tx_vlan_offload": "on [fixed]", 
            "udp_fragmentation_offload": "off [fixed]", 
            "vlan_challenged": "off [fixed]"
        }, 
        "hw_timestamp_filters": [], 
        "ipv4": {
            "address": "192.168.0.218", 
            "broadcast": "192.168.0.255", 
            "netmask": "255.255.255.0", 
            "network": "192.168.0.0"
        }, 
        "ipv6": [
            {
                "address": "fe80::20c:29ff:fee8:f67b", 
                "prefix": "64", 
                "scope": "link"
            }
        ], 
        "macaddress": "00:0c:29:e8:f6:7b", 
        "module": "e1000", 
        "mtu": 1500, 
        "pciid": "0000:02:01.0", 
        "promisc": false, 
        "speed": 1000, 
        "timestamping": [
            "rx_software", 
            "software"
        ], 
        "type": "ether"
    }
}

PLAY RECAP **********************************************************************************************************
192.168.0.218              : ok=2    changed=0    unreachable=0    failed=0   

[root@test ~]#

  说明:以上playbook就实现了对ansible_eth0这个变量进行调试并打印,可以看到ansible_eth0是一个相对比较复杂的变量,里面包含了字典,列表混合一起的一个大字典。

我们可以看到ansible_eht0里面包含了很多内容,我们要想读取其中的IPV4地址,我们可以采用“.”或者下标的方式去访问,如下所示

[root@test ~]#cat test.yml 
---
- hosts: 192.168.0.218
  remote_user: root
  
  tasks:
    - name: print ipv4  
      shell: echo {{ ansible_eth0["ipv4"]["address"] }} 
    - name: print mac
      shell: echo  {{ ansible_eth0.macaddress }}
[root@test ~]#ansible-playbook test.yml -v
Using /etc/ansible/ansible.cfg as config file

PLAY [192.168.0.218] ************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218]

TASK [print ipv4] ***************************************************************************************************
changed: [192.168.0.218] => {"changed": true, "cmd": "echo 192.168.0.218", "delta": "0:00:00.001680", "end": "2019-11-17 18:30:21.926368", "rc": 0, "start": "2019-11-17 18:30:21.924688", "stderr": "", "stderr_lines": [], "stdout": "192.168.0.218", "stdout_lines": ["192.168.0.218"]}

TASK [print mac] ****************************************************************************************************
changed: [192.168.0.218] => {"changed": true, "cmd": "echo 00:0c:29:e8:f6:7b", "delta": "0:00:00.001746", "end": "2019-11-17 18:30:22.650541", "rc": 0, "start": "2019-11-17 18:30:22.648795", "stderr": "", "stderr_lines": [], "stdout": "00:0c:29:e8:f6:7b", "stdout_lines": ["00:0c:29:e8:f6:7b"]}

PLAY RECAP **********************************************************************************************************
192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   

[root@test ~]#

  说明:由此可以看出ansible多级变量的调用,使用中括号和点号都是可以的

原文地址:https://www.cnblogs.com/qiuhom-1874/p/11877353.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


----name:setpublickeyonremotehosts&setreomtehostssudoersfilehosts:all#此脚本要求所有的主机root用户密码相同become:noremote_user:rootvars:-remoteuser:user1:rhcetasks:-name:setsecondarygroupforrhce
环境准备#cat/etcedhat-releaseCentOSLinuxrelease7.9.2009(Core)#pythonPython3.7.11(default,Jul312022,16:12:35)[GCC4.8.520150623(RedHat4.8.5-44)]onlinuxType"help","copyright","credits"or"li
准备好环境,在安装之前请先了解openshift提供的ansible有大量的安装选项文档地址:https://docs.okd.io/latest/install/configuring_inventory_file.html1、配置/etc/ansible/hosts 
Ansible:运维工作:系统安装(物理机、虚拟机)-->程序包安装、配置、服务启动-->批量操作-->程序发布-->监控OSProvisioning:物理机:PXE、Cobbler虚拟机:ImageTemplatesConfigration:puppet(ruby)saltstack(python)chefcfengineCommandand
ansible与salt对比相同都是为了同时在多台机器上执行相同的命令都是python开发不同agent(saltstack需要安装、ansible不需要)配置(salt配置麻烦,ansible基本不用配置)学习路线(salt比较陡峭,ansible比较平缓)第三方工具(salt比较少)开源社区的对接(salt比较少)现有用户(salt还是an
[root@node1playbook]#catnginx.yml-hosts:test\\主机组,要和nginx.yml在同一个目录下remote_user:root\\远端执行任务的用户tasks:\\任务-name:installhttpd\\任务描述command:yum-yinstallhttpd\\调用ansible的command模块安装httpd-na
一直不知道这个模块到底在哪,并且也挺想搞清楚官方那些模块到底在哪个目录下。1.使用grep-rl"copy.py"/usr/lib/python2.7/site-packages/ansible(这个目录是专门放ansible源码目录的)然后找到是/usr/lib/python2.7/site-packages/ansible/modules/files/copy.py这个文件,这里需要
ansile作为去除安装agent的自动化工具,通过ssh协议的简单功能强大的自动化工作。在ansile使用的过程中,有三种用途1、ansible自行一次性任务,即执行命令如:ansible10.59.87.11-mping*ansible"dev-hdp"-mcopy-a"src=oot/HfHadoopHiveUdf.jardest=/data1/opt/cloudera/par
ansible-playbook(1) Ansible组成部分InventoryModulesAdHocCommandsplaybooksplaybooks:Tasks:任务,即调用的模块完成的某操作variables:变量Templates:模版Roles:角色 基本结构:-host:webserverremote_user:tasks:
报错:[root@jenkins~]#ansiblego_activity-mcron-a"name='log_clear'minute=0hour=2job=find/home/golanger/log/-typef-name'log$(date+\%d-d-1day)'-delete"ERROR!thistask'cron'hasextraparams,wh
一、测试环境说明1、系统:rhel6.92、ip地址:20.20.20.24/2420.20.20.41/2420.20.20.42/243、以下操作使用root身份进行,也可以使用具有sudo权限的用户进行相关操作二、环境准备1、关闭iptables防火墙、selinux#/etc/init.d/iptablesstop#
ansible常用模块安装:依赖于epel源yuminstallansible-y配置文件:/etc/ansible/ansible.cfgInvertoory:/etc/ansible/hosts 如何查看模块帮助:ansible-doc-lansible-doc-sMODULE_NAME` ansible命令应用基础:语法:ansible<host-pattern>[options]-fforks
copycopy模块是将ansible管理主机上的文件拷贝上远程主机中,与fetch相反,如果目标路径不存在,则自动创建,如果src的目录带“/”则复制该目录下的所有东西,如果src的目录不带“/”则连同该目录一起复制到目标路径;常用模块src参数:用于指定需要copy的文件或目录
9.YAML9.1简介(1)YAML是一个可读性高的用来表达资料序列的格式。(2)YAML参考了其它多种语言。包括:XML、C语言、python、perl以及电子邮件格式的RFC2822等。ClarkEvans在2001年首次发表了这种语言。(3)YAML不是XML,在开发这种语言时,YAML的意思其实是:yetanothermarkuplanguage,9.2特性(1)YA
了解ansibleansible批量在远程主机上执行命令ansible主要是为了进行操作多个主机而进行的#!/bin/envpython文件中直接指向python文件#!/bin/base 指行脚本一.ansible第一步.下载epel源wget-O/etc/yum.repos.d/epel.repohttp://mirrors.aliyun.comepo/epel-7.repo
背景:在私有云环境下,遇到要开通某个项目,则需要快速的响应创建虚拟机,并且做一些基础的配置。为了提高效率以及减少手工犯错的概率,一般会采取ansible批量部署,但是使用ansible的前提是预先配置好免密。在密码一致的场景中,可以使用expect优化做免密的过程解决方案:1.
简单例子1:vars定义变量-hosts:allremote_user:rootvars:-package:nginx-service:nginx tasks:-name:installnginxpackage yum:name={{package}}state=latest-name:installconfigurationfileforhttpd copy:src=/etcginxginx
 ansible自动化运维工具的介绍      ansible结构特性:            模块化,调用特定的模块,完成特定的任务;        基于Python语言实现,由Paramiko、PyYAML和Jinja2三个关键模块;        部署简单,agentless        主从模
---恢复内容开始---Templates:模版 cat/etc/ansible/hosts  cattemplatesginx.conf.j2 -hosts:testremote_user:rootvars:-package:httpd-service:httpdtasks:-name:installnginxpackage yum:name={{package}}state=la
1、配置资源清单inventory文件[root@test1~]#cat>/etc/ansible/hosts<<EOF[k8s]192.168.0.92ansible_ssh_port=22ansible_ssh_user=k8sansible_ssh_pass='123'ansible_become_pass='123456'EOF解释:ansible_ssh_pass='123'