Ansible简介与实验

 

1、简介

ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优势,实现了批量系统配置、批量程序部署、批量运行命令等功能。linux

ansible是基于模块工做的,自己没有批量部署的能力。真正具备批量部署的是ansible所运行的模块,ansible只是提供一种框架。shell

主要特色:
  • 模块化,调用特定的模块,完成特定的任务,基于Python语言实现,易于扩展;编程

  • 部署简单,agentless,无需客户端安装软件,服务端经过链接插件connection plugins和被监控端实现通讯;bash

  • playbook:可让节点调用角色模板一次性运行多个任务快速部署基础环境。架构

  • ansible所执行的操做主要是定义管理者所指望的对象状态,屡次执行命令的结果具备幂等性框架

    幂等性本来是数学上的概念,即便公式:f(x)=f(f(x)) 可以成立的数学性质。用在编程领域,则意为对同一个系统,使用一样的条件,一次请求和重复的屡次请求对系统资源的影响是一致的less

ansible架构图

2、经常使用模块介绍

ansible-doc  命令用于获取ansible相关帮助页面,-l是查看可用模块,-s可显示指定模块说明。运维

ansible的命令行执行格式以下:ssh

ansible <host-pattern>  [-f forks] (host分批)   -m module_name  -a args 模块化

  • command:执行命令无须为key=value格式,而是直接给出要执行的命令便可。

    注意,command为默认调用模块能够不使用-m指定。

    • 示例1:

      [root@ansible-manager ~]# ansible directors -a "ifconfig"192.168.7.151 | SUCCESS | rc=0 >>ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 192.168.7.151  netmask 255.255.255.0  broadcast 192.168.7.255       .........

    • 示例2:chdir选项可指定命令运行的目录

      [root@ansible-manager ~]# ansible directors  -a "chdir=/var ls"192.168.7.151 | SUCCESS | rc=0 >>

      ..........

    • 示例3:command模块并不能理解执行  花括号命令行展开,管道符传递等特殊命令形式

      [root@ansible-manager ~]# ansible directors -a "ifconfig |grep ens33"192.168.7.152 | FAILED | rc=255 >>SIOCSIFADDR: No such device

      ..........

    • 示例4: 上例的问题可用shell模块解决

      [root@ansible-manager ~]# ansible directors -m shell -a "ifconfig |grep ens33" 192.168.7.151 | SUCCESS | rc=0 >>ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500

      .........

  • user      -a 'name= state={present|absent} system= uid='

    • 示例:

      [root@ansible-manager ~]# ansible directors -m user -a "name=wind state=present password=abc321"192.168.7.152 | SUCCESS => {    "changed": true,     "comment": "", #用户的描述信息    "createhome": true,     "group": 1000,     "home": "/home/wind",     "name": "wind",     "password": "NOT_LOGGING_PASSWORD",     "shell": "/bin/bash",     "state": "present",     "system": false, #非系统用户    "uid": 1000}

      到客户机上验证结果:

      [root@client2 ~]# id winduid=1000(wind) gid=1000(wind) groups=1000(wind)

  • cron         -a 'name= minute= hour= day= month= weekday= job= user= state='

    • 示例:

      [root@ansible-manager ~]# ansible all -m cron -a "name=ntptime minute=*/3 job='/usr/sbin/ntpdate 192.168.7.138 &>/dev/null '"192.168.7.152 | SUCCESS => {    "changed": true,     "envs": [],     "jobs": [        "ntptime"    ]}

      注意:

      1. 默认的state就是present,删除的时候能够仅指定name和state=absent.

      2. job='character string'  job的内容必须加单引号,不然报错.

      3. 任务计划可否成功建立并不受客户机是否有相关命令影响,没有安装ntpdate命令也能够成功建立.

  • copy    -a 'dest= src= mode= owner= group='

    • 示例: src参数不带绝对路径的话默认是复制当前目录下的指定文件,支持相对路径。

      • [root@ansible-manager ~]# ansible directors -m copy -a "src=repo.tar dest=/root"

        192.168.7.151 | SUCCESS => {

      • [root@ansible-manager ~]# ansible directors -m copy -a "src=../home/wind/1.txt dest=/root/2.txt"192.168.7.151 | SUCCESS => {

    • 注意:若是src以“/”结尾则仅复制目录中的内容,不以此结尾就是复制目录及其中内容src不是必选项由于能够用content直接生成目标文件的内容(可生成空文件)。

  • yum   -a 'name= state={present|latest|absent}'

    • 示例:

      ansible directors -m yum -a "name=ntpdate"

      192.168.7.151 | SUCCESS => {

      ​    "changed": true,

  • fetch   从远程主机取回文件到本地,

    • 示例:

      [root@ansible-manager ~]# ansible 192.168.7.151 -m fetch -a "src=/root/2.txt dest=remotefile"

      命令运行后在本地直接生成了remotefile目录,并且将远程主机上的绝对路径也复制到了本地指定目录的远程主机名目录之下。即./remotefile/REMOTE_HOST/REMOTE_PATH

    • 若是不须要此种多级目录结构,可以使用flat选项,其帮助文件说明以下:

      flat:    #   If dest ends with '/', it will use the basename of the source file, similar to the copy module. Obviously this is only handy if the filenames are unique.

      • ansible 192.168.7.152  -m fetch -a "src=/root/2.txt src=/root/3.txt flat=yes dest=test/" 

        [root@ansible-manager ~]# ls test/2.txt  3.txt

      使用此选项并不会生成多级目录,可是显然这个选项不适合从多主机上拉取文件的状况。

      会形成多主机重复写入同一文件。

      若是在多个远程主机的拉取文件时使用了flat选项,执行命令后,则会轮流覆盖写入拉回本地的文件,执行结果多个主机依次变为黄色changed。

      缘由是,依照hosts文件中定义的主机上下顺序,依次对比远程主机文件与ansiblemanager本地文件的校验值,若是发生改变则覆盖,执行结果黄色;校验值同的主机显示为绿色状态未变动。

      此种执行方式仅为兴趣探究,实际中并没有意义,从多个主机取回文件必然是不但愿互相覆盖的。

    • 注意:

      • src必须指向远程主机上的文件,不能够是目录。能够指定多个src

      • 使用flat=yes选项时,适合拉取单台主机文件的状况,下降目录复杂性。

  • file   -a 'path= mode= owner= group= state={directory|link|present|absent} src='

    • 示例:

      [root@ansible-manager ~]# ansible directors -m file -a "path=/root/a.txt src=/root/2.txt state=link"192.168.7.152 | SUCCESS => {    "changed": true,     "dest": "/root/a.txt",     "gid": 0,     "group": "root",     "mode": "0777",     "owner": "root",     "size": 11,     "src": "/root/2.txt",     "state": "link",     "uid": 0}

    • state选项说明:

      If 'directory', all immediate subdirectories will be created if they do not exist, since 1.7 they will be created with the supplied permissions.

      ​ If 'file', the file will NOT be created if it does not exist, see the [copy] or [template] module if you want that behavior.

      If 'link', the symbolic link will be created or changed. Use 'hard' for hardlinks.

      If 'absent', directories will be recursively deleted, and files or symlinks will be unlinked. Note that 'absent' will not cause 'file' to fail if the 'path' does not exist as the state did not change.

      If 'touch' (new in 1.4), an empty file will be created if the 'path' does not exist, while an existing file or directory will receive updated file access and modification times (similar to the way 'touch' works from the command line).

      • 若是是directionary,1.7版本后,  path指定的目录都将依据提供的权限设置递归建立。

      • 若是是file,path指定的文件若是原来不存在, 那么也不会被建立。若是须要新建一个文件请使用copy或template模块,或者使用touch参数(建立空文件)。

      • 若是是link,符号连接将被建立或更改。使用hard选项建立 hardlinks(也就是说默认软链接)。

      • 若是是absent, 目录将被递归地删除, 文件或符号连接将被取消连接。请注意, path不存在时不会致使file执行失败,由于命令会返回状态未改变的结果。

      • 若是是touch, (1.4新增参数), 若是path不存在, 则会建立一个空文件, 而若是path是现有或目录时将更新文件access和modifycation时间 (相似命令行下执行touch命令)。

  • ping   没有参数,仅测试是否能够ping通

    • 示例:

      [root@ansible-manager ~]# ansible directors -m ping 192.168.7.151 | SUCCESS => {    "changed": false,     "ping": "pong"}192.168.7.152 | UNREACHABLE! => {    "changed": false,     "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.7.152 port 22: Connection timed out\r\n",     "unreachable": true}

  • service    -a 'name= state={started|stopped|restarted} enabled='

    • 示例:

      [root@ansible-manager ~]# ansible directors -m service -a "name=httpd state=restarted"192.168.7.151 | SUCCESS => {

      .......会显示很长的详细状态信息

3、playbook

Playbooks 是 Ansible的配置,部署,编排语言。是一种但愿远程主机执行所需命令的方案,或者一组IT程序运行的命令集合.

(一)Playbook的核心元素:
  • tasks: 任务       

    任务列表

  • variables: 变量 

    ansible有内置变量与自定义变量,变量定义能够在命令行,主机清单,角色目录下的变量目录等多处进行。      

  • templates: 模板

    主要用于服务的配置文件的参数传递至被控主机       

  • handlers: 触发调用任务 

    适用于如配置文件变动时触发重启/重载等任务。须要tasks任务列表中使用notify调用。     

  • roles: 角色

    经过对以上元素的整合,达成一整套的服务自动配置的目的。有固定的目录组织形式,各元素分别定义。在playbook中经过对host安排角色进行调用。

具体的每一个元素再也不详述,能够参考ansible中文手册,下面以实例来演示。

(二)使用roles部署keepalived一主一备实例
  1. 建立目录

    [root@ansible-manager ansible]# mkdir -p roles/keepalived/{tasks,handlers,meta,templates,vars,files}

    [root@ansible-manager ansible]# tree roles/

    roles/

    └── keepalived 

      ├── files

      ├── handlers

      ├── meta

      ├── tasks

      ├── templates

      └── vars

    7 directories, 0 files

    tasks⽬录:存放task列表。若role要⽣效,此⽬录必需要有⼀个主task⽂件main.yml,在main.yml中可使⽤include包含同⽬录(即tasks)中的其余⽂件。handlers⽬录:存放handlers的⽬录,若要⽣效,则⽂件必须名为main.yml⽂件。files⽬录:在task中执⾏copy或script模块时,若是使⽤的是相对路径,则会到此⽬录中寻找对应的⽂件。templates⽬录:在task中执⾏template模块时,若是使⽤的是相对路径,则会到此⽬录中寻找对应的模块⽂件。vars⽬录:定义专属于该role的变量,若是要有var⽂件,则必须为main.yml⽂件。defaults⽬录:定义⾓⾊默认变量,⾓⾊默认变量的优先级最低,会被任意其余层次的同名变量覆盖。若是要有var⽂件,则必须为main.yml⽂件。meta⽬录:⽤于定义⾓⾊依赖(dependencies),若是要有⾓⾊依赖关系,则⽂件必须为main.yml。

    以上引自博客园——骏马金龙的ansible教程。

  2. 各目录具体配置

    • tasks

      • main.yml

        - name: yum install keepalived
        yum: name=keepalived state=present
        when: ansible_distribution_major_version == '7' #无实际意义的条件判断仅测试下when语句
        - name: copy script
        copy: src=notify.sh dest=/etc/keepalived
        - name: copy conf
        template: src=keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf
        notify: restart keepalived
        - name: start keepalived
        systemd: name=keepalived state=started
        - name: show vip
        shell: /usr/sbin/ip addr show |grep {{ vip }}
    • handlers

      • main.yml

        - name: restart keepalived
        systemd: name=keepalived state=restarted
    • templates

      • keepalived.conf.j2

        ! Configuration File for keepalived

        global_defs {
          notification_email {
              root@localhost
          }
          notification_email_from keepalived@localhost
          smtp_server 127.0.0.1
          smtp_connect_timeout 30
          router_id {{ ansible_hostname }} #引用内置变量
          vrrp_mcast_group1 224.0.0.33
          vrrp_skip_check_adv_addr
          vrrp_strict
          vrrp_garp_interval 0
          vrrp_gna_interval 0
        }

        vrrp_instance vip1 {
          state {{ keepalived_state }} #主机清单定义变量
          interface {{ ansible_default_ipv4.interface }}  #引用内置变量的子参数需以VAR.XX的形式
          virtual_router_id 51
          priority {{ pri }} #主机清单定义变量
          advert_int 1
          authentication {
              auth_type PASS
              auth_pass 1111
          }
            virtual_ipaddress {
                              {{ vip }} #自定义变量
                          }
                          notify_master "/etc/keepalived/notify.sh master"
                          notify_backup "/etc/keepalived/notify.sh backup"
                          notify_fault "/etc/keepalived/notify.sh fault"
        }
    • files

      • notify.sh

        #!/bin/bash
           #仅通知本机root用户作测试
           contact='root@localhost'

          notify() {
              local mailsubject="$(hostname) to be $1, vip floating"
              local mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
               echo "$mailbody" | mail -s "$mailsubject" $contact
          }

          case $1 in
          master)
              notify master
              ;;
          backup)
              notify backup
              ;;
          fault)
              notify fault
              ;;
          *)
               echo "Usage: $(basename $0) {master|backup|fault}"
               exit 1
              ;;
           esac
    • vars

      • main.yml

        vip: 192.168.7.120 #必须是字典形式
    • roles所在目录定义hosts以及playbook

      • hosts

        [directors]
        192.168.7.151 keepalived_state=MASTER pri=99
        192.168.7.152 keepalived_state=SLAVE pri=90
      • keepalived.yml

        - hosts: directors
        roles:
           - keepalived
相关文章
相关标签/搜索