zoukankan      html  css  js  c++  java
  • Ansible 自动化运维工具简单入门(三)

    四、Ansible-playbook

    1、YAML介绍

    1)基础知识

    • YAML是一个可读性高的用来表达资料序列的格式。YAML参考了很多语言,包括C语言、Python、Perl德国,Clark Evens在2001年首次发表了这种语言,另外Ingy dot 和Oren Ben-Kiki也是共同设计者

    • YAML Ain’t Mrakup Language ,即YAML不是XML,不过在开发语言的时候,YAML的愿意是:"Yet Another Markup Language"(仍是一种标记语言)

    • 特性

      YAML的可读性好

      YAML和脚本语言的交互性好

      YAML使用实现语言的数据类型

      YAML有一个一致的信息模型

      YAML易于实现

      YAML可以基于流来处理

      YAML表达能力强,扩展性好

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

    2)语法简介

    • 在单一档案中,可用连续三个---区分多个档案(习惯首行---)。另外,可以选择性的连续...来表示档案结尾
    • 慈航开始正常些Playbook内容,一般建议写明该Playbook的功能
    • 使用#号注释代码
    • 缩进必须是统一的,空格和tab不能混用
    • 缩进的级别必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
    • YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感
    • k/v的值可同行业可以换行,同行使用:分割
    • v可是字符串,也可以是另外一个表
    • 一个完整的代码块所需最小的元素包括:name:task
    • 一个name只能包括一个task
    • YAML文件扩展名通常为yml或yaml

    3)基础用法

    • List:列表,其所有元素均使用"-"开头

      # A list of tasty fruits

      - apple

      - orange

      - strawberry

      - mango

    -后面有空格

    • Dictonary:字典,通常由多个key和value构成


      # An emplyoyee record

      name: example developer

      job: developer

      skill: elite

      也可以将key:value放置于{}内进行表示,用,分开多个


      # An emplyoyee record

      {name: example developer,job: developer,skill: elite}

    • YAML语法和其他告诫语言类似,并且可以简单表达清单,散列表,标量等数据结构。其结构通过空格来展示,序列里面的项用-来代表,mao理的键值对用:隔开

    name: John Smith

    age: 40

    gender: male

    spourse:

    ​ name: Tom Smith

    ​ age: 37

    ​ gender: female

    ​ children:

    ​ - name: jimmy Smith

    ​ - age: 17

    ​ - name: kitty Smith

    ​ - age: 12

    2、Playbook基础理论

    1)简介

    • playbook 是由一个或多个play组成的 列表
    • play的主要功能在于将直线归并为一组的主机装扮实现通过ansible中的task定义好的角色。从根本来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook内,即可以让它们联动起来按实现编排的机制唱一台大戏
    • playbook采用YAML语言编写

    2)工作流程

    3 、Playbook核心元素

    • Hosts 执行的远程主机列表

    • Tasks 任务集

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

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

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

    • Tags 标签 制定某条任务执行,用户选择运行playbook中的部分代码,ansible具有幂等性,因此会自动跳过没有辩护的部分,即便如此,有的代码为测试其确实没有发生变化的时间依然会非常的长,此时确信其没有变化,就可以通过tags跳过这些代码片段

      ansible-playbook -t tagsname useradd.yml

    4、Hosts

    • playbook中的每一个play 的目的都是为了让某个或某些主机以某个特定身份执行任务,hosts用于制定要执行执行任务的主机,须事先定义在主机清单内

    • 可以是如下形式:

      one.exaple.com

      one.exaple.com:two.exaple.com

      172.16.111.7

      172.16.111.*

    • web:db 两个组的并集

    • web:&app 两个组的交集

    • app:!db 在app且不在db组内

      - hosts: web:db

    实例:

    [root@ansible ansible]# vim ./test.yml
    
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: create new file    #创建文件
          file: name=/data/file123 state=touch 
        - name: create new user    #创建用户
          user: name=test222 system=yes shell=/sbin/nologin
        - name: install httpd    #安装httpd
          yum: name=httpd 
        - name: copy html     #复制html
          copy: src=/usr/share/httpd/noindex/index.html dest=/var/www/html/
        - name: start service   #开启httpd服务
          service: name=httpd state=started enabled=yes
          #执行前检查剧本是否正常
       [root@ansible ansible]# ansible-playbook -C ./test.yml  
    
    PLAY [web] *********************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [172.16.111.8]
    ok: [172.16.111.7]
    
    TASK [create new file] *********************************************************
    changed: [172.16.111.8]
    changed: [172.16.111.7]
    
    TASK [create new user] *********************************************************
    changed: [172.16.111.7]
    changed: [172.16.111.8]
    
    TASK [remove httpd] ************************************************************
    ok: [172.16.111.8]
    ok: [172.16.111.7]
    
    TASK [copy html] ***************************************************************
    changed: [172.16.111.7]
    changed: [172.16.111.8]
    
    TASK [start service] ***********************************************************
    ok: [172.16.111.7]
    ok: [172.16.111.8]
    
    PLAY RECAP *********************************************************************
    172.16.111.7               : ok=6    changed=3    unreachable=0    failed=0   
    172.16.111.8               : ok=6    changed=3    unreachable=0    failed=0                                                   
    

    测试没问题后执行,然后去被控端检查上述剧本中各项任务是否执行成功,验证。

    5、Remote_user

    remote_user:可用于Host和task中,也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某服务;次在,甚至可以在sudo时使用sudo_user制定sudo时切换的用户

    - hosts: web
      remote_user: root
    tasks:
      - name: test connection
        ping:
        remote_user: white
        sudo: yes     #默认为root
        sudo_user: wang     #sudo为wang
    

    6、Task

    • play的主题部分是task list。task list中的个任务按次序诸葛在hosts制定的所有主机下执行,即在所有主机上完成第一个任务后开始第二个。在运行紫霞而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。

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

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

    • task:任务列表

      格式:action: module arguments

      module: arguments 建议使用

      注意:shell和command模块后面跟命令二不是key=value

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

      任务可以通过tags打标签,而后可在ansible-playbook命令上使用-t制定进行调用

      task:

      - name: disable selinux

      ​ command: /sbin/setenforce 0

      如果命令或脚本的退出吗不为0(命令执行失败),可以用如下方式替代:

      tasks:

      - name: run this command and ignore the result

      ​ shell: /usr/bin/command || /bin/true

      或者使用ignore_errors来忽略错误信息:

      tasks:

      - name: run this command and ignore the result

      ​ shell: /usr/bin/command

      ​ ignore_errors: True

    7、Playbook

    • 运行playbook的方式

    ansible-playbook <filename.yml> ...[options]

    • 常见选项

      -- check只检车可能发生的改变,不真正执行等于-C

      --list-hosts 列出运行任务的主机

      --limit 主机列表指着对主机列表中的主机执行

      -v 显示过程 -vv -vvv更详细

    • 实例

      ansible-playbook file.yml --check

      ansible-playbook file.yml

      ansible-playbook file.yml --limit web

      ansible-playbook file.yml --list-tasks

      [root@ansible ~]# ansible-playbook ./ansible/test.yml --list-tasks
      
      playbook: ./ansible/test.yml
      
        play #1 (web): web	TAGS: []
          tasks:
            create new file	TAGS: []
            create new user	TAGS: []
            remove httpd	TAGS: []
            copy html	TAGS: []
            start service	TAGS: []
      [root@ansible ~]# ansible-playbook ./ansible/test.yml --list-hosts
      
      playbook: ./ansible/test.yml
      
        play #1 (web): web	TAGS: []
          pattern: [u'web']
          hosts (2):
            172.16.111.7
            172.16.111.
      

    实例:

    httpd.tml
    - hosts: web
      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 enable=yes 
    

    注意此时files使用的是相对路径,默认是当前用户家目录/下,没有files目录新建即可,把需要复制的文件复制到改文件夹内,YML脚本内即可使用相对路径

    8、Handers

    是task任务列表,这些task与前述的task没有本质的不同,用于当关注的资源发生变化时,才会采取一定的操作

    9、Notify

    此action可用于在每个play的最后被处罚,这样可以避免多次有改变每次都执行制定的操作,仅在所有的变化发生完成后一次性执行制定操作,在notify中累出的操作称为handler,也即notify中调用hander中定义的操作

    [root@ansible ansible]# mkdir files
    [root@ansible ansible]# cp /etc/httpd/conf/httpd.conf ./files
    [root@ansible ansible]# vim httpd.yml
    
    
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: install httpd package
          yum: name=httpd
        - name: copy conf file
          copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes
        - name: start service
          service: name=httpd state=started enabled=yes                                                       
          #提前修改conf文件内容 用于验证 例如端口 修改为8008
          [root@ansible ansible]# ansible-playbook -C httpd.yml 
    
    PLAY [all] *****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] *****************************************************************************************************************************************************
    ok: [172.16.111.9]
    ok: [172.16.111.7]
    ok: [172.16.111.8]
    
    TASK [install httpd package] ***********************************************************************************************************************************************
    changed: [172.16.111.9]
    changed: [172.16.111.7]
    changed: [172.16.111.8]
    
    TASK [copy conf file] ******************************************************************************************************************************************************
    changed: [172.16.111.9]
    changed: [172.16.111.7]
    changed: [172.16.111.8]
    
    TASK [start service] *******************************************************************************************************************************************************
    changed: [172.16.111.9]
    changed: [172.16.111.8]
    changed: [172.16.111.7]
    
    PLAY RECAP *****************************************************************************************************************************************************************
    172.16.111.7               : ok=4    changed=3    unreachable=0    failed=0   
    172.16.111.8               : ok=4    changed=3    unreachable=0    failed=0   
    172.16.111.9               : ok=4    changed=3    unreachable=0    failed=0  
    #测试正常
    执行后验证结果,查询被控端8008端口和80端口是否启动
    [root@ansible ansible]# ansible all -m shell -a 'ss -lnt|grep :8080'
    172.16.111.9 | FAILED | rc=1 >>
    non-zero return code
    
    172.16.111.8 | FAILED | rc=1 >>
    non-zero return code
    
    172.16.111.7 | FAILED | rc=1 >>
    non-zero return code
    
    [root@ansible ansible]# ansible all -m shell -a 'ss -lnt|grep :80'
    172.16.111.9 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::8008                    :::*                  
    
    172.16.111.8 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::8008                    :::*                  
    
    172.16.111.7 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::8008                    :::*  
    #查看可知80端口端口依然启动8008未启动,但是被控端都生成了httpd.conf的备份文件
    

    此时我们需要做到的是,检测到conf文件有变化,服务自动重启,此时就需要handers介入

    [root@ansible ansible]# vim httpd.yml 
    
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: install httpd package
          yum: name=httpd
        - name: copy conf file
          copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes
          notify: restart service   #触发器,放在需要监控的触发动作后,: 后面是执行的东走
        - name: start service
          service: name=httpd state=started enabled=yes
    
      handlers:
        - name: restart service
          service: name=httpd state=restarted
    
    

    此时最好再次修改httpd.conf 因为前次操作已经把httpd。conf文件已经修改了 ,修改端口为9527 ,由于安装过httpd,本次执行默认跳过安装,再次执行后查看端口

    [root@ansible ansible]# ansible-playbook  httpd.yml -C
    
    PLAY [all] *****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] *****************************************************************************************************************************************************
    ok: [172.16.111.9]
    ok: [172.16.111.8]
    ok: [172.16.111.7]
    
    TASK [install httpd package] ***********************************************************************************************************************************************
    ok: [172.16.111.8]
    ok: [172.16.111.9]
    ok: [172.16.111.7]
    
    TASK [copy conf file] ******************************************************************************************************************************************************
    changed: [172.16.111.9]
    changed: [172.16.111.8]
    changed: [172.16.111.7]
    
    TASK [start service] *******************************************************************************************************************************************************
    ok: [172.16.111.8]
    ok: [172.16.111.9]
    ok: [172.16.111.7]
    
    RUNNING HANDLER [restart service] ******************************************************************************************************************************************
    changed: [172.16.111.9]
    changed: [172.16.111.7]
    changed: [172.16.111.8]
    
    PLAY RECAP *****************************************************************************************************************************************************************
    172.16.111.7               : ok=5    changed=2    unreachable=0    failed=0   
    172.16.111.8               : ok=5    changed=2    unreachable=0    failed=0   
    172.16.111.9               : ok=5    changed=2    unreachable=0    failed=0   
    [root@ansible ansible]# ansible all -m shell -a 'ss -lnt|grep 80'
    172.16.111.9 | FAILED | rc=1 >>
    non-zero return code
    
    172.16.111.8 | FAILED | rc=1 >>
    non-zero return code
    
    172.16.111.7 | FAILED | rc=1 >>
    non-zero return code
    
    [root@ansible ansible]# ansible all -m shell -a 'ss -lnt|grep 9527'
    172.16.111.9 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::9527                    :::*                  
    
    172.16.111.7 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::9527                    :::*                  
    
    172.16.111.8 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::9527                    :::*   
    
    

    可以看出,handlers和notify配合使用,类似于linux系统的inotify,监控行为

    10、Targs

    可以使用tags增加标签,在执行YML的时候可以指定标签使用

    [root@ansible ansible]# vim httpd.yml 
    
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: install httpd package
          yum: name=httpd
          tags: inhttpd
        - name: copy conf file
          copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes
          notify: restart service
        - name: start service
          service: name=httpd state=started enabled=yes
          tages: rshttpd
      handlers:
        - name: restart service
          service: name=httpd state=restarted
    [root@ansible ansible]# ansible-playbook -t rshttpd httpd.yml #-t 指定标签
     [WARNING]: Ignoring invalid attribute: tages
    
    
    PLAY [all] *****************************************************************************************************************************************************************
    
    TASK [Gathering Facts] *****************************************************************************************************************************************************
    ok: [172.16.111.9]
    ok: [172.16.111.8]
    ok: [172.16.111.7]
    
    PLAY RECAP *****************************************************************************************************************************************************************
    172.16.111.7               : ok=1    changed=0    unreachable=0    failed=0   
    172.16.111.8               : ok=1    changed=0    unreachable=0    failed=0   
    172.16.111.9               : ok=1    changed=0    unreachable=0    failed=0  
    
    

    ansible-playbook -t rshttpd,inhttpd httpd.yml #多个标签逗号隔开

    多个动作可以共用一个标签(个人感觉类似索引,关键词)

    11、vars

    以上操作都是所有任务依次操作,所有主机都执行,不够灵活,需要引入变量,让不同的主机可以进行不同的操作,可以做条件供以后判断等操作

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

    变量来源:

    1、ansible setup facts远程主机的所有变量都可以直接调用,支持通配符

    ansible web -m setup -a 'filter=*address*'

    2、在/etc/ansible/hosts中定义

    普通变量:主机组中主机单独定义,优先级高于公共变量

    公共变量:针对主机组中所有主机定义统一变量

    #对所有主机的hostname可以修改  根据名字区分
    [root@ansible ansible]# vim httpd1.yml 
    
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: set hostname
          hostname: name=www{{http_port}}.white.com
    #此时这样执行,hostname均可以被修改,我们发现该hostname内 www和.white.com都是web内左右主机共用的  那就可以用在hosts内设置变量
    [root@ansible ansible]# vim /etc/ansible/hosts 
    [web]
    172.16.111.7
    172.16.111.8
    [web:vars]     #新增web组变量
    nodename=www
    damainname=white.com
    [root@ansible ansible]# vim httpd1.yml 
    #根据设置配置剧本
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: set hostname
          hostname: name={{nodename}}{{http_port}}.{{domainname}}
    ~                                                     [root@ansible ansible]# ansible-playbook httpd1.yml 
    

    3、通过命令行制定变量,优先级最高

    ansible-playbook -e varname=value

    [root@ansible ansible]# vim app.yml
    ---
    - hosts: app
      remote_user: root
    
      tasks:
        - name: install  package
          yum: name={{ pkname}}    #设置变量名
        - name: start service
          service: name={{ pkname}} state=started  enabled=yes   #调用变量
    
    
    [root@ansible ansible]# ansible-playbook -e 'pkname=vsftpd' app.yml #执行时需要 -e给变量赋值 
    #结果如下
    PLAY [app] **********************************************************************************
    
    TASK [Gathering Facts] **********************************************************************
    ok: [172.16.111.8]
    ok: [172.16.111.7]
    ok: [172.16.111.9]
    
    TASK [install  package] *********************************************************************
    ok: [172.16.111.9]
    ok: [172.16.111.7]
    ok: [172.16.111.8]
    
    TASK [start service] ************************************************************************
    ok: [172.16.111.9]
    ok: [172.16.111.8]
    ok: [172.16.111.7]
    
    PLAY RECAP **********************************************************************************
    172.16.111.7               : ok=3    changed=0    unreachable=0    failed=0   
    172.16.111.8               : ok=3    changed=0    unreachable=0    failed=0   
    172.16.111.9               : ok=3    changed=0    unreachable=0    failed=0   
    
    [root@ansible ansible]# ansible app -m shell -a 'ss -lnt|grep 21'  #检查验证
    172.16.111.9 | SUCCESS | rc=0 >>
    LISTEN     0      32          :::21                      :::*                  
    
    172.16.111.7 | SUCCESS | rc=0 >>
    LISTEN     0      32          :::21                      :::*                  
    
    172.16.111.8 | SUCCESS | rc=0 >>
    LISTEN     0      32          :::21                      :::*    
    

    装多个安装包可以设置多个变量

      tasks:
        - name: install  package
          yum: name={{ pkname1}}    #设置变量名1
        - name: install  package
          yum: name={{ pkname2}}    #设置变量名2
    [root@ansible ansible]# ansible-playbook -e 'pkname1=vsftpd pkname2=httpd' app.yml  #多个变量
    
    

    4、在playbook内定义

    vars:

    - var1: value1

    - var2: value2

    [root@ansible ansible]# vim app1.yml 
    
    ---
    - hosts: app
      remote_user: root
      vars:
        - pkname1: httpd
        - pkname2: vsftp
    
      tasks:
        - name: install  package
          yum: name={{ pkname1}}
          yum: name={{ pkname2}}
        - name: start service
          service: name={{ pkname1}} state=started enabled=yes
          service: name={{ pkname2}} state=started enabled=yes
    [root@ansible ansible]# ansible-playbook app1.yml 
    #由于在脚本内已经定义了变量,直接执行即可
    

    5、在role内定义

    后面介绍

    6、在独立的YML文件内定义

    对于变量管理,由于变量有多重方式可以定义,不同人习惯会导致变量混乱等,故可以考虑吧变量放在同一文件内,使用的时候在文件内修改,剧本中调用该文件

    [root@ansible ansible]# vim var.yml #配置变量文件
    
    var1: httpd
    var2: vsftpd
    [root@ansible ansible]# vim testvars.yml
    ---
    - hosts: web
      remote_user: root
      vars_files:     #调用变量文件
        - var.yml
    
      tasks:
        - name: install packages
          yum: name={{ var1}}
        - name: create file
          file : name=/tmp/{{ var2}}.log state=touch
    [root@ansible ansible]# ansible-playbook testvars.yml 
    
    [root@ansible ansible]# ansible web -m shell -a 'rpm -q httpd'   #验证结果
     [WARNING]: Consider using yum, dnf or zypper module rather than running rpm
    
    172.16.111.8 | SUCCESS | rc=0 >>
    httpd-2.4.6-80.el7.centos.1.x86_64
    
    172.16.111.7 | SUCCESS | rc=0 >>
    httpd-2.4.6-80.el7.centos.1.x86_64
    [root@ansible ansible]# ansible web -m shell -a 'ls /tmp/vsftpd.log'
    172.16.111.7 | SUCCESS | rc=0 >>
    /tmp/vsftpd.log
    
    172.16.111.8 | SUCCESS | rc=0 >>
    /tmp/vsftpd.log
    
    

    以上可以用来解决较为简单的命令

    12、Templates

    • 文本文件,嵌套有脚本(使用模板变成语言编写)

    • jinja2语言,使用字面量,有下面形式

      字符串:使用单引号或双信号

      数字:整数,浮点数

      列表:[item1,item2,...]

      元组:(item1,item2,...)

      字典:{key1:value1,key2:value2,...}

      布尔型:true/false

    • 算数运算:+、-、*、/、//、%、**

      //整除,不留小数和余数 **指数

    • 比较运算:==,!=,>,>=,<,<=

    • 逻辑运算:and,or,not

    • 流表达式:For If When

    配置文一般防止在yml文件同级的目录的templates下 配置文件以.js结尾

    以下使用nginx做为案例

    准备环境 nginx.conf为模板文件

    #创建模板文件
    [root@ansible ansible]# cp /etc/nginx/nginx.conf ~/ansible/templates/nginx.conf.j2
    #编写脚本
    [root@ansible ansible]# vim testtemplated.yml
    
    ---
    - hosts: web
      remote_user: root
    
      tasks:
      - name: install package
        yum: name=nginx
      - name: copy templated
        template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf  #调用模板
      - name: start service
        service: name=nginx state=started enabled=yes
    #-C测试
    [root@ansible ansible]# ansible-playbook testtemplated.yml -C
    #测试正常后取消-C 执行
    [root@ansible ansible]# ansible web -m shell -a 'ps -ef|grep nginx'
    172.16.111.7 | SUCCESS | rc=0 >>
    root      24383      1  0 23:22 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     24384  24383  0 23:22 ?        00:00:00 nginx: worker process
    root      24435  24430  0 23:23 pts/0    00:00:00 /bin/sh -c ps -ef|grep nginx
    root      24437  24435  0 23:23 pts/0    00:00:00 grep nginx
    
    172.16.111.8 | SUCCESS | rc=0 >>
    root      28866      1  0 23:22 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     28867  28866  0 23:22 ?        00:00:00 nginx: worker process
    root      28918  28913  0 23:23 pts/0    00:00:00 /bin/sh -c ps -ef|grep nginx
    root      28920  28918  0 23:23 pts/0    00:00:00 grep nginx
    #查看结果,被控端nginx已经开启,注意进程数
    

    修改nginx.conf后再继续测试,(默认nginx.conf的worker_processes 1;和CPU核心数相等,有的版本是auto,本次测试nginx版本为1.14,默认是1)

    #查询setup自带的CPU变量
    [root@ansible ~]# ansible web -m setup|grep "cpu"
            "ansible_processor_vcpus": 2, 
            "ansible_processor_vcpus": 2, 
    #修改nginx.conf.j2文件
    [root@ansible ansible]# vim templates/nginx.conf.j2 
    worker_processes  {{ansible_processor_vcpus*2}};
    #由于此前已经安装并启动了nginx,此时需要更改配置文件后重启服务,可以借助前面使用的handlers+notify来完成
    [root@ansible ansible]# vim testtemplated.yml 
    
    ---
    - hosts: web
      remote_user: root
    
      tasks:
      - name: install package
        yum: name=nginx
      - name: copy templated
        template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
        notify: restart service
      - name: start service
        service: name=nginx state=started enabled=yes
    
      handlers:
      - name: restart service
        service: name=nginx state=restarted
    #-C测试正常后执行
    [root@ansible ansible]# ansible-playbook testtemplated.yml
    
    #再次查看nginx进程数
     [root@ansible ansible]# ansible web -m shell -a 'ps -ef|grep nginx'
    172.16.111.8 | SUCCESS | rc=0 >>
    root      29793      1  0 23:34 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     29794  29793  0 23:34 ?        00:00:00 nginx: worker process
    nginx     29795  29793  0 23:34 ?        00:00:00 nginx: worker process
    nginx     29796  29793  0 23:34 ?        00:00:00 nginx: worker process
    nginx     29797  29793  0 23:34 ?        00:00:00 nginx: worker process
    root      29862  29857  0 23:35 pts/0    00:00:00 /bin/sh -c ps -ef|grep nginx
    root      29864  29862  0 23:35 pts/0    00:00:00 grep nginx
    
    172.16.111.7 | SUCCESS | rc=0 >>
    root      25398      1  0 23:34 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     25399  25398  0 23:34 ?        00:00:00 nginx: worker process
    nginx     25400  25398  0 23:34 ?        00:00:00 nginx: worker process
    nginx     25401  25398  0 23:34 ?        00:00:00 nginx: worker process
    nginx     25402  25398  0 23:34 ?        00:00:00 nginx: worker process
    root      25463  25458  0 23:35 pts/0    00:00:00 /bin/sh -c ps -ef|grep nginx
    root      25465  25463  0 23:35 pts/0    00:00:00 grep nginx
    #进程数都有所增加
    
    

    扩展:此时被控端的web组内(node1,node2)的nginx的服务都是80端口,如果有需求更换不同的端口(node1使用8080,node2使用9080),可以为hosts内进行配置

    [root@ansible ansible]# vim /etc/ansible/hosts
    [web]
    172.16.111.7 http_port=8080  #配置变量
    172.16.111.8 http_port=9080  #配置变量
    [root@ansible ansible]# vim templates/nginx.conf.j2 
    server {
        listen       {{ http_port}};
    #    listen      [::]:{{ http_port}} default_server
        server_name  _;
    
        #charset koi8-r;
        #access_log  /var/log/nginx/host.access.log  main;
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    }
    #注意 默认nginx1.14内么有上述server 需要自己添加或者从conf.d/default.conf内自己复制,可能是作者希望使用include进行管理
    [root@ansible ansible]# ansible-playbook testtemplated.yml 
    
    #执行脚本后查看结果(主要是查看端口变量是否成功  使用 ss -lnt)
    [root@ansible ansible]# ansible web -m shell -a 'ss -lnt'
    172.16.111.8 | SUCCESS | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:9080                     *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128          *:80                       *:*                  
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100        ::1:25                      :::*                  
    LISTEN     0      128         :::22                      :::*                  
    
    172.16.111.7 | SUCCESS | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128          *:8080                     *:*                  
    LISTEN     0      128          *:80                       *:*                  
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100        ::1:25                      :::*                  
    LISTEN     0      128         :::22                      :::* 
    #查看结果可知 8080  9080端口已经开启
    

    此外,还可以在playbook内写入变量

    [root@ansible ansible]# vim testtemplated.yml 
    ---
    - hosts: web
      remote_user: root
      vars:      #配置变量
        - http_port: 88
      tasks:
      - name: install package
        yum: name=nginx
      - name: copy templated
        template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
        notify: restart service
      - name: start service
        service: name=nginx state=started enabled=yes
    
      handlers:
      - name: restart service
        service: name=nginx state=restarted
    #保存修改 执行  -C测试  执行(执行信息省略)
    [root@ansible ansible]# ansible-playbook testtemplated.yml  
    #检验结果
    [root@ansible ansible]# ansible web -m shell -a 'ss -lnt'
    172.16.111.8 | SUCCESS | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:88                       *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128          *:80                       *:*                  
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100        ::1:25                      :::*                  
    LISTEN     0      128         :::22                      :::*                  
    
    172.16.111.7 | SUCCESS | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:88                       *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128          *:80                       *:*                  
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100        ::1:25                      :::*                  
    LISTEN     0      128         :::22                      :::*   
    #端口都被修改为88
    

    验证了最开始的优先级的概念

    命令行-e>playbook剧本>hosts内普通变量>hosts内的公共(组)变量

    13、When

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

    • 在task后增加when子句即可实现条件测试;when语句支持jinja2表达式语法

    • 示例:

      tasks:

      - name: "shutdown RedHat"

      ​ command: /sbin/shutdown -h now

      ​ when: ansible_os_family == "RedHat"

    #ansible_os_family 是setup自带变量

    [root@ansible ~]# ansible 172.16.111.7 -m setup -a "filter=ansible_os_family"   #查看系列
    172.16.111.7 | SUCCESS => {
        "ansible_facts": {
            "ansible_os_family": "RedHat"
        }, 
        "changed": false
    }
    #" "内的内容就是匹配到的内容,以后可根据此进行判断等操作
    

    举例:在上次操作texttemplated.yml中,加入when判断,判断被控端hostname是node2的时候才复制配置文件并重启服务

    [root@ansible ansible]# cp testtemplated.yml testwhen.yml
    #修改脚本
    [root@ansible ansible]# vim testwhen.yml 
    
    ---
    - hosts: web
      remote_user: root
      vars:
        - http_port: 8888
      tasks:
      - name: install package
        yum: name=nginx
      - name: copy templated
        template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
        when: ansible_hostname == "node2"     #判断条件 可以多个task多个判断
        notify: restart service
      - name: start service
        service: name=nginx state=started enabled=yes
    
      handlers:
      - name: restart service
        service: name=nginx state=restarted
    #检测后执行
    [root@ansible ansible]# ansible-playbook testwhen.yml 
    #查看端口是否修改
    [root@ansible ansible]# ansible all -m shell -a 'ss -lnt'
      172.16.111.8 | SUCCESS | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:8888                     *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128          *:80                       *:*                  
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100        ::1:25                      :::*                  
    LISTEN     0      128         :::22                      :::*                  
    
    172.16.111.7 | SUCCESS | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:88                       *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128          *:80                       *:*                  
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100        ::1:25                      :::*                  
    LISTEN     0      128         :::22                      :::*                  
    
    172.16.111.9 | SUCCESS | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100        ::1:25                      :::*                  
    LISTEN     0      128         :::22                      :::*     
    #查看nginx服务是否开启
    [root@ansible ansible]# ansible all -m shell -a 'ps -ef|grep nginx'
    172.16.111.9 | SUCCESS | rc=0 >>
    root       8463   8462  0 17:11 pts/0    00:00:00 /bin/sh -c ps -ef|grep nginx
    root       8465   8463  0 17:11 pts/0    00:00:00 grep nginx
    
    172.16.111.7 | SUCCESS | rc=0 >>
    root      28374      1  0 00:18 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     28375  28374  0 00:18 ?        00:00:00 nginx: worker process
    nginx     28376  28374  0 00:18 ?        00:00:00 nginx: worker process
    nginx     28377  28374  0 00:18 ?        00:00:00 nginx: worker process
    nginx     28378  28374  0 00:18 ?        00:00:00 nginx: worker process
    root      29899  29894  0 00:55 pts/0    00:00:00 /bin/sh -c ps -ef|grep nginx
    root      29901  29899  0 00:55 pts/0    00:00:00 grep nginx
    
    172.16.111.8 | SUCCESS | rc=0 >>
    root      33658      1  0 00:47 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     33659  33658  0 00:47 ?        00:00:00 nginx: worker process
    nginx     33660  33658  0 00:47 ?        00:00:00 nginx: worker process
    nginx     33661  33658  0 00:47 ?        00:00:00 nginx: worker process
    nginx     33662  33658  0 00:47 ?        00:00:00 nginx: worker process
    root      33852  33843  0 00:55 pts/0    00:00:00 /bin/sh -c ps -ef|grep nginx
    root      33854  33852  0 00:55 pts/0    00:00:00 grep nginx
    
    #结果:node1(172.16.111.7)的端口未发生变化,node2(172.16.111.8)的nginx端口被修改为了8888,node3(172.16.111.9)不在web组内,没有任何操作,测试成功
    

    14、Item

    可以使用循环迭代来操作多个重复动作,比如批量创建文件等

    [root@ansible ansible]# vim testitem.yml
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: create files
          file: name=/data/{{ item}} state=touch
          when: ansible_hostname == "node3"
          with_items:
            - file1
            - file2
            - file3
        - name: install some software
          yum: name={{ item}}
          with_items:
            - sysstat
            - lrzsz
            - dstat
    #测试后执行
    [root@ansible ansible]# ansible-playbook testitem.yml
    #验证
    [root@ansible ansible]# ansible all -m shell -a 'rpm -q sysstat dstat lrzsz'
    #所有被控端都安装了sysstat dstat lrzsz三个软件
    [root@ansible ansible]# ansible all -m command -a 'ls -l  /data'
    172.16.111.9 | SUCCESS | rc=0 >>
    total 0
    -rw-r--r--. 1 root root 0 Oct 25 18:27 file1
    -rw-r--r--. 1 root root 0 Oct 25 18:27 file2
    -rw-r--r--. 1 root root 0 Oct 25 18:27 file3
    
    172.16.111.8 | SUCCESS | rc=0 >>
    total 0
    -rw-r--r--. 1 root root  0 Oct 25 15:22 file123
    drwxr-xr-x. 3 root root 21 Oct 22 16:33 svndata
    
    172.16.111.7 | SUCCESS | rc=0 >>
    total 0
    -rw-r--r--. 1 root root  0 Oct 25 15:22 file123
    drwxr-xr-x. 3 root root 21 Oct 22 17:10 svndata
    #只有node3创建了file1 file2 file3文件
    

    需求:创建三个组,创建三个用户,并且把每个用户分别放入一个组

    (user1属于g1,user2属于g2,user3属于g3)

    [root@ansible ansible]# vim testgroup.yml
    
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: add some groups
          group: name={{ item}} state=present
          with_items:
            - g1
            - g2
            - g3
    
        - name: add some user
          user: name={{ item.name}} group={{ item.group}} state=present
          with_items:
            - { name: 'user1', group: 'g1'}    #类似于键值对一个K对应一个V
            - { name: 'user2', group: 'g2'}
            - { name: 'user3', group: 'g3'}
    #item.name语法记住 
    #执行结果验证
    [root@ansible ansible]# ansible all -m shell -a 'getent passwd#该命令结果过长
    [root@ansible ansible]# ansible all -m shell -a 'tail -3 /etc/passwd'
    172.16.111.9 | SUCCESS | rc=0 >>
    user1:x:1002:1002::/home/user1:/bin/bash
    user2:x:1003:1003::/home/user2:/bin/bash
    user3:x:1004:1004::/home/user3:/bin/bash
    
    172.16.111.8 | SUCCESS | rc=0 >>
    user1:x:1002:1002::/home/user1:/bin/bash
    user2:x:1003:1003::/home/user2:/bin/bash
    user3:x:1004:1004::/home/user3:/bin/bash
    
    172.16.111.7 | SUCCESS | rc=0 >>
    user1:x:1003:1003::/home/user1:/bin/bash
    user2:x:1004:1004::/home/user2:/bin/bash
    user3:x:1005:1005::/home/user3:/bin/bash
    

    15、For

    类似shell等的shell循环

    语法

    {% for vhost in nginx/-vhosts %}

    server {

    listen {{ vhost.listen| default('80 default_server') }}

    {% endfor %}

    需求:生成nginx.conf的server标签 listen端口不同

    #创建conf文件
    [root@ansible ansible]# vim templates/for1.conf.j2
    
    {% for port in ports%}   #调用变量
    server {
            listen {{ port}}
    }
    {% endfor %}
    #创建执行脚本 
    [root@ansible ansible]# vim testfor.yml
    
    ---
    - hosts: web
      remote_user: root
      vars:
        ports:
          - 81
          - 82
          - 83
    
      tasks:
        - name: copy conf
          template: src=for1.conf.j2 dest=/data/for1.conf
          #调用模板,模板内调用YML脚本内定义的变量
    [root@ansible ansible]# ansible-playbook testfor.yml
    [root@ansible ansible]# ansible web -m shell -a 'ls -l /data'
    172.16.111.8 | SUCCESS | rc=0 >>
    total 4
    -rw-r--r--. 1 root root  0 Oct 25 15:22 file123
    -rw-r--r--. 1 root root 66 Oct 28 20:17 for1.conf
    drwxr-xr-x. 3 root root 21 Oct 22 16:33 svndata
    
    172.16.111.7 | SUCCESS | rc=0 >>
    total 4
    -rw-r--r--. 1 root root  0 Oct 25 15:22 file123
    -rw-r--r--. 1 root root 66 Oct 28 20:17 for1.conf
    drwxr-xr-x. 3 root root 21 Oct 22 17:10 svndata
    
    [root@ansible ansible]# ansible web -m shell -a 'less /data/for1.conf'
    172.16.111.8 | SUCCESS | rc=0 >>
    server {
    	listen 81
    }
    server {
    	listen 82
    }
    server {
    	listen 83
    }
    
    172.16.111.7 | SUCCESS | rc=0 >>
    server {
    	listen 81
    }
    server {
    	listen 82
    }
    server {
    	listen 83
    }
    
    #使用字典的方式来修改
    [root@ansible ansible]# vim testfor.yml 
    
    ---
    - hosts: web
      remote_user: root
      vars:
        ports:
          - listen_port: 81
          - listen_port: 82
          - listen_port: 83
    
      tasks:
        - name: copy conf
          template: src=for1.conf.j2 dest=/data/for1.conf
    [root@ansible ansible]# vim templates/for1.conf.j2 
    
    {% for port in ports %}
    server {
            listen {{ port.listen_port}}
    }
    {% endfor %}
    
    #执行效果与上面相同,如果是多键值对的时候建议使用此方法,如果只是单一的值,推荐上面方法
    

    多键值对示例

    #配置剧本文件
    [root@ansible ansible]# vim testfor2.yml 
    
    ---
    - hosts: web
      remote_user: root
      vars:
        ports:
          - web1:
            port: 86
            name: web1.white.com
            rootdir: /data/website1
          - web2:
            port: 87
            name: web2.white.com
            rootdir: /data/website2
          - web3:
            port: 88
            name: web3.white.com
            rootdir: /data/website3
    
      tasks:
        - name: copy conf
          template: src=for2.conf.j2 dest=/data/for2.conf
    
    #配置conf文件
    [root@ansible ansible]# vim templates/for2.conf.j2 
    
    {% for p in ports %}
    server {
            listen {{ p.port }}
            servername {{p.name }}
            documentroot {{ p.rootdir }}
    }
    {% endfor %}         
    #验证后执行
    [root@ansible ansible]# ansible-playbook testfor2.yml 
    #验证执行结果
    [root@ansible ansible]# ansible web -m shell -a 'ls /data'
    172.16.111.8 | SUCCESS | rc=0 >>
    file123
    for1.conf
    for2.conf
    svndata
    
    172.16.111.7 | SUCCESS | rc=0 >>
    file123
    for1.conf
    for2.conf
    svndata
    [root@ansible ansible]# ansible 172.16.111.7 -m shell -a 'less /data/for2.conf' 
    172.16.111.7 | SUCCESS | rc=0 >>
    server {
    	listen 86
            servername web1.white.com
            documentroot /data/website1
    }
    server {
    	listen 87
            servername web2.white.com
            documentroot /data/website2
    }
    server {
    	listen 88
            servername web3.white.com
            documentroot /data/website3
    }
    

    16、If

    判断语句,与shell内相同,不多做介绍

    语法

    {% if vhost.server_name is defined %}

    server_name {{vhost.server_name }};

    {% endif %}

    {% if vhost.root is defined 80 %}

    root {{ vhost.root }};

    {% endif %}

    [root@ansible ansible]# vim testif1.yml 
    
    ---
    - hosts: web
      remote_user: root
      vars:
        ports:
          - web1:
            port: 86
            #name: web1.white.com   #注释
            rootdir: /data/website1
          - web2:
            port: 87
            name: web2.white.com
            rootdir: /data/website2
          - web3:
            port: 88
            #name: web3.white.com   #注释
            rootdir: /data/website3
    
      tasks:
        - name: copy conf
          template: src=for3.conf.j2 dest=/data/for3.conf
    #对p.name进行判断,没有则不生成servername
    [root@ansible ansible]# vim templates/for3.conf.j2 
    
    {% for p in ports %}
    server {
            listen {{ p.port }}
    {% if p.name is defined %}
            servername {{ p.name }}
    {% endif %}
            documentroot {{ p.rootdir }}
    }
    {% endfor %}
    #验证执行
    [root@ansible ansible]# ansible-playbook testif1.yml 
    
    [root@ansible ansible]# ansible web -m shell -a 'less /data/for3.conf'
    172.16.111.8 | SUCCESS | rc=0 >>
    server {
    	listen 86
            documentroot /data/website1
    }
    server {
    	listen 87
            servername web2.white.com
            documentroot /data/website2
    }
    server {
    	listen 88
            documentroot /data/website3
    }
    
    172.16.111.7 | SUCCESS | rc=0 >>
    server {
    	listen 86
            documentroot /data/website1
    }
    server {
    	listen 87
            servername web2.white.com
            documentroot /data/website2
    }
    server {
    	listen 88
            documentroot /data/website3
    }
    #只有87端口的server有servername  别的由于被注释,if判断不存在 就不创建servername
    
  • 相关阅读:
    HBaseTDG ClientAPI The Basics
    Hadoop TDG 3 – MR Features
    NoSQL Data Modeling Techniques
    配置SharePoint 2010的User Profile Synchronization连接到第三方的LDAP服务
    Failed to load data access DLL, 0x80004005
    如何开放HyperV服务的远程连接权限给别人?
    SharePoint 2010 Search 架构 已完工
    如何对SharePoint里OOB的JavaScript文件进行Debug 之一
    UPA Sync Service启动之后立即自动停止
    SharePoint 2010服务器场的防火墙需要开放哪些端口?
  • 原文地址:https://www.cnblogs.com/wlbl/p/9853277.html
Copyright © 2011-2022 走看看