zoukankan      html  css  js  c++  java
  • Ansible-playbook

    Ansible-playbook简介

    什么是playbook?

    简单点说,playbook就是ansible用于配置,部署和管控节点机器的剧本,将一系列命令的集合归一使用,类似于shell脚本,不过更加强大.

    playbook与shell脚本比对

    它们功能形似,playbook和shell脚本一样,都是批量处理任务.都是把很多命令组合到一起,加入对应条件判断等,要说区别就是命令结构和被执行场景有所不同;

    shell脚本由一条条命令构成,一般只在当前的服务器运行;

    playbook中是有一个个task任务构成,每个task都可以当做shell中的一条命令,playbook不止在一个服务器上执行,因此它需要在其中指定运行该playbook的服务器名.而且playbook有着自己的语法格式

    playbook语法格式

    playbook由YMAL语言编写,YMAL格式类似于JSON格式,便于写读和理解,它的格式如下:

    #格式
    1.文件的第一行应该以 "---"这三个连续字符开始,代表了YAML文件的开始
    
    2.在一行中, # 后面的内容代表注释,python,ruby,shell都是如此
    
    3.YAML中的列表元素以"-"开头然后紧接着一个空格,后面为元素内容
    
    4.在同一个列表中的元素应该保持相同的缩进,否则会当作错误处理
    
    5.play中hosts ,variables,roles,tasks等对象的表示方法都是键值对,中间以 ":"分割,且":"后面还要增加一个空格.

    6.文件名称后缀为 xxx.yml/yaml #示例 --- #复制file - hosts: task01 remote_user: root tasks: - name: copyfile copy: src=/etc/passwd dest=/tmp/data

    Ansible-playbook使用

    playbook核心参数

    hosts    #主机组
    tasks    #任务列表
    vars     #变量,如下有几种设置方式
    template   #jinja2模板语法
    tags         #标签
    handlers   #由一定条件出发,就是notify咯

    ① 基本参数

    #写法
    --- #文件开头 - hosts: dbservers #指定该playbook在哪个服务器上执行 remote_user: root #指定远程的用户名, vars: #表示定义变量 http_port: 80 #变量形式key: value user: coco tasks: #构成playbook的tasks,每个task都有 - name: 开始,name 指定该任务的名称 - name: copyfile copy: src=/etc/fstab dest=/tmp/fs - name: install redis yum: name=redis

    ② ansible-playbook -h命令分析

    #常用命令
    -C   --check   #检查但是不会真的执行
    -f FORKS, --forks=FORKS  #并发,默认5个
    --list-hosts     #列出匹配的主机
    --sytax-check   #检查语法
    -t #只执行某个task任务

     ③ 执行一个playbook命令 --->ansible-playbook p1.yml (单任务)

    #p1.yml
    ---
    - hosts: web
      tasks:
      - name: install bc
        yum: name=bc

    注解:如上图所示

    - PLAY表示执行hosts 中web组远程机器

    - 第一个TASK表示正在收集两台远程机器的数据信息,采集成功为显示绿色,代表执行成功

    - 第二个TASK表示我们要执行任务的名称,执行成功后状态发生变化为黄色,状态没变化为绿色,执行失败为红色.

    ④ 再来个例子ansible-playbook p2.yml(多任务)看看效果,会更加清楚

    #p2.yml
    ---
    - hosts: web
      remote_user: root
      tasks:
      - name: createuser
        user: name=coco
      - name: deluser
        user: name=coco state=absent 
    p2.yml
    [root@localhost playbook]# ansible-playbook p2.yml 
    
    PLAY [web] *********************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [192.168.220.134]
    ok: [192.168.220.136]
    ok: [192.168.220.135]
    
    TASK [createuser] **************************************************************
    changed: [192.168.220.134]
    changed: [192.168.220.135]
    changed: [192.168.220.136]
    
    TASK [deluser] *****************************************************************
    changed: [192.168.220.134]
    changed: [192.168.220.135]
    changed: [192.168.220.136]
    
    PLAY RECAP *********************************************************************
    192.168.220.134            : ok=3    changed=2    unreachable=0    failed=0   
    192.168.220.135            : ok=3    changed=2    unreachable=0    failed=0   
    192.168.220.136            : ok=3    changed=2    unreachable=0    failed=0
    p2.yml执行结果

    注意:执行后发现第一个task任务执行完后,第二个task任务才执行的,多个task是顺序执行的,所以先创建,再删除...

    playbook幂等性

    什么意思呢?就是不管执行多少次,得到的结果永远是相同的,试着一直执行p2.yml,最终的结构都一样.

    playbook (5种传参方式)

    为什么要这么做呢?

    主要防止需求不断变化嘛,总不能反复修改文件是吧

    方式一

    ---
    #方式一
    - hosts: web
      remote_user: root
      tasks:
      - name: create{{user}}
        user: name={{user}}
    
    ansible-playbook -e user=superman p1.yml
    
    #有没有发现什么?没错就是jinja2模板语法,

     方式二

    [web]
    192.168.220.[134:135]  user=laifu
    192.168.220.136  user=wangcai
    
    #vi /etc/ansible/hosts
    #针对hosts文件进行传参,执行结果web组为全部创建laifu
    #实际上134,135会创建出laifu用户,136会创建出wangcai用户.
    
    ansible-playbook p1.yml

     方式三

    [web:vars]
    user=taidi
    
    #还是在hosts文件传参,给web组vars进行传参
    ansible-playbook p1.yml    会创建出一个taidi用户

     方式四 

    - hosts: web
      vars:
      - user: jinmao
      tasks:
      - name: create{{user}}
        user: name={{user}}
    
    
    #利用vars变量参数进行传参,执行后会创建出一个jinmao用户

     方式五 

    - hosts: web
      tasks:
      - name: yumbc
        yum: name=bc
      - name: sum
        shell: echo 8+9|bc  #linux 计算通过bc  
        register: user     #得到结果注册为user,但是拿到一个字典
      - name: echo
        shell: echo {{user.stdout}} >/tmp/sum.txt #将user字典中的stdout值取出来
      - name: createuser{{user.stdout}}
        user: name=keke{{user.stdout}}  #执行创建出keke9
    
    #上面先计算,注册user得到一个大字典,再取出user.stdout写到文件中,最后创建对应的参数的用户keke9

    注:这五种传参优先级: -e >playbook的vars >hosts

    setup模块

    在playbook中负责收集信息,因此放在这里进行补充模块信息

    ① 执行命令 ansible 192.168.220.134 -m setup |more 收集信息

    #如下是setup模块常用参数
    
    ansible_all_ipv4_addresses # 所有的ipv4地址
    ansible_all_ipv6_addresses # 所有的ipv6的地址
    ansible_bios_version # 主板bios的版本
    ansible_architecture # 架构信息
    ansible_date_time # 系统的时间
    ansible_default_ipv4 # IPv4默认地址
        address #ip地址
        alias #网卡名称
        broadcast #广播地址
        gateway # 网关
        macaddress #mac地址
        netmask #子网掩码
        network #网段
    ansible_distribution #系统的版本
    ansible_distribution_file_variety# 系统的基于对象
    ansible_distribution_major_version# 系统的主版本
    ansible_distribution_version #系统的版本
    ansible_domain #系统的域
    ansible_dns #系统的dns
    ansible_env #系统的环境变量
    ansible_hostname #系统的主机名
    ansible_fqdn #系统的完整主机名
    ansible_machine #系统的架构
    ansible_memory_mb #系统的内存信息
    ansible_os_family #系统的家族
    ansible_pkg_mgr #系统的包管理工具
    ansible_processor_cores #cpu的核数
    ansible_processor_count #每颗cpu上的颗数
    ansible_processor_vcpus #cpu的总核数=cpu的颗数*每颗cpu上的核数
    ansible_python #系统的python版本
    
    #快速筛选查找,支持正则拼接
    ansible 192.168.220.134 -m setup -a "filter=*processor*" 

    ② 正则在linux中简单实用

    [root@localhost playbook]# echo 123 |grep "[0-9]{2}"  #发现"{}"是需要转义的
    123   #取到12
    
    [root@localhost playbook]# echo 123 |grep "[0-9]?" #?也需要转义
    123   #取到123
    
    [root@localhost playbook]# echo 123 |grep "^[0-9]"
    123 #取到1
    [root@localhost playbook]# echo 123 |grep "<[0-9]" #^在linux中也可以写成>放在起始位
    123   #取到 1
    
    [root@localhost playbook]# echo 123 |grep "[0-9]$"
    123  #取到3
    [root@localhost playbook]# echo 123 |grep "[0-9]>" #^在linux中也可以写成>放在末位
    123  #取到3 

    tags

    给某个task任务加上标签,执行的时候防止重复执行yml文件中已经执行过的命令

    #p4.yml
    
    ---
    - hosts: web
      tasks:
      - name: install
        yum: name=redis
      - name: copyfile
        copy: dest=/etc/redis.conf src=/etc/redis.conf
        tags: copyall
      - name: start
        service: name=redis state=started 
    
    #执行这条命令  ansible-playbook -t copyall p4.yml ,由于tags标签名称 copyall 存在于copyfile中上述的三个task任务就只执行copyfile的task,避免重复工作.

    handlers

    由notify 进行触发执行handlers中的任务

    #p5.yml
    - hosts: web
      tasks:
      - name: install
        yum: name=redis
      - name: copyfile
        copy: dest=/etc/redis.conf src=/etc/redis.conf
        tags: copyall
        notify: restart  # 触发handlers中的task任务并执行
      - name: start
        service: name=redis state=started
      handlers:
      - name: restart
        service: name=redis state=restarted
    
    #为什么要这样写呢?
    #其实我就是想copy下文件并重启,不想执行其它 的task任务的需求
    #在copy的task任务的基础上无法再添加标签tags,这时有notify进行触发handlers参数,执行其中的task,是不是很方便呢

    template

    可以通过setup模块获取到的信息进行模板渲染到需要用的文件中.创建一个templates目录,将要渲染模板的文件放在目录中,通过jinja2语法进行替换文件中经常改动的内容

    #redis.conf
    
    bind {{ansible_default_ipv4.address}}  #替换redis绑定的ip地址,因为默认是本地的.当然还可以替换很多东西
    - hosts: web
      tasks:
      - name: install
        yum: name=redis
      - name: copyfile
        template: dest=/etc/redis.conf src=redis.conf
        tags: copyfile
        notify: restart
      - name: start
        service: name=redis state=started
      handlers:
      - name: restart
        service: name=redis state=restarted
    
    #需要在本地的目录下创建一个templates目录,就可以用相对路径,在执行copyfile所在的task时就会执行templates中的redis.conf文件,实时将各个机器地址获取到

    when

    在task中使用,jinja2的语法格式

    情景:比如在setup模块中可以获取到版本信息 ansible_distribution_version ,拿到是7,当版本为6的时候,同样的任务,执行的命令不尽相同,这时就需要判断了when

    [root@localhost playbook]# ansible 192.168.220.134 -m setup -a "filter=*distribution*"
    192.168.220.134 | SUCCESS => {
        "ansible_facts": {
            "ansible_distribution": "CentOS", 
            "ansible_distribution_file_parsed": true, 
            "ansible_distribution_file_path": "/etc/redhat-release", 
            "ansible_distribution_file_variety": "RedHat", 
            "ansible_distribution_major_version": "7", 
            "ansible_distribution_release": "Core", 
            "ansible_distribution_version": "7.5.1804"
        }, 
        "changed": false
    }

    需求1:比如在版本6和版本7生成两个文件内容不同

    #p7.yml
    ---
    - hosts: web
      tasks:
      - name: file
        copy: content="东船西舫悄无言" dest=/opt/file
        when: ansible_distribution_major_version=="7"
      - name: file
        copy: content="唯见江心秋月白" dest=/opt/file
        when: ansible_distribution_major_version=="6"
    
    #ansible-playbook p7.yml  就会在对应Contos版本生成两个文件对应的内容
    [root@localhost playbook]# ansible-playbook p7.yml 
    
    PLAY [web] *****************************************************************************************************************************************
    
    TASK [Gathering Facts] *****************************************************************************************************************************
    ok: [192.168.220.135]
    ok: [192.168.220.134]
    ok: [192.168.220.136]
    
    TASK [file] ****************************************************************************************************************************************
    changed: [192.168.220.135]
    changed: [192.168.220.134]
    changed: [192.168.220.136]
    
    TASK [file] ****************************************************************************************************************************************
    skipping: [192.168.220.134]
    skipping: [192.168.220.135]
    skipping: [192.168.220.136]
    
    PLAY RECAP *****************************************************************************************************************************************
    192.168.220.134            : ok=2    changed=1    unreachable=0    failed=0   
    192.168.220.135            : ok=2    changed=1    unreachable=0    failed=0   
    192.168.220.136            : ok=2    changed=1    unreachable=0    failed=0   
    需求1执行结果

    由于我的虚拟机上并没有安装Centos6,因此当 ansible_distribution_major_version=="6" 的时候该task任务直接跳过了.

    需求2.根据传值执行对应task

    #p6.yml
    ---
    - hosts: web
      tasks:
      - name: file
        copy: content="大弦嘈嘈如急雨
    " dest=/opt/file
        when: num=="7"
      - name: file
        copy: content="小弦切切如私语
    " dest=/opt/file
        when: num=="6"
    
    
    #ansible-playbook -e num=6 p6.yml  #当固定给num传参的时候,task任务根据参数执行,此时执行的是num=='6'的task.
    [root@localhost playbook]# ansible-playbook -e num=6 p6.yml 
    
    PLAY [web] *****************************************************************************************************************************************
    
    TASK [Gathering Facts] *****************************************************************************************************************************
    ok: [192.168.220.136]
    ok: [192.168.220.135]
    ok: [192.168.220.134]
    
    TASK [file] ****************************************************************************************************************************************
    skipping: [192.168.220.134]
    skipping: [192.168.220.135]
    skipping: [192.168.220.136]
    
    TASK [file] ****************************************************************************************************************************************
    changed: [192.168.220.134]
    changed: [192.168.220.135]
    changed: [192.168.220.136]
    
    PLAY RECAP *****************************************************************************************************************************************
    192.168.220.134            : ok=2    changed=1    unreachable=0    failed=0   
    192.168.220.135            : ok=2    changed=1    unreachable=0    failed=0   
    192.168.220.136            : ok=2    changed=1    unreachable=0    failed=0 
    需求2.执行结果

    循环

    也称迭代,当需要执行大量重复性工作的时候,对迭代项的引用,固定变量名为"item",在task中使用with_item给定要迭代的元素列表:

    ①简单循环

    示例1

    ---
    - hosts: web
      tasks:
      - name: createuser
        user: name={{item}}
        with_items:
        - hanghang
        - haha
    
    
    #执行后循环在web组内所有远程机器创建出,hanghang和haha两个用户

    示例2

    ---
    - hosts: web
      tasks:
      - name: creategroup
        group: name={{item}}
        with_items:
        - 666
        - 999
      - name: createuser
        user: name={{item}}
        with_items:
        - xxx
        - ooo
    
    #类似于python中的两个for循环,分别创建组和用户

    playbook字典功能

    嵌套循环实现

    ---
    - hosts: web
      tasks:
      - name: creategroup
        group: name={{item}}
        with_items:
        - mama
        - baba
      - name: createuser
        user: name={{item.name}} group={{item.group}}
        with_items:
        - {"name":lili,"group":mama}
        - {"name":nana,"group":baba}
    
    #执行后 用户lili对应mama组;用户nana对应baba组

    roles

    roles的作用?

    roles让playbook的众多yml文件执行更加规范,更好的进行管理yml文件,好处如下:

    目录结构清晰;

    可以互相调用,

    nginx/
    ├── files       #存放静态文件
    │   └── fstab
    ├── handlers   #存放需要触发的任务,里面必须main.yml文件
    │   └── main.yml
    ├── tasks     #存放的执行任务,里面必须main.yml文件
    │   ├── copyfile.yml
    │   ├── install.yml
    │   ├── main.yml
    │   └── start.yml
    ├── templates   #存放模板文件
    │   ├── centos6.conf
    │   └── nginx.conf
    └── vars    #存放的是参数,里面必须main.yml文件
         └── main.yml
    
    #入口文件与roles文件同级
    - hosts :web
      remote_user: root
      roles:
      - nginx

    查找顺序

    1.先查找当前目录下 roles目录里面指定的对应文件夹

    2.找到tasks目录下面的main.yml文件,如果import_tasks就导入

    3.如下

      如果遇到了template,存放是动态文件setup,去找templates文件夹下面对应的文件

      如果遇到notify,去找handlers里面的main.yml文件

      files:存放的是静态文件

      vars:存放的是参数,入口文件main.yml

      如果发现变量,如果是setup收集的变量就去setup,如果不是就去vars里面main.yml文件查找

    总结: Ansible rotes管理ansible playbook文件,形成结构化,ansible-playbook 文件管理繁多的命令.让凌乱的命令集成化和脚本化.从全面来看,ansible是一个优秀的管理工具

    ...

  • 相关阅读:
    怎么过滤JSON数组中反斜杠“”,反序列化
    ibatis教学实例
    jQuery给input CheckBox的值查询的一致就选中
    jQuery给CheckBox全选与不全选
    ThinkPHP5.1完全开发手册.CHM离线版下载
    4.2 执行环境及作用域【JavaScript高级程序设计第三版】
    21.1 XMLHttpRequest 对象【JavaScript高级程序设计第三版】
    13.4.3 鼠标与滚轮事件【JavaScript高级程序设计第三版】
    13.6 模拟事件【JavaScript高级程序设计第三版】
    14.5 富文本编辑【JavaScript高级程序设计第三版】
  • 原文地址:https://www.cnblogs.com/CrazySheldon1/p/10692573.html
Copyright © 2011-2022 走看看