zoukankan      html  css  js  c++  java
  • ansible快速文档

    ansible

    what:ansible是基于python模块paramiko开发的自动化运维工具

    why:实现了批量系统配置、批量程序部署、批量运行命令等功能

    Ansible is Simple IT Automation

    马哥ansible入门到精通及企业实战_哔哩哔哩_bilibili

    运维自动化发展历程,运维职业发展路线 – 运维派 (yunweipai.com)

    自动化运维工具——ansible详解(一) - 珂儿吖 - 博客园 (cnblogs.com)

    自动化运维工具——ansible详解(二) - 珂儿吖 - 博客园 (cnblogs.com)


    Ansible 发展史

    作者:Michael DeHaan( Cobbler 与 Func 作者)

    ansible 的名称来自科幻小说《安德的游戏》中跨越时空的即时通信工具,使用它可以在相距数光年的距离,远程实时控制前线的舰队战斗

    2012-03-09,发布0.0.1版,2015-10-17,Red Hat宣布1.5亿美元收购

    Ansible 特性

    • 模块化:调用特定的模块完成特定任务,支持自定义模块,可使用任何编程语言写模块
    • Paramiko(python对ssh的实现),PyYAML,Jinja2(模板语言)三个关键模块
    • 基于Python语言实现
    • 部署简单,基于python和SSH(默认已安装),agentless,无需代理不依赖PKI(无需ssl)
    • 安全,基于OpenSSH
    • 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
    • 支持playbook编排任务,YAML格式,编排任务,支持丰富的数据结构
    • 较强大的多层解决方案role

    注意事项

    • 基于模块化工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架
    • ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的
    • 执行ansible的主机一般称为主控端,中控,master或堡垒机
    • 主控端Python版本需要2.6或以上
    • 被控端Python版本小于2.4,需要安装python-simplejson
    • 被控端如开启SELinux需要安装libselinux-python
    • windows 不能做为主控端

    Ansible 架构

    组合INVENTORY、API、MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具

    • INVENTORY:Ansible管理主机的清单/etc/anaible/hosts
    • MODULES:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
    • PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
    • API:供第三方程序调用的应用程序编程接口

    Ansible命令执行过程

    1. 加载自己的配置文件,默认/etc/ansible/ansible.cfg
    2. 加载自己对应的模块文件,如:command
    3. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
    4. 给文件+x执行权限
    5. 执行并返回结果
    6. 删除临时py文件,退出

    1.ansible install

    1.1使用yum安装

    ansible在epel源

    yum -y install epel-release
    yum makecache
    yum -y install ansible
    安装的依赖:
    
    Installing:
    ansible noarch 2.9.24-2.el7 epel 17 M
    Installing for dependencies:
    python-babel noarch 0.9.6-8.el7 base 1.4 M
    python-backports x86_64 1.0-8.el7 base 5.8 k
    python-backports-ssl_match_hostname noarch 3.5.0.1-1.el7 base 13 k
    python-cffi x86_64 1.6.0-5.el7 base 218 k
    python-enum34 noarch 1.0.4-1.el7 base 52 k
    python-idna noarch 2.4-1.el7 base 94 k
    python-ipaddress noarch 1.0.16-2.el7 base 34 k
    python-jinja2 noarch 2.7.2-4.el7 base 519 k
    python-markupsafe x86_64 0.11-10.el7 base 25 k
    python-paramiko noarch 2.1.1-9.el7 base 269 k
    python-ply noarch 3.4-11.el7 base 123 k
    python-pycparser noarch 2.14-1.el7 base 104 k
    python-setuptools noarch 0.9.8-7.el7 base 397 k
    python2-cryptography x86_64 1.7.2-2.el7 base 502 k
    python2-httplib2 noarch 0.18.1-3.el7 epel 125 k
    python2-jmespath noarch 0.9.4-2.el7 epel 41 k
    python2-pyasn1 noarch 0.1.9-7.el7 base 100 k
    sshpass x86_64 1.06-2.el7 extras 21 k

    ##

    2.免密认证

    ssh免密码认证 - omgasw - 博客园 (cnblogs.com)

    3.配置文件

    3.1./etc/ansible/ansible.cfg

    ansible的主配置文件,其中大部分配置内容无需修改

    [defaults]
    
    # some basic default values...
    
    #inventory      = /etc/ansible/hosts        ## 主机列表配置文件
    #library        = /usr/share/my_modules/        ## 库文件存放目录
    #module_utils   = /usr/share/my_module_utils/
    #remote_tmp     = ~/.ansible/tmp        ## 临时python命令文件存放在远程主机目录
    #local_tmp      = ~/.ansible/tmp        ## 本机的临时命令执行目录
    #forks          = 5        ## 默认并发数
    #sudo_user      = root        ## 默认sudo用户
    #ask_sudo_pass = True        ##每次执行ansible命令是否询问ssh密码
    #ask_pass      = True    
    #remote_port    = 22
    
    #host_key_checking = False        ## 检查对应服务器的host_key,建议取消注释
    #log_path = /var/log/ansible.log        ## 日志文件,建议启用
    #module_name = command        ## 默认模块,可以修改为shell模块

    3.2./etc/ansible/hosts

    主机清单,可以进行分组

    # Ex 1: Ungrouped hosts, specify before any group headers.
    
    ## green.example.com
    ## blue.example.com
    ## 192.168.100.1
    ## 192.168.100.10
    
    # Ex 2: A collection of hosts belonging to the 'webservers' group
    
    ## [webservers]
    ## alpha.example.org
    ## beta.example.org
    ## 192.168.1.100
    ## 192.168.1.110
    
    # If you have multiple hosts following a pattern you can specify
    # them like this:
    
    ## www[001:006].example.com
    
    # Ex 3: A collection of database servers in the 'dbservers' group
    
    ## [dbservers]
    ## 
    ## db01.intranet.mydomain.net
    ## db02.intranet.mydomain.net
    ## 10.25.1.56
    ## 10.25.1.57

    3.3./etc/ansible/roles

    用于默认存放roles的文件夹

    [root@ansible01 ~]# ansible-galaxy list
    # /root/.ansible/roles
    # /usr/share/ansible/roles
    # /etc/ansible/roles

    4.ansible模块

    command

    默认模块,不支持管道通配等符号

    shell

    可以修改为默认模块

    [root@ansible01 ~]# ansible test -m shell -a 'df -Th'
    10.1.10.72 | CHANGED | rc=0 >>
    Filesystem              Type      Size  Used Avail Use% Mounted on
    devtmpfs                devtmpfs  979M     0  979M   0% /dev
    tmpfs                   tmpfs     991M     0  991M   0% /dev/shm
    tmpfs                   tmpfs     991M  9.5M  981M   1% /run
    tmpfs                   tmpfs     991M     0  991M   0% /sys/fs/cgroup
    /dev/mapper/centos-root xfs        25G  1.8G   24G   8% /
    /dev/mapper/centos-var  xfs        50G  555M   50G   2% /var
    /dev/mapper/centos-home xfs        10G   33M   10G   1% /home
    /dev/sda1               xfs       5.0G  196M  4.8G   4% /boot
    tmpfs                   tmpfs     199M     0  199M   0% /run/user/0

    ping

    [root@ansible01 ~]# ansible 10.1.10.72 -m ping
    10.1.10.72 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    [root@ansible01 ~]# ansible all -m ping
    10.1.10.72 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }

    script

    [root@ansible01 ~]# ansible test -m script -a /root/df.sh
    10.1.10.72 | CHANGED => {
        "changed": true, 
        "rc": 0, 
        "stderr": "Shared connection to 10.1.10.72 closed.
    ", 
        "stderr_lines": [
            "Shared connection to 10.1.10.72 closed."
        ], 
        "stdout": "Filesystem              Type      Size  Used Avail Use% Mounted on
    devtmpfs                devtmpfs  979M     0  979M   0% /dev
    tmpfs                   tmpfs     991M     0  991M   0% /dev/shm
    tmpfs                   tmpfs     991M  9.5M  981M   1% /run
    tmpfs                   tmpfs     991M     0  991M   0% /sys/fs/cgroup
    /dev/mapper/centos-root xfs        25G  1.8G   24G   8% /
    /dev/mapper/centos-var  xfs        50G  555M   50G   2% /var
    /dev/mapper/centos-home xfs        10G   33M   10G   1% /home
    /dev/sda1               xfs       5.0G  196M  4.8G   4% /boot
    tmpfs                   tmpfs     199M     0  199M   0% /run/user/0
    ", 
        "stdout_lines": [
            "Filesystem              Type      Size  Used Avail Use% Mounted on", 
            "devtmpfs                devtmpfs  979M     0  979M   0% /dev", 
            "tmpfs                   tmpfs     991M     0  991M   0% /dev/shm", 
            "tmpfs                   tmpfs     991M  9.5M  981M   1% /run", 
            "tmpfs                   tmpfs     991M     0  991M   0% /sys/fs/cgroup", 
            "/dev/mapper/centos-root xfs        25G  1.8G   24G   8% /", 
            "/dev/mapper/centos-var  xfs        50G  555M   50G   2% /var", 
            "/dev/mapper/centos-home xfs        10G   33M   10G   1% /home", 
            "/dev/sda1               xfs       5.0G  196M  4.8G   4% /boot", 
            "tmpfs                   tmpfs     199M     0  199M   0% /run/user/0"
        ]
    }

    copy

    #如目标存在,默认覆盖,此处指定先备份
    ansible websrvs -m copy -a “src=/root/test1.sh dest=/tmp/test2.sh    owner=wang  mode=600 backup=yes” 
    #指定内容,直接生成目标文件    
    ansible websrvs -m copy -a "content='test line1
    test line2' dest=/tmp/test.txt"
    #复制/etc/下的文件,不包括/etc/目录自身
    ansible websrvs -m copy -a “src=/etc/ dest=/backup”

    fetch

    从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录

    [root@ansible ~]#ansible   all -m  fetch -a 'src=/etc/redhat-release dest=/data/os'
    [root@ansible ~]#tree /data/os/
    /data/os/
    ├── 10.0.0.6
    │   └── etc
    │       └── redhat-release
    ├── 10.0.0.7
    │   └── etc
    │       └── redhat-release
    └── 10.0.0.8
        └── etc
            └── redhat-release

    file

    #创建空文件
    ansible all -m  file  -a 'path=/data/test.txt state=touch'
    ansible all -m  file  -a 'path=/data/test.txt state=absent'
    ansible all -m file -a "path=/root/test.sh owner=wang mode=755“
    #创建目录
    ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
    #创建软链接
    ansible all -m file -a ‘src=/data/testfile  dest=/data/testfile-link state=link’

    archive

    打包压缩

    ansible websrvs -m archive  -a 'path=/var/log/ dest=/data/log.tar.bz2 format=bz2  owner=wang mode=0600'

    unarchive

    解包解压缩

    1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes

    2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no

    常见参数:

    copy:默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no,会在远程主机上寻找src源文件

    remote_src:和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible主机上

    src:源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,如果是远程主机上的路径,则需要设置copy=no

    dest:远程主机上的目标路径

    mode:设置解压缩后的文件权限

    ansible all -m unarchive -a 'src=/data/foo.tgz dest=/var/lib/foo'
    ansible all -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
    ansible all -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'

    hostname

    ansible node1 -m hostname -a “name=websrv” 
    ansible 192.168.100.18 -m hostname -a 'name=node18.magedu.com'

    cron

    #备份数据库脚本
    [root@centos8 ~]#cat mysql_backup.sh 
    mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql_date +%F_%T.sql.gz
    #创建任务
    ansible 10.0.0.8 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'
    ansible websrvs   -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime"
    #禁用计划任务
    ansible websrvs   -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=yes"
    #启用计划任务
    ansible websrvs   -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=no"
    #删除任务
    ansible websrvs -m cron -a "name='backup mysql' state=absent"
    ansible websrvs -m cron -a 'state=absent name=Synctime'

    yum

    ansible websrvs -m yum -a ‘name=httpd state=present’  #安装
    ansible websrvs -m yum -a ‘name=httpd state=absent’  #删除

    service

    ansible all -m service -a 'name=httpd state=started enabled=yes'
    ansible all -m service -a 'name=httpd state=stopped'
    ansible all -m service -a 'name=httpd state=reloaded’
    ansible all -m shell -a "sed -i 's/^Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf"
    ansible all -m service -a 'name=httpd state=restarted' 

    user

    #创建用户
    ansible all -m user -a 'name=user1 comment=“test user” uid=2048 home=/app/user1 group=root'
    ansible all -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no  home=/data/nginx non_unique=yes'
    #删除用户及家目录等数据
    ansible all -m user -a 'name=nginx state=absent remove=yes'

    group

    #创建组
    ansible websrvs -m group  -a 'name=nginx gid=88 system=yes'
    #删除组
    ansible websrvs -m group  -a 'name=nginx state=absent'

    lineinfile

    ansible在使用sed进行替换时,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换时,存在问题,无法正常进行替换 。其实在ansible自身提供了两个模块:lineinfile模块和replace模块,可以方便的进行替换

    功能:相当于sed,可以修改文件内容

    ansible all -m   lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=enforcing'"
    ansible all -m lineinfile  -a 'dest=/etc/fstab state=absent regexp="^#"'

    replace

    该模块有点类似于sed命令,主要也是基于正则进行匹配和替换

    ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#1'"  
    ansible all -m replace -a "path=/etc/fstab regexp='^#(.*)' replace='1'"

    setup

    功能: setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度

    可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息

    [root@ansible01 ~]# ansible test  -m setup
    10.1.10.72 | SUCCESS => {
        "ansible_facts": {
            "ansible_all_ipv4_addresses": [
                "10.1.10.72"
            ], 
    [root@ansible01 ~]# ansible test  -m setup -a 'filter=ansible_all_ipv4_addresses'
    10.1.10.72 | SUCCESS => {
        "ansible_facts": {
            "ansible_all_ipv4_addresses": [
                "10.1.10.72"
            ], 
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false
    }

    ##

    Ansible常用模块详解 – 运维派 (yunweipai.com)

    Ansible常用模块介绍_pushiqiang的博客-CSDN博客_ansible模块介绍

    ansible 常用模块 - 一只宅男的自我修养 - 博客园 (cnblogs.com)

    5.playbook

    5.1.yaml语言

    The Official YAML Web Site

    YAML是一种可读性高的,用来表达资料序列的格式

    三种常见的数据格式

    • XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置

    • JSON:JavaScript Object Notation, JavaScript 对象表记法,主要用来数据交换或配置,不支持注释

    • YAML:YAML Ain’t Markup Language YAML 不是一种标记语言, 主要用来配置,大小写敏感,不支持tab

    可以用工具互相转换,参考网站:

    https://www.json2yaml.com/

    http://www.bejson.com/json/json2yaml/

    ansible-vault

    用于加密yml文件

    ansible-vault [create|decrypt|edit|encrypt|rekey|view]
    ansible-vault encrypt hello.yml     #加密
    ansible-vault decrypt hello.yml     #解密
    ansible-vault view hello.yml        #查看
    ansible-vault edit  hello.yml       #编辑加密文件
    ansible-vault rekey  hello.yml      #修改口令
    ansible-vault create new.yml        #创建新文件

    5.1.1.YAML语法

    • 在单一文件第一行,用连续三个连字号“-” 开始,还有选择性的连续三个点号( … )用来表示文件的结尾

    • 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能

    • 使用#号注释代码

    • 缩进必须是统一的,不能空格和tab混用

    • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的

      YAML文件内容是区别大小写的,key/value的值均需大小写敏感

    • 多个key/value可同行写也可换行写,同行使用,分隔

    • v可是个字符串,也可是另一个列表

    • 一个完整的代码块功能需最少元素需包括 name 和 task

    • 一个name只能包括一个task

    • YAML文件扩展名通常为yml或yaml

    YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔

    5.1.2.list

    列表由多个元素组成,每个元素放在不同行,且元素前均使用“-”打头,或者将所有元素用 [ ] 括起来放在同一行

    # A list of tasty fruits
    - Apple
    - Orange
    - Strawberry
    - Mango
    
    [Apple,Orange,Strawberry,Mango]

    5.1.3.Dictionary字典

    字典由多个key与value构成,key和value之间用 :分隔,所有k/v可以放在一行,或者每个 k/v 分别放在不同行

    # An employee record
    name: Example Developer
    job: Developer
    skill: Elite
    也可以将key:value放置于{}中进行表示,用,分隔多个key:value
    
    # An employee record
    {name: “Example Developer”, job: “Developer”, skill: “Elite”}
    
    或
    
    name: John Smith
    age: 41
    gender: Male
    spouse:
      name: Jane Smith
      age: 37
      gender: Female
    children:
      - name: Jimmy Smith
        age: 17
        gender: Male
      - name: Jenny Smith
        age 13
        gender: Female

    5.2.核心元素

    • Hosts 执行的远程主机列表

    • Tasks 任务集

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

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

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

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

    5.2.1.hosts

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

    one.example.com
    one.example.com:two.example.com
    192.168.1.50
    192.168.1.*
    Websrvs:dbsrvs      #或者,两个组的并集
    Websrvs:&dbsrvs     #与,两个组的交集
    webservers:!phoenix  #在websrvs组,但不在dbsrvs组
    
    举例:
    - hosts: websrvs:appsrvs

    5.2.2.remote_user

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

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

    5.2.3.task列表

    play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task

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

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

    task两种格式:

    (1) action: module arguments

    (2) module: arguments 建议使用

    注意:shell和command模块后面跟命令,而非key=value

    ---
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: install httpd
          yum: name=httpd 
        - name: start httpd
          service: name=httpd state=started enabled=yes

    5.2.4.notify和handlers

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

    - name: template configuration file
      template: src=template.j2 dest=/etc/foo.conf
      notify:
         - restart memcached
         - restart apache
    
    handlers:
        - name: restart memcached
          service:  name=memcached state=restarted
        - name: restart apache
          service: name=apache state=restarted

    5.2.5.tags

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

    ---
    - hosts: test70
      remote_user: root
      tasks:
      - name: task1
        file:
          path: /testdir/t1
          state: touch
        tags: t1
      - name: task2
        file: path=/testdir/t2
              state=touch
        tags: t2
      - name: task3
        file: path=/testdir/t3
              state=touch
        tags: t3

    5.3.变量

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

    变量定义:

    variable=value

    范例:

    http_port=80

    变量调用方式:

    通过{{ variable_name }} 调用变量,且变量名前后建议加空格,有时用“{{ variable_name }}”才生效

    变量来源:

    5.3.1.ansible 的 setup facts 远程主机的所有变量都可直接调用

    ---
    #var.yml
    - hosts: all
      remote_user: root
      gather_facts: yes
    
      tasks:
        - name: create log file
          file: name=/data/{{ ansible_nodename }}.log state=touch owner=wang mode=600
    
    ansible-playbook  var.yml

    5.3.2.通过命令行指定变量,优先级最高

    vim var2.yml
    ---
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: install package
          yum: name={{ pkname }} state=present
    
    ansible-playbook  –e pkname=httpd  var2.yml

    5.3.3.在playbook文件中定义

    vim var3.yml
    ---
    - hosts: websrvs
      remote_user: root
      vars:
        - username: user1
        - groupname: group1
    
      tasks:
        - name: create group
          group: name={{ groupname }} state=present
        - name: create user
          user: name={{ username }} group={{ groupname }} state=present
    
    ansible-playbook -e "username=user2 groupname=group2”  var3.yml

    5.3.4.在独立的变量YAML文件中定义

    可以在一个独立的playbook文件中定义变量,在另一个playbook文件中引用变量文件中的变量,比playbook中定义的变量优化级高

    cat  vars2.yml
    ---
    var1: httpd
    var2: nginx
    
    cat  var5.yml
    ---         
    - hosts: web
      remote_user: root
      vars_files:
        - vars2.yml
    
       tasks:
         - name: create httpd log
           file: name=/app/{{ var1 }}.log state=touch
         - name: create nginx log
           file: name=/app/{{ var2 }}.log state=touch

    5.3.5.主机清单文件中定义变量

    主机变量

    在inventory 主机清单文件中为指定的主机定义变量以便于在playbook中使用

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

    组(公共)变量

    在inventory 主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量,如果和主机变是同名,优先级低于主机变量

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

    调用

    vim /etc/ansible/hosts
    
    [websrvs]
    192.168.0.101 hname=www1 domain=magedu.io
    192.168.0.102 hname=www2 
    
    [websvrs:vars]
    mark=“-”
    domain=magedu.org
    
    ansible  websvrs  –m hostname –a ‘name={{ hname }}{{ mark }}{{ domain }}’
    bash
    #命令行指定变量: 
    ansible  websvrs  –e domain=magedu.cn –m hostname –a    ‘name={{ hname }}{{ mark }}{{ domain }}’

    5.4.when

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

    ---
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: "shutdown RedHat flavored systems"
          command: /sbin/shutdown -h now
          when: ansible_os_family == "RedHat"
    ---
    - hosts: websrvs
      remote_user: root
      tasks: 
        - name: install conf file to centos7
          template: src=nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
          when: ansible_distribution_major_version == "7"
        - name: install conf file to centos6
          template: src=nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
          when: ansible_distribution_major_version == "6"
    ---
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: add group nginx
          tags: user
          user: name=nginx state=present
        - name: add user nginx
          user: name=nginx state=present group=nginx
        - name: Install Nginx
          yum: name=nginx state=present
        - name: restart Nginx
          service: name=nginx state=restarted
          when: ansible_distribution_major_version == “6

    5.5.with_items

    迭代:当有需要重复性执行的任务时,可以使用迭代机制

    对迭代项的引用,固定变量名为"item"

    要在task中使用with_items给定要迭代的元素列表

    列表元素格式:

    字符串

    字典

    ---
    - hosts: websrvs
      remote_user: root
    
      tasks:
        - name: add several users
          user: name={{ item }} state=present groups=wheel
          with_items:
            - testuser1
            - testuser2
    #上面语句的功能等同于下面的语句
        - name: add user testuser1
          user: name=testuser1 state=present groups=wheel
        - name: add user testuser2
          user: name=testuser2 state=present groups=wheel
    ---
    #remove mariadb server
    - hosts: appsrvs:!192.168.38.8
      remote_user: root
    
      tasks:
        - name: stop service
          shell: /etc/init.d/mysqld stop
        - name:  delete files and dir
          file: path={{item}} state=absent
          with_items:
            - /usr/local/mysql
            - /usr/local/mariadb-10.2.27-linux-x86_64
            - /etc/init.d/mysqld
            - /etc/profile.d/mysql.sh
            - /etc/my.cnf
            - /data/mysql
        - name: delete user
          user: name=mysql state=absent remove=yes 
    ---
    - hosts:websrvs
      remote_user: root
    
      tasks
        - name: install some packages
          yum: name={{ item }} state=present
          with_items:
            - nginx
            - memcached
            - php-fpm 
    ---
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: copy file
          copy: src={{ item }} dest=/tmp/{{ item }}
          with_items:
            - file1
            - file2
            - file3
        - name: yum install httpd
          yum: name={{ item }}  state=present 
          with_items:
            - apr
            - apr-util
            - httpd

    迭代嵌套子变量:

    在迭代中,还可以嵌套子变量,关联多个变量在一起使用

    ---
    - hosts: websrvs
      remote_user: root
    
      tasks:
        - name: add some groups
          group: name={{ item }} state=present
          with_items:
            - nginx
            - mysql
            - apache
        - name: add some users
          user: name={{ item.name }} group={{ item.group }} state=present
          with_items:
            - { name: 'nginx', group: 'nginx' }
            - { name: 'mysql', group: 'mysql' }
            - { name: 'apache', group: 'apache' }
    ---
    - hosts: websrvs
      remote_user: root
    
      tasks:
        - name: add some groups
          group: name={{ item }} state=present
          with_items:
            - g1
            - g2
            - g3
        - name: add some users
          user: name={{ item.name }} group={{ item.group }} home={{ item.home }} create_home=yes state=present
          with_items:
            - { name: 'user1', group: 'g1', home: '/data/user1' }
            - { name: 'user2', group: 'g2', home: '/data/user2' }
            - { name: 'user3', group: 'g3', home: '/data/user3' }

    5.6.template

    模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法

    5.4.1.jinjia2语言

    jinja2 语言使用字面量,有下面形式:
    字符串:使用单引号或双引号
    数字:整数,浮点数
    列表:[item1, item2, …]
    元组:(item1, item2, …)
    字典:{key1:value1, key2:value2, …}
    布尔型:true/false
    算术运算:+, -, *, /, //, %, **
    比较操作:==, !=, >, >=, <, <=
    逻辑运算:and,or,not
    流表达式:For,If,When

    字面量:

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

    算术运算:

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

    比较操作符
    == 比较两个对象是否相等
    != 比较两个对象是否不等

    如果左边大于右边,返回 true
    = 如果左边大于等于右边,返回 true
    < 如果左边小于右边,返回 true
    <= 如果左边小于等于右边,返回 true

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

    ##

    5.4.2.template使用

    template功能:可以根据和参考模块文件,动态生成相类似的配置文件

    template文件必须存放于templates目录下,且命名为 .j2 结尾

    yaml/yml 文件需和templates目录平级,目录结构如下示例:
    ./
    ├── temnginx.yml
    └── templates
    └── nginx.conf.j2

    #修改文件nginx.conf.j2 
    mkdir templates
    vim templates/nginx.conf.j2
    worker_processes {{ ansible_processor_vcpus }};
    
    vim temnginx2.yml
    ---
    - hosts: websrvs
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name=nginx
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf 
        - name: start service
          service: name=nginx state=started enable=yes
    
    ansible-playbook temnginx2.yml

    5.4.3.算术运算

    [root@ansible ansible]#vim templates/nginx.conf.j2
    worker_processes {{ ansible_processor_vcpus**3 }};
    
    [root@ansible ansible]#cat templnginx.yml
    ---
    - hosts: websrvs
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name=nginx
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
          notify: restart nginx
        - name: start service
          service: name=nginx state=started enabled=yes
    
      handlers:
        - name: restart nginx
          service: name=nginx state=restarted
    
    ansible-playbook  templnginx.yml --limit 10.0.0.8

    5.4.4.template中使用流程控制 for 和 if

    template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能

    ## for

    #temlnginx2.yml
    ---
    - hosts: websrvs
      remote_user: root
      vars:
        nginx_vhosts:
          - 81
          - 82
          - 83
      tasks:
        - name: template config
          template: src=nginx.conf.j2 dest=/data/nginx.conf
    
    #templates/nginx.conf2.j2
    {% for vhost in  nginx_vhosts %}
    server {
       listen {{ vhost }}
    }
    {% endfor %}
    
    ansible-playbook -C  templnginx2.yml  --limit 10.0.0.8
    
    #生成的结果:
    server {
       listen 81   
    }
    server {
       listen 82   
    }
    server {
       listen 83   
    }
    #temlnginx3.yml
    ---
    - hosts: websrvs
      remote_user: root
      vars:
        nginx_vhosts:
          - listen: 8080
      tasks:
        - name: config file
          template: src=nginx.conf3.j2 dest=/data/nginx3.conf
    
    #templates/nginx.conf3.j2
    {% for vhost in nginx_vhosts %}   
    server {
      listen {{ vhost.listen }}
    }
    {% endfor %}
    
    ansible-playbook   templnginx3.yml  --limit 10.0.0.8
    
    #生成的结果
    server {
      listen 8080  
    }
    #templnginx4.yml
    - hosts: websrvs
      remote_user: root
      vars:
        nginx_vhosts:
          - listen: 8080
            server_name: "web1.magedu.com"
            root: "/var/www/nginx/web1/"
          - listen: 8081
            server_name: "web2.magedu.com"
            root: "/var/www/nginx/web2/"
          - {listen: 8082, server_name: "web3.magedu.com", root: "/var/www/nginx/web3/"}
      tasks:
        - name: template config 
          template: src=nginx.conf4.j2 dest=/data/nginx4.conf
    
    # templates/nginx.conf4.j2
    {% for vhost in nginx_vhosts %}
    server {
       listen {{ vhost.listen }}
       server_name {{ vhost.server_name }}
       root {{ vhost.root }}  
    }
    {% endfor %}
    
    ansible-playbook  templnginx4.yml --limit 10.0.0.8
    
    #生成结果:
    server {
        listen 8080
        server_name web1.magedu.com
        root /var/www/nginx/web1/  
    }
    server {
        listen 8081
        server_name web2.magedu.com
        root /var/www/nginx/web2/  
    }
    server {
        listen 8082
        server_name web3.magedu.com
        root /var/www/nginx/web3/  
    } 

    在模版文件中还可以使用 if条件判断,决定是否生成相关的配置信息

    ## if

    #templnginx5.yml
    - hosts: websrvs
      remote_user: root
      vars:
        nginx_vhosts:
          - web1:
            listen: 8080
            root: "/var/www/nginx/web1/"
          - web2:
            listen: 8080
            server_name: "web2.magedu.com"
            root: "/var/www/nginx/web2/"
          - web3:
            listen: 8080
            server_name: "web3.magedu.com"
            root: "/var/www/nginx/web3/"
      tasks:
        - name: template config to 
          template: src=nginx.conf5.j2 dest=/data/nginx5.conf
    
    #templates/nginx.conf5.j2
    {% for vhost in  nginx_vhosts %}
    server {
       listen {{ vhost.listen }}
       {% if vhost.server_name is defined %}
    server_name {{ vhost.server_name }}
       {% endif %}
    root  {{ vhost.root }}
    }
    {% endfor %}
    
    #生成的结果
    server {
       listen 8080
       root  /var/www/nginx/web1/
    }
    server {
       listen 8080
       server_name web2.magedu.com
       root  /var/www/nginx/web2/
    }
    server {
       listen 8080
       server_name web3.magedu.com
       root  /var/www/nginx/web3/
    }

    6.roles

    6.1.使用ansible-galaxy下载共享的roles和collection

    Ansible Galaxy

    ansible-galaxy — Ansible Documentation

    ansible-galaxy list
    ansible-galaxy install geerlingguy.redis
    ansible-galaxy remove geerlingguy.redis
    [root@ansible01 ~]# ansible-galaxy collection install community.postgresql
    Process install dependency map
    Starting collection install process
    Installing 'community.postgresql:1.4.0' to '/root/.ansible/collections/ansible_collections/community/postgresql'

    6.2.roles目录结构

    playbook.yml
    roles/
    project/    ## 项目名称,有以下子目录
    tasks/        ## 定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
    files/        ## 存放由copy或script模块等调用的文件
    vars/        ## 定义变量,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
    templates/        ## template模块查找所需要模板文件的目录
    handlers/        ## 至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
    default/        ## 设定默认变量时使用此目录中的main.yml文件,比vars的优先级低
    meta/        ## 定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含

    6.2.1.创建role的步骤

    (1) 创建以roles命名的目录

    (2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等

    (3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建

    (4) 在playbook文件中,调用各角色

    针对大型项目使用Roles进行编排

    nginx-role.yml 
    roles/
    └── nginx 
         ├── files
         │    └── main.yml 
         ├── tasks
         │    ├── groupadd.yml 
         │    ├── install.yml 
         │    ├── main.yml 
         │    ├── restart.yml 
         │    └── useradd.yml 
         └── vars 
              └── main.yml

    6.2.2.playbook调用roles

    ---
    - hosts: websrvs
      remote_user: root
      roles:
        - mysql
        - memcached
        - nginx   
    ---
    - hosts: all
      remote_user: root
      roles:
        - mysql
        - { role: nginx, username: nginx }        ## 键role用于指定角色名称,后续的k/v用于传递变量给角色
    ---
    - hosts: all
      remote_user: root
      roles:
        - { role: nginx, username: nginx, when: ansible_distribution_major_version == ‘7’  }        ## 基于条件测试实现角色调用
    ---
    - hosts: websrvs
      remote_user: root
      roles:
        - { role: nginx ,tags: [ 'nginx', 'web' ] ,when: ansible_distribution_major_version == "6“ }
        - { role: httpd ,tags: [ 'httpd', 'web' ]  }
        - { role: mysql ,tags: [ 'mysql', 'db' ] }
        - { role: mariadb ,tags: [ 'mariadb', 'db' ] }
    
    ansible-playbook --tags="nginx,httpd,mysql" nginx-role.yml        ## roles中使用tags
  • 相关阅读:
    【tarjan】BZOJ 1051:受欢迎的牛
    【递推】BZOJ 1088: [SCOI2005]扫雷Mine
    【计算几何】多边形
    【贪心】Bzoj 2457:[BeiJing2011]双端队列
    【单调栈】Bzoj 1012: 最大数maxnumber
    [洛谷P3584] POI2015 LAS
    [洛谷P4049] JSOI2007 合金
    [51nod1533] 一堆的堆
    [AGC018E] Sightseeing Plan
    [CF1065E] Side Transmutations
  • 原文地址:https://www.cnblogs.com/omgasw/p/15136352.html
Copyright © 2011-2022 走看看