ansible

作者: 毛利卷卷发 | 来源:发表于2018-07-25 10:33 被阅读0次

    简介

    架构

    ansible架构.jpg

    原理

    ansible原理.jpg

    组成

    ANSIBLE PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件

    INVENTORY:Ansible管理主机的清单/etc/anaible/hosts

    MODULES:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义

    PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用

    API:供第三方程序调用的应用程序编程接口

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

    安装

    rpm包安装

    基于epel:yum install ansible

    编译安装

    1. yum -y install python-jinja2 PyYAMLpython-paramikopython-babelpython-crypto
    2. tar xfansible-1.5.4.tar.gz
    3. cdansible-1.5.4
    4. python setup.pybuild
    5. python setup.pyinstall
    6. mkdir/etc/ansible
    7. cp -r examples/* /etc/ansible

    git安装

    1. gitclone git://github.com/ansible/ansible.git --recursive
    2. cd ./ansible
    3. source ./hacking/env-setup

    pip安装

    pip是安装Python包的管理器,类似yum

    1. yum install python-pip python-devel
    2. yum install gccglibc-develzibl-develrpm-bulidopenssl-devel
    3. pip install --upgrade pip
    4. pip install ansible--upgrade

    inventory

    主机清单,ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名

    默认的inventory file为/etc/ansible/hosts

    inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成

    /etc/ansible/hosts

    ntp.magedu.com
    
    [webservers] # 分组名称
    www1.magedu.com:2222 # 默认是ssh的22端口,如果不是22端口需要指定端口号
    www2.magedu.com
    
    [dbservers]
    db1.magedu.com
    db2.magedu.com
    db3.magedu.com
    
    [websrvs]
    www[01:100].example.com # 列表方式表示主机
    
    [dbsrvs]
    db-[a:f].example.com
    

    /etc/ansible/ansible.cfg

    主配置文件,一般保持默认

    [defaults]
    #inventory = /etc/ansible/hosts # 主机列表配置文件
    #library = /usr/share/my_modules/ # 库文件存放目录
    #remote_tmp= $HOME/.ansible/tmp # 临时py命令文件存放在远程主机目录
    #local_tmp= $HOME/.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 # 日志文件,建议取消注释
    

    命令

    执行过程

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

    执行状态

    • 绿色:执行成功并且不需要做改变的操作
    • 黄色:执行成功并且对目标主机做变更
    • 红色:执行失败

    ansible

    ansible <host-pattern> [-m module_name][-a args],常用选项:

    • --version:显示版本
    • -m module:指定模块,默认位command,可通过修改/etc/ansible/ansible.cfg来修改
    • -v:详细过程,-vv,-vvv
    • --list-host:显示主机列表,可简写--list
    • -k/--ask-pass:提示输入ssh连接密码,默认是key验证
    • -K/--ask-become-pass:提示输入sudo时的口令
    • -C/--check:检查,并不执行
    • -T/--timeout=TIMEOUT:执行命令的超时时间,默认为10s
    • -u/--user=REMOTE_user:远程执行时使用的用户
    • -b/--become:代替旧版的sudo切换

    Host-pattern

    匹配主机的列表

    All :表示所有Inventory中的所有主机

    ansibleall –m ping
    

    * :通配符

    ansible "*" -m ping
    ansible 192.168.1.* -m ping
    ansible "*srvs" -m ping
    

    : :逻辑或

    ansible 192.168.39.129:192.168.39.140 -m ping
    

    :& :逻辑与

    ansible "websrvs:&dbsrvs" –m ping
    

    :! :逻辑非

    ansible 'websrvs:!dbsrvs' –m ping # 在websrvs组,但不在dbsrvs组中的主机。注意:此处为单引号
    

    综合逻辑

    ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping
    

    正则表达式

    ansible "websrvs:&dbsrvs" –m ping
    ansible "~(web|db).*\.magedu\.com" –m ping
    

    示例:

    # 以wang用户执行ping存活检测
    ansible all -m ping -u wang -k
    
    # 以wang sudo至root执行ping存活检测
    ansible all -m ping -u wang –b -k
    
    # 以wang sudo至mage用户执行ping存活检测
    ansible all -m ping -u wang –b -k --become-user mage
    
    # 以wang sudo至root用户执行ls
    ansible all -m command -u wang --become-user=root -a 'ls /root' -b –k -K
    

    module

    ansible-doc -l:列出所有可用模块

    ansible-doc -s MODULE:先查看模块帮助

    command

    在远程主机执行命令,默认模块,可执行简单命令,可忽略-m选项

    ansiblesrvs-m command -a 'service vsftpd start'
    ansiblesrvs-m command -a 'echo magedu|passwd--stdinwang' # 不成功
    

    注意:不支持$VARNAME<>|;& 等,用shell模块实现

    shell

    和command相似,用shell执行命令,调用bash执行命令

    ansiblesrv-m shell -a 'echo magedu|passwd –stdin wang'
    

    注意:即使使用shell也可能会失败(解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器)

    script

    运行脚本

    [root@centos6 app]# cat f1.sh 
    #!/bin/bash
    touch /app/test.txt
    
    [root@centos6 app]# ansible all -m script -a 'f1.sh'
    
    [root@centos6 app]# ansible all -m command -a 'ls /app'
    192.168.39.139 | SUCCESS | rc=0 >>
    test.txt
    
    192.168.39.129 | SUCCESS | rc=0 >>
    test.txt
    
    192.168.39.140 | SUCCESS | rc=0 >>
    test.tx
    
    copy

    从主控端复制文件到被控端,推送

    # 如目标存在,默认覆盖,此处指定先备份
    ansiblesrv-m copy -a "src=/root/f1.sh dest=/tmp/f2.sh backup=yes"
    
    # 利用内容,直接生成目标文件
    ansiblesrv-m copy -a "content='test content\n' dest=/tmp/f1.txt"
    

    注意:src可以使用相对路径,基于yml文件的相对路径

    fetch

    从被控端取文件到主控端,与copy相反,拉取,目录可先tar

    [root@centos6 app]# ansible all -m fetch -a 'src=/app/nihao dest=/app/'
    
    [root@centos6 app]# tree
    .
    ├── 192.168.39.129
    │   └── app
    │       └── nihao
    ├── 192.168.39.139
    │   └── app
    │       └── nihao
    └── 192.168.39.140
        └── app
            └── nihao
    

    注意:直接拉取过来不是单文件,而是全路径的文件

    file

    设置文件属性

    # 修改被控端文件属主和权限
    ansiblesrv-m file -a "path=/root/a.sh owner=wangmode=755"
    
    # 在被控端创建软连接
    ansibleweb -m file -a 'src=/app/testfiledest=/app/testfile-link state=link'
    
    hostname

    管理主机名,修改主机名,永久生效

    ansible test -m hostname -a 'name=test'
    
    cron

    计划任务

    [root@centos6 ~]# ansible all -m cron -a 'minute=*/5 job="/usr/sbin/ntpdate 172.18.0.1 &> /dev/null" name=synctime' # 创建计划任务
    
    [root@centos6 ~]# ansible all -a 'crontab -l'
    192.168.39.139 | SUCCESS | rc=0 >>
    #Ansible: synctime
    */5 * * * * /usr/sbin/ntpdate 172.18.0.1 &> /dev/null
    
    192.168.39.129 | SUCCESS | rc=0 >>
    #Ansible: synctime
    */5 * * * * /usr/sbin/ntpdate 172.18.0.1 &> /dev/null
    
    192.168.39.140 | SUCCESS | rc=0 >>
    #Ansible: synctime
    */5 * * * * /usr/sbin/ntpdate 172.18.0.1 &> /dev/null
    
    [root@centos6 ~]# ansible all -m cron -a 'state=absent name=synctime' # 删除计划任务
    
    [root@centos6 ~]# ansible all -a 'crontab -l'
    192.168.39.139 | SUCCESS | rc=0 >>
    
    
    192.168.39.129 | SUCCESS | rc=0 >>
    
    
    192.168.39.140 | SUCCESS | rc=0 >>
    
    
    yum

    管理包

    ansible srv-m yum -a 'name=httpdstate=latest' # 安装
    ansiblesrv-m yum -a 'name=httpdstate=absent' # 删除
    
    service

    管理服务

    ansible srv-m service -a 'name=httpdstate=stopped' # 关闭服务
    ansiblesrv-m service -a 'name=httpdstate=started' # 开启服务
    ansiblesrv–m service –a 'name=httpdstate=reloaded' # 重载配置文件
    ansiblesrv-m service -a 'name=httpdstate=restarted' # 重启服务
    
    user

    管理用户

    # 创建用户,添加描述信息,指定uid,指定家目录,指定属组
    ansible srv -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root'
    
    # 创建系统用户,指定家目录
    ansible srv -m user -a 'name=sysuser1 system=yes home=/app/sysuser1'
    
    # 删除用户,并删除家目录
    ansible srv -m user -a 'name=user1 state=absent remove=yes'
    
    group

    管理组

    ansible srv -m group -a "name=testgroupsystem=yes" # 创建系统组
    ansiblesrv-m group -a "name=testgroupstate=absent" # 删除组
    

    ansible-doc

    显示模块帮助,ansible-doc [options][module...],常用选项:

    • -a:显示所有模块的文档
    • -l/--list:列出可用模块
    • -s/--snippet:显示指定模块的playbook片段
    ansible-doc –l # 列出所有模块
    ansible-doc ping # 查看指定模块帮助用法
    ansible-doc –s ping # 查看指定模块帮助用法
    

    ansible-galaxy

    连接https://galaxy.ansible.com 下载相应的roles

    列出所有已安装的galaxy:ansible-galaxy list

    安装galaxy:ansible-galaxy install geerlingguy.redis

    删除galaxy:ansible-galaxy remove geerlingguy.redis

    ansible-pull

    推送命令至远程,效率无限提升,对运维要求较高

    ansible-playbook

    ansible-playbook <filename.yml> ... [options],常用选项:

    • --check:只检测可能会发生的改变,但不真正执行操作
    • --list-hosts:列出运行任务的主机
    • --limit:指定主机列表,只针对主机列表中的主机执行
    • -v:详细过程,-vv,-vvv
    ansible-playbook file.yml--check # 只检测,不执行
    ansible-playbook file.yml # 执行
    ansible-playbook file.yml--limit websrvs # 指定主机列表执行
    

    ansible-vault

    管理加密解密yml文件,常用动作:

    • encrypt:加密
    • decrypt:解密
    • view:查看
    • edit:编辑机密文件
    • rekey:修改口令
    • create:创建新文件

    ansible-console

    2.0+新增,可交互执行命令,支持tab

    root@all (3)[f:5]:执行用户@当前操作的主机组(当前组的主机数量)[f:并发数]

    设置并发数:forks n 例如:forks 10

    切换组:cd 主机组例如:cd web

    列出当前组主机列表:list

    列出所有的内置命令:?或help

    [root@centos6 app]# ansible-console
    Welcome to the ansible console.
    Type help or ? to list commands.
    
    root@all (3)[f:5]$ list
    192.168.39.129
    192.168.39.140
    192.168.39.139
    root@all (3)[f:5]$ cd webservers
    root@webservers (2)[f:5]$ list
    192.168.39.129
    192.168.39.140
    root@webservers (2)[f:5]$ yum name=httpdstate=present
    root@webservers (2)[f:5]$ service name=httpdstate=started
    root@webservers (2)[f:5]$ shell ss -tnl|grep :80
    192.168.39.129 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::80                      :::*                  
    
    192.168.39.140 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::80                      :::* 
    

    playbook

    playbook是由一个或多个“play”组成的列表

    play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同唱一台大戏

    Playbook采用YAML语言编写

    playbook.jpg

    YAML

    YAML是一个可读性高的用来表达资料序列的格式。更多的内容及规范参见http://www.yaml.org

    • 在单一档案中,可用连续三个连字号(——)区分多个档案。另外,还有选择性的连续三个点号( ... )用来表示档案结尾
    • 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
    • 使用#号注释代码
    • 缩进必须是统一的,不能空格和tab混用
    • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
    • YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感
    • k/v的值可同行写也可换行写。同行使用:分隔
    • v可是个字符串,也可是另一个列表
    • 一个完整的代码块功能需最少元素需包括name: task
    • 一个name只能包括一个task
    • YAML文件扩展名通常为yml或yaml
    • List:列表,其所有元素均使用“-”打头。具体在ansible playbook中,列表所描述的是局部环境,它不一定要有名称,不一定要从同一个属性开始,只要使用"- ",它就表示圈定一个范围,范围内的项都属于该列表
    • Dictionary:字典,通常由多个key与value构成。具体到playbook中,一般"虚拟性"的内容都可以通过字典的方式书写,而实体化的、动作性的、对象性的内容则应该定义为列表形式。
    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
    

    hosts

    用于指定要执行指定任务的主机,须事先定义在主机清单中

    格式:

    • 192.168.1.*
    • Websrvs:dbsrvs:两个组的并集
    • Websrvs:&dbsrvs:两个组的交集
    • webservers:!phoenix:在websrvs组,但不在dbsrvs组
      - hosts: websrvs:dbsrvs
    

    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
    

    gather_facts

    ansible-playbook的第一个步骤总是执行gather_facts,不论你有没有再playbook设定这个tasks,而且通常这步时间都会比较久,因为需要家藏facts库。因此如果不需要获取被控端fact数据的话,可以关闭fact数据功能(playbook中添加 gather_facts: no 和hosts对齐即可)

    ---
    - hosts: '7'
      remote_user: root
      gather_facts: no
      tasks:
        - name: touch file
          file: name=/app/test state=touch
    

    可以设置"gather_facts: no"来禁止ansible收集facts信息,但是有时候又需要使用facts中的内容,这时候可以设置facts的缓存。例如,在空闲的时候收集facts,缓存下来,在需要的时候直接读取缓存进行引用。

    先来查看一下/etc/ansible/ansible.cfg中facts的默认设置

    #gathering = implicit
    

    gathering的三种状态:

    • implicit:默认收集
    • explicit:默认不收集
    • smart:默认收集,但facts已有的情况下不会收集,即使用缓存facts

    tasks

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

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

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

    # 临时禁用selinux
    tasks:
      - name: disable selinux
        command: /sbin/getenforce 0
        
    # 如果命令或脚本的退出码不为零,可以使用如下方式替代
    tasks:
      - name: run this command and ignore the result
        shell: /usr/bin/somecommand || /bin/true
        
    # 或者使用ignore_errors来忽略错误信息
    tasks:
      - name: run this command and ignore the result
        shell: /usr/bin/somecommand
        ignore_errors: true
    
    [root@centos6 app]# cat httpd.yml 
    ---
    
    - hosts: webservers
      remote_user: root
      tasks:
        - name: install httpd
          yum: name=httpd
        - name: copy httpd.conf
          copy: src=/app/httpd7.conf dest=/etc/httpd/conf/httpd.conf
        - name: start httpd
          service: name=httpd state=started
    
    - hosts: appservers
      remote_user: root
      tasks:
        - name: install httpd
          yum: name=httpd
        - name: copy httpd.conf
          copy: src=/app/httpd6.conf dest=/etc/httpd/conf/httpd.conf
        - name: start httpd
          service: name=httpd state=started
    
    [root@centos6 app]# ansible-playbook httpd.yml --list-hosts
    
    playbook: httpd.yml
    
      play #1 (webservers): webservers  TAGS: []
        pattern: [u'webservers']
        hosts (2):
          192.168.39.140
          192.168.39.129
    
      play #2 (appservers): appservers  TAGS: []
        pattern: [u'appservers']
        hosts (1):
          192.168.39.139
    [root@centos6 app]# ansible-playbook httpd.yml --check
    
    PLAY RECAP ************************************************************************
    192.168.39.129             : ok=4    changed=3    unreachable=0    failed=0   
    192.168.39.139             : ok=4    changed=3    unreachable=0    failed=0   
    192.168.39.140             : ok=4    changed=3    unreachable=0    failed=0   
    
    [root@centos6 app]# ansible-playbook httpd.yml
    
    PLAY RECAP ************************************************************************
    192.168.39.129             : ok=4    changed=3    unreachable=0    failed=0   
    192.168.39.139             : ok=4    changed=3    unreachable=0    failed=0   
    192.168.39.140             : ok=4    changed=3    unreachable=0    failed=0   
    
    [root@centos6 app]# ansible all -m shell -a 'ss -tnl |grep :8080'
    192.168.39.139 | SUCCESS | rc=0 >>
    LISTEN     0      128                      :::8080                    :::*     
    
    192.168.39.129 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::8080                    :::*                  
    
    192.168.39.140 | SUCCESS | rc=0 >>
    LISTEN     0      128         :::8080                    :::* 
    

    handles和notify

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

    notify:用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作

    [root@centos6 app]# cat httpd.yml 
    ---
    
    - hosts: appservers
      remote_user: root
      tasks:
        - name: install httpd
          yum: name=httpd
        - name: copy httpd.conf
          copy: src=/app/httpd6.conf dest=/etc/httpd/conf/httpd.conf
          notify: restart httpd
        - name: start httpd
          service: name=httpd state=started
      handlers: 
        - name: restart httpd
          service: name=httpd state=restarted
    
    [root@centos6 app]# ansible-playbook httpd.yml 
    
    RUNNING HANDLER [restart httpd] ***************************************************
    changed: [192.168.39.139]
    
    PLAY RECAP ************************************************************************
    192.168.39.139             : ok=5    changed=2    unreachable=0    failed=0   
    
    
    [root@centos6 app]# ansible appservers -m shell -a 'ss -tnl |grep :9527'
    192.168.39.139 | SUCCESS | rc=0 >>
    LISTEN     0      128                      :::9527                    :::*
    
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: add group nginx
          tags: user
          user: name=nginxstate=present
        - name: add user nginx
          user: name=nginxstate=present         group=nginx
        - name: Install Nginx
          yum: name=nginxstate=present
        - name: config
          copy: src=/root/config.txtdest=/etc/nginx/nginx.conf
          notify:
            - Restart Nginx
            - Check NginxProcess
      handlers:
        - name: Restart Nginx
          service: name=nginxstate=restarted enabled=yes
        - name: Check Nginxprocess
          shell: killall-0 nginx> /tmp/nginx.log # 检查进程是否启动
    

    tags

    相当于给tasks中的action起个别名,配合ansible-lpaybook -t TAGS file.yml来执行文件中的指定标签action

    注意:-t选项可以指定多个标签同时执行,多个action也可以定义为同一个标签

    [root@centos6 app]# ansible appservers -m shell -a 'ss -tnl |grep :9527'
    192.168.39.139 | SUCCESS | rc=0 >>
    LISTEN     0      128                      :::9527                    :::*     
    
    [root@centos6 app]# cat httpd.yml 
    ---
    
    - hosts: appservers
      remote_user: root
      tasks:
        - name: install httpd
          yum: name=httpd
        - name: copy httpd.conf
          copy: src=/app/httpd6.conf dest=/etc/httpd/conf/httpd.conf
          notify: restart httpd
          tags: conf
        - name: start httpd
          service: name=httpd state=started
      handlers: 
        - name: restart httpd
          service: name=httpd state=restarted
    
    [root@centos6 app]# ansible-playbook httpd.yml --list-tags
    
    playbook: httpd.yml
    
      play #1 (appservers): appservers  TAGS: []
          TASK TAGS: [conf]
          
    [root@centos6 app]# ansible-playbook -t conf httpd.yml 
    
    PLAY [appservers] *****************************************************************
    
    TASK [Gathering Facts] ************************************************************
    ok: [192.168.39.139]
    
    TASK [copy httpd.conf] ************************************************************
    changed: [192.168.39.139]
    
    RUNNING HANDLER [restart httpd] ***************************************************
    changed: [192.168.39.139]
    
    PLAY RECAP ************************************************************************
    192.168.39.139             : ok=3    changed=2    unreachable=0    failed=0   
    
    [root@centos6 app]# ansible appservers -m shell -a 'ss -tnl |grep :80'
    192.168.39.139 | SUCCESS | rc=0 >>
    LISTEN     0      128                      :::80                      :::* 
    

    vars

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

    变量来源:

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

      ansible 192.168.39.139 -m setup # 收集关于远程主机的事实,可以看到变量
      
      [root@centos6 app]# cat var.yml 
      ---
      
      - hosts: appservers
        remote_user: root
        tasks:
          - name: create log file
            file: name=/app/{{ ansible_fqdn }} state=touch
            
      [root@centos6 app]# ansible appservers -m setup |grep ansible_fqdn
              "ansible_fqdn": "test", 
              
      [root@centos6 app]# ansible-playbook var.yml --check
      PLAY RECAP ************************************************************************
      192.168.39.139             : ok=2    changed=1    unreachable=0    failed=0   
      
      [root@centos6 app]# ansible-playbook var.yml 
      PLAY RECAP ************************************************************************
      192.168.39.139             : ok=2    changed=1    unreachable=0    failed=0   
      
      [root@centos6 app]# ansible appservers -a "ls /app"
      192.168.39.139 | SUCCESS | rc=0 >>
      test
      
    2. 在/etc/ansible/hosts中定义

      [webservers]
      192.168.39.129 http_port=81 # 普通变量,仅在当前主机生效,优先级高于公共变量
      192.168.39.140 http_port=82
      http_port=80 # 公共变量,组内主机都可用,
      
    3. 通过命令行指定变量,优先级最高

      ansible-playbook –e varname=value
      
      [root@centos6 app]# cat var.yml 
      ---
      
      - hosts: appservers
        remote_user: root
        tasks:
          - name: install package
            yum: name={{ pkname }} state=present
            
      [root@centos6 app]# ansible-playbook -e pkname=lftp var.yml 
      PLAY RECAP ************************************************************************
      192.168.39.139             : ok=2    changed=1    unreachable=0    failed=0   
      
      [root@centos6 app]# ansible appservers -a "rpm -q lftp"
       [WARNING]: Consider using the yum, dnf or zypper module rather than running rpm.
      If you need to use command because yum, dnf or zypper is insufficient you can add
      warn=False to this command task or set command_warnings=False in ansible.cfg to
      get rid of this message.
      
      192.168.39.139 | SUCCESS | rc=0 >>
      lftp-4.0.9-14.el6.x86_64
      
    4. 在playbook中定义

      vars:
        - http6_port: 8080
        - http7_port: 9527
      
      [root@centos6 app]# cat var.yml 
      ---
      
      - hosts: appservers
        remote_user: root
        vars:
          - username=user1
          - groupname=group1
        tasks:
          - name: create user
            user: name={{ username }}
          - group: create group
            group: name={{  groupname }}
      
      [root@centos6 app]# ansible-playbook var.yml
      
      [root@centos6 app]# ansible-playbook -e "username=user2 groupname=group2" var2.yml # 命令行的优先级最高
      
    5. 在独立的变量YAML文件中定义,然后再playbook中引用

      [root@centos6 app]# cat vars.yml 
      var1: httpd
      var2: lftp
      
      [root@centos6 app]# cat var.yml 
      ---
      
      - hosts: appservers
        remote_user: root
        vars_files:
          - vars.yml
        tasks:
          - name: create httpd log
            file: name=/app/{{ var1 }}.log state=touch
          - name: create lftp log
            file: name=/app/{{ var2 }}.log state=touch
            
      [root@centos6 app]# ansible-playbook var.yml --check
      PLAY RECAP ************************************************************************
      192.168.39.139             : ok=3    changed=2    unreachable=0    failed=0   
      
      [root@centos6 app]# ansible-playbook var.yml
      PLAY RECAP ************************************************************************
      192.168.39.139             : ok=3    changed=2    unreachable=0    failed=0   
      
      [root@centos6 app]# ansible appservers -a 'ls /app'
      192.168.39.139 | SUCCESS | rc=0 >>
      httpd.log
      lftp.log
      
    6. 在role中定义

    变量调用:

    1. 通过{{ variable_name}} 调用变量,且变量名前后必须有空格,有时用"{{ variable_name}}"才生效

    2. ansible-playbook –e 选项指定

      ansible-playbook test.yml-e "hosts=www user=magedu"
      

    templates

    模板,根据模块文件动态生成对应的配置文件

    注意:

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

    2. yaml/yml文件需和templates目录平级,目录结构如下:

      ├── temnginx.yml
      └── templates
          └── nginx.conf.j2
      

    示例:利用templates 同步nginx配置文件

    [root@centos6 app]# cat temnginx.yml 
    ---
    
    - hosts: appservers
      remote_user: root
      tasks:
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
          notify: restart service
        - name: start service
          service: name=nginx state=starte
      handlers:
        - name: restart service
          service: name=nginx state=restarted
          
    [root@centos6 app]# ansible-playbook temnginx.yml
    PLAY RECAP ************************************************************************
    192.168.39.139             : ok=3    changed=1    unreachable=0    failed=0   
    
    [root@centos6 app]# ansible appservers -a 'ps aux |grep nginx'
    192.168.39.139 | SUCCESS | rc=0 >>
    root      11997  0.0  0.4 108944  2048 ?        Ss   21:18   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     11999  0.0  0.5 109368  2700 ?        S    21:18   0:00 nginx: worker process                   
    root      12062  0.0  0.2 106120  1136 pts/2    S+   21:18   0:00 /bin/sh -c ps aux |grep nginx
    root      12064  0.0  0.1 103336   848 pts/2    S+   21:18   0:00 grep nginx
    

    修改文件nginx.conf.j2 下面行为
    worker_processes{{ ansible_processor_vcpus}};

    [root@centos6 app]# ansible-playbook temnginx.yml
    PLAY RECAP ************************************************************************
    192.168.39.139             : ok=3    changed=1    unreachable=0    failed=0   
    
    [root@centos6 app]# ansible appservers -a 'ps aux |grep nginx'
    192.168.39.139 | SUCCESS | rc=0 >>
    root      11997  0.0  0.4 108944  2048 ?        Ss   21:18   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     11999  0.0  0.5 109368  2700 ?        S    21:18   0:00 nginx: worker process                   
    root      12062  0.0  0.2 106120  1136 pts/2    S+   21:18   0:00 /bin/sh -c ps aux |grep nginx
    root      12064  0.0  0.1 103336   848 pts/2    S+   21:18   0:00 grep nginx
    

    算术运算

    vim nginx.conf.j2:worker_processes{{ ansible_processor_vcpus**2 }};

    [root@centos6 app]# ansible-playbook temnginx.yml
    PLAY RECAP ************************************************************************************************************************************************************
    192.168.39.139             : ok=3    changed=1    unreachable=0    failed=0   
    
    [root@centos6 app]# ansible appservers -a 'ps aux |grep nginx'
    192.168.39.139 | SUCCESS | rc=0 >>
    root      13307  0.0  0.4 108944  2048 ?        Ss   21:27   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     13309  0.0  0.5 109368  2792 ?        S    21:27   0:00 nginx: worker process                   
    nginx     13310  0.0  0.5 109368  2700 ?        S    21:27   0:00 nginx: worker process                   
    root      13373  0.0  0.2 106120  1140 pts/2    S+   21:27   0:00 /bin/sh -c ps aux |grep nginx
    root      13375  0.0  0.1 103336   852 pts/2    S+   21:27   0:00 grep nginx
    

    vim nginx.conf.j2:worker_processes{{ ansible_processor_vcpus+2 }};

    [root@centos6 app]# ansible-playbook temnginx.yml
    PLAY RECAP ************************************************************************************************************************************************************
    192.168.39.139             : ok=3    changed=2    unreachable=0    failed=0  
    [root@centos6 app]# ansible appservers -a 'ps aux |grep nginx'
    192.168.39.139 | SUCCESS | rc=0 >>
    root      13747  0.0  0.4 108944  2052 ?        Ss   21:30   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx     13749  0.0  0.5 109368  2796 ?        S    21:30   0:00 nginx: worker process                   
    nginx     13750  0.0  0.5 109368  2796 ?        S    21:30   0:00 nginx: worker process                   
    nginx     13751  0.0  0.5 109368  2776 ?        S    21:30   0:00 nginx: worker process                   
    root      13814  0.0  0.2 106120  1136 pts/2    S+   21:31   0:00 /bin/sh -c ps aux |grep nginx
    root      13816  0.0  0.1 103336   852 pts/2    S+   21:31   0:00 grep nginx
    

    for

    格式如下:

    { % for VAR in LIST % }
        代码块
    { % endfor % }
    

    示例:

    // temnginx.yml
    ---
    - hosts: mageduweb
      remote_user: root
      vars:
        nginx_vhosts:
          - web1
          - web2
          - web3
      tasks:
        - name: template config
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    
    // templates/nginx.conf.j2
    {% for vhostin nginx_vhosts%}
    server {
      listen {{ vhost}}
    }
    {% endfor%}
    
    生成的结果:
    server {
      listen web1
    }
    server {
      listen web2
    }
    server {
      listen web3
    }
    
    // temnginx.yml
    - hosts: mageduweb
      remote_user: root
      vars:
        nginx_vhosts:
          - web1:
            listen: 8080
            server_name: "web1.magedu.com"
            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
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    
    // templates/nginx.conf.j2
    {% for vhostin nginx_vhosts%}
    server {
      listen {{ vhost.listen}}
      server_name {{ vhost.server_name}}
      root {{ vhost.root}}
    }
    {% endfor%}
    
    生成结果:
    server {
      listen 8080
      server_nameweb1.magedu.com
      root /var/www/nginx/web1/
    }
    server {
      listen 8080
      server_nameweb2.magedu.com
      root /var/www/nginx/web2/
    }
    server {
      listen 8080
      server_nameweb3.magedu.com
      root /var/www/nginx/web3/
    }
    

    if

    格式如下:

    {% if vhost.server_name is defined %}
    server_name {{ vhost.server_name }};
    {% endif %}
    

    示例:

    // temnginx.yml
    - hosts: mageduweb
      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 configto
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    
    // templates/nginx.conf.j2
    {% for vhostin nginx_vhosts%}
    server {
      listen {{ vhost.listen}}
      {% if vhost.server_nameis defined %}
      server_name {{ vhost.server_name}}
      {% endif%}
      root {{ vhost.root}}
    }
    {% endfor%}
    
    生成的结果
    server {
      listen 8080
      root /var/www/nginx/web1/
    }
    server {
      listen 8080
      server_nameweb2.magedu.com
      root /var/www/nginx/web2/
    }
    server {
      listen 8080
      server_nameweb3.magedu.com
      root /var/www/nginx/web3/
    }
    

    when

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

    示例:

    - name: "shutdown RedHatflavored systems"
      command: /sbin/shutdown -h now
      when: ansible_os_family == "RedHat"
    

    当系统版本为6时,重启nginx服务

    [root@centos6 app]# cat when.yml 
    ---
    
    - hosts: all
      remote_user: root
      tasks:
        - name: restart nginx
          service: name=nginx state=restarted
          when: ansible_distribution_major_version == "6"
          
    [root@centos6 app]# ansible-playbook when.yml 
    
    PLAY [all] ************************************************************************
    
    TASK [Gathering Facts] ************************************************************
    ok: [192.168.39.139]
    ok: [192.168.39.129]
    ok: [192.168.39.140]
    
    TASK [restart nginx] **************************************************************
    skipping: [192.168.39.129]
    skipping: [192.168.39.140]
    changed: [192.168.39.139]
    
    PLAY RECAP ************************************************************************
    192.168.39.129             : ok=1    changed=0    unreachable=0    failed=0   
    192.168.39.139             : ok=2    changed=1    unreachable=0    failed=0   
    192.168.39.140             : ok=1    changed=0    unreachable=0    failed=0 
    
    [root@centos6 app]# cat when.yml 
    ---
    
    - hosts: all
      remote_user: root
      tasks:
        - name: centos6 touch
          file: name=/app/cnetos{{  ansible_distribution_major_version }} state=touch
          when: ansible_distribution_major_version == "6"
        - name: centos7 touch
          file: name=/app/centos{{  ansible_distribution_major_version }} state=touch
          when: ansible_distribution_major_version == "7"
          
    [root@centos6 app]# ansible-playbook when.yml
    
    PLAY [all] ************************************************************************
    
    TASK [Gathering Facts] ************************************************************
    ok: [192.168.39.140]
    ok: [192.168.39.129]
    ok: [192.168.39.139]
    
    TASK [centos6 touch] **************************************************************
    skipping: [192.168.39.129]
    skipping: [192.168.39.140]
    changed: [192.168.39.139]
    
    TASK [centos7 touch] **************************************************************
    skipping: [192.168.39.139]
    changed: [192.168.39.129]
    changed: [192.168.39.140]
    
    PLAY RECAP ************************************************************************
    192.168.39.129             : ok=2    changed=1    unreachable=0    failed=0   
    192.168.39.139             : ok=2    changed=1    unreachable=0    failed=0   
    192.168.39.140             : ok=2    changed=1    unreachable=0    failed=0   
    
    [root@centos6 app]# ansible all -a 'ls /app'
    192.168.39.139 | SUCCESS | rc=0 >>
    cnetos6
    
    192.168.39.129 | SUCCESS | rc=0 >>
    centos7
    
    192.168.39.140 | SUCCESS | rc=0 >>
    centos7
    

    with_items

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

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

    示例:

    - 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
    

    将多个文件进行copy到被控端

    - name: Create rsyncd config
      copy: src={{ item }} dest=/etc/{{ item }}
      with_items:
        - rsyncd.secrets
        - rsyncd.conf
    

    迭代嵌套子变量

    ---
    
    - hosts: appservers
      remote_user: root
      tasks:
        - name: add some groups
          group: name={{ item }} state=present
          with_items: 
            - group1
            - group2
            - group3
        - name: add some users
          user: name={{ item.name }} group={{ item.group }}
          with_items:
            - { name: 'user1', group: 'group1' }
            - { name: 'user2', group: 'group2' }
            - { name: 'user3', group: 'group3' }
    

    roles

    roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中

    目录

    结构如下:

    playbook.yml
    roles/
        project/
            tasks/
            files/
            vars/ 不常用
            default/ 不常用
            templates/
            handlers/
            meta/ 不常用
    

    各目录作用:

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

    示例:

    [root@centos7 .ansible]# tree
    .
    └── roles
        └── ajsalminen.hosts
            ├── defaults
            │   └── main.yml
            ├── meta
            │   └── main.yml
            ├── README.md
            ├── tasks
            │   ├── hostname.yml
            │   ├── hosts.yml
            │   └── main.yml
            ├── templates
            │   ├── hostname.j2
            │   └── hosts.j2
            └── vars
                └── FreeBSD.yml
    

    创建

    1. 创建以roles命名的目录
    2. 在roles目录中分别创建以各角色名称命名的目录,如webservers等
    3. 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建
    4. 在playbook文件中,调用各角色

    调用角色

    1. 直接调用

      ---
      - hosts: websrvs
        remote_user: root
        roles:
          - mysql
          - memcached
          - nginx
      
    2. 传递变量给角色

      ---
      - hosts: websrvs
        remote_user: root
        roles:
          - mysql
          - { role: nginx, username: nginx }
      

      键role用于指定角色名称,后续的k/v用于传递变量给角色

    3. 基于条件测试实现角色调用

      roles:
        - { role: nginx, username: nginx, when: ansible_distribution_major_version == '7' }
      

    相关文章

      网友评论

          本文标题:ansible

          本文链接:https://www.haomeiwen.com/subject/hxxpmftx.html