Ansible实践
2015 年 12 月 01 日
devops

    相信大家对运维这个词都比较熟悉,何为运维? 运维就是保障服务器资源安全,稳定,合理。 但是安全稳定不易,合理更难。在达到该目标之前, 运维人员会运用各种工具来方便自己管理服务器资源,最简单基础的就是Shell,在Shell中定义好自己的各种功能,需要时执行即可, 但面对大型的运维环境,光靠Shell是有些力不从心的,还需要一些更强大方便的工具, 如常用的脚本语言RubyPython等,当然还有些专门为运维人员准备的工具, 如FabricSaltStackAnsible等,本文将对Ansible进行探讨。

  • 什么是Ansible

  • Ansible是一个基于SSH的自动化运维工具, 使用python编写。由于基于SSH, 因此不需要在远程主机上安装额外的软件。

  • 安装Ansible

  • 安装Ansible之前,需安装 Python2.6或2.7, 并支持各种安装。 如在Centos上,可以直接使用yum安装:

    yum install ansible
        
  • First Ansible

  • 安装好后,可初试一下ansible使用:

    ansible -i hosts haolin-apps -m ping
    haolin-apps | success >> {
        "changed": false,
        "ping": "pong"
    }    
        

    -i hosts指定了主机配置文件, haolin-apps则为其中的一个主机或主机组, -m ping表示执行ping模块。

  • 配置文件

  • Ansible启动时,会加载默认配置,会尝试加载以下文件:
  • * ANSIBLE_CONFIG (环境变量)    
    * ansible.cfg (当前目录)
    * .ansible.cfg (用户主目录)
    * /etc/ansible/ansible.cfg    
        
  • Ansible 1.5之前加载顺序稍有不同:
  • * ansible.cfg (当前目录)    
    * ANSIBLE_CONFIG (环境变量)    
    * .ansible.cfg (用户主目录)
    * /etc/ansible/ansible.cfg    
        
  • Inventory(清单)

  • Ansible执行任务前,需要先加载Inventory信息, 默认文件为/etc/ansible/hosts, 可通过-i参数指定,格式大概如下:

    test
    
    [api]
    api01
    api02
    
    [db]
    db01
    db02
    
    [all:children]
    api
    db
    ..
        

    test定义了一个主机, api定义了一个主机组, 包含主机api01api02 all定义了一个父主机组, 其包含了子主机组apidb

  • 变量

  • 主机和主机组均支持定义额外的变量,如

    # 主机变量    
    [atlanta]
    host1 http_port=80 maxRequestsPerChild=808
    host2 http_port=303 maxRequestsPerChild=909
    
    # 主机组变量
    [atlanta:vars]
    ntp_server=ntp.atlanta.example.com
    proxy=proxy.atlanta.example.com
        
  • 多文件存储Inventory

  • 当主机信息变得越来越多时,单个文件就比较难以维护,而应该采用多个文件来存储, 建议可以在Ansible配置文件中添加inventory目录:

    [defaults]
    # ansible 1.9 之前叫hostfile
    inventory = /path/to/inventory
        

    这样Ansible会合并/path/to/inventory目录下的主机文件。

  • Playbooks(剧本)

  • 上面使用命令行方式(Ad-Hoc)运行了Ansible任务, 但实际中这样做是很少的,往往任务不会只有一个,而常会执行多个任务,于是需要一种描述语言来描述一些列任务的执行, 这就是PlaybookPlaybook使用YAML文件格式编写,如:

    ---
    - hosts: webservers     # 主机列表
      vars:                 # 变量
        http_port: 80
        max_clients: 200
      remote_user: root     # ssh用户
      tasks:                # 任务列表
      - name: ensure apache is at the latest version
        yum: name=httpd state=latest
      - name: write the apache config file
        template: src=/srv/httpd.j2 dest=/etc/httpd.conf
        notify:
        - restart apache
      - name: ensure apache is running (and enable it at boot)
        service: name=httpd state=started enabled=yes
      handlers:             # 通知处理器
        - name: restart apache
          service: name=httpd state=restarted
        

    Playbook主要由几部分组成: hosts(任务执行的目标主机), vars(任务执行上下文的变量信息), tasks(任务执行列表)和handlers(任务执行完成的通知处理器)。 上面的Playbook 将以root用户在webservers服务器上执行一些列任务: yum安装最新apache包配置httpd重启apache开机自启动apache

  • 执行Playbook

  • 可以通过ansible-playbook执行编写好的Playbook:

    ansible-playbook -i [inventory] my_playbook.yml
        
  • Modules(模块)

  • Ansible提供了很多可用的模块, 这些模块可以直接在远程主机上执行,如上面的Playbook使用到了 yumtemplateservice模块。

  • Roles(角色)

  • 当编写的Playbook越来越多,则需要一种更好的方式来组织这些Playbook,这时就需要RolesRoles规范出了Playbook的一些通用目录,在运行Playbook时,会自动加载这些目录中的信息,目录列表大致如:

    site.yml
    webservers.yml
    fooservers.yml
    roles/
       common/
         files/
         templates/
         tasks/
         handlers/
         vars/
         defaults/
         meta/
       webservers/
         files/
         templates/
         tasks/
         handlers/
         vars/
         defaults/
         meta/
        

    上面目录中,包含两个角色commonwebservers, 每个角色包含一些可选的目录,在Playbook中可以调用角色:

    ---
    - hosts: webservers
      roles:
         - common
         - webservers
        

    Playbook执行中,会使用对应角色目录下的文件, tasks/main.yml存放任务列表, handlers/main.yml存放处理器列表, vars/main.yml存放变量, defaults/main.yml存放默认变量(优先级最低), meta/main.yml存放角色依赖关系, files/存放文件复制操作中使用到的文件(此时可以仅指定文件名,而不需要绝对路径), templates/存放template模块操作的模板文件。

  • 角色参数化

  • 调用角色时,可以传递一些额外参数,如:

    - hosts: webservers
      roles:
        - common
        - { role: role_one, dir: '/opt/a',  port: 5000 }            # 定义变量dir,port
        - { role: role_two, when: "ansible_os_family == 'RedHat'" } # 增加条件限制
        
  • 角色依赖

  • 可以在meta/main.yml中定义角色依赖关系,如:

    ---
    dependencies:
      - { role: common, some_parameter: 3 }
      - { role: apache, port: 80 }
      - { role: postgres, dbname: blarg, other_parameter: 12 }
        

    使用Role组织脚本是官方强烈推荐的, 实际中,应尽量做到Role细粒度化, 需要执行某些任务时,则将这些Role进行自由组合来达到目的, 以实现复用

  • 第三方Role

  • Ansible提供了一个第三方Role平台Ansible Galaxy,可以通过ansible-galaxy安装使用。

  • Ansible最佳实践

  • Ansible提供了一个较详细的 最佳实践,可结合实际情况作一些斟酌,这里有一些样例代码

好人,一生平安。