7 minute read

intro

什么是 ansible

ansible 是一套完整的系统配置管理工具, 丰富的功能组件, 使运维或者开发人员非常方便的管理线上环境.

ansible 能干什么

在我的工作中, ansible 对我比较重要, 因为需要维护40-70台(好吧, 最多的时候240台)弹性服务器, 需要批量执行代码更新, 清除数据文件, 查看日志文件等工作, 而使用 ansible 可以让工作更轻松.

为什么选择 ansible

其实关注 ansible 很长时间了, 一直没有什么机会使用, 因为之前需要维护的也就那么一两台服务器, 完全没有使用 CM 必要, 但是, 当我发现每日服务器的管理工作需要占用我20分钟以上的时候, 我觉得是使用管理工具的时候了.

其实可以选择的工具非常多, 老牌的 puppet, chef. 同期的 saltstack 等等. 最后选择 ansible 的原因是不需要安装 agent, 通过 ssh 管理更方便一些.

当然, 星多.

入门

文档

官方文档很翔实, 但是碎片化, 我不喜欢, 看书的话我觉得没太大的必要, 毕竟我就简单用用, 不干什么惊天地泣鬼神的事, 所以我觉得看看别人的代码效果更好一些.

最佳实践

ansibleplaybook 作为最主要的工具, 如何组织是一个不小的挑战, 不过官方的最佳实践说明我觉得很够用了, 参考下github上别的大牛写的 playbook 也是很好的.

.
├── anonymous.yml
├── ansible.cfg
├── authorized
│   ├── id_rsa
│   └── id_rsa.pub
├── authorized.yml
├── deploys.yml
├── hosts
├── maintain.yml
├── proxy.yml
├── readerImage.yml
├── readme.md
└── roles
    ├── anonymize-proxy
    │   ├── configures
    │   │   ├── passwords
    │   │   └── squid.conf
    │   ├── handlers
    │   │   └── main.yml
    │   └── tasks
    │       └── main.yml
    ├── authorized
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    │       └── sshd_config.j2
    ├── code
    │   ├── keys
    │   │   ├── id_rsa
    │   │   └── id_rsa.pub
    │   └── tasks
    │       └── main.yml
    ├── cron
    │   └── tasks
    │       └── main.yml
    ├── maintain
    │   └── tasks
    │       └── main.yml
    ├── post-image
    │   └── tasks
    │       └── main.yml
    ├── proxy
    │   ├── configures
    │   │   └── nginx.conf
    │   ├── handlers
    │   │   └── main.yml
    │   └── tasks
    │       └── main.yml
    ├── runtime
    │   └── tasks
    │       └── main.yml
    └── services
        ├── configures
        │   ├── service1.service
        │   ├── service2.service
        │   ├── service3.service
        │   └── service4.service
        └── tasks
            └── main.yml

这是是我整个 ansible-playbook 的目录结构, 大体分成了9个role, 6个 playbook.

在一个 playbook 中可以调用多个 role, 这样就组成了自动化配置的基础, 每个 role 只负责干好自己所定义的任务, 而 playbook 负责组合所需的模块.

inventory

inventory 的作用就是定义你需要维护的服务器, 格式也非常简单, 如下:

[readers]

[builds]

[proxies]
proxybase ansible_host=192.168.0.4

[anonymous]
anonymbase ansible_host=192.168.0.5

[removes]


[maintains]

service01 ansible_host=192.168.0.1
service02 ansible_host=192.168.0.2
service03 ansible_host=192.168.0.3
...

其中, [] 定义分组, 你可以根据自己的实际需要, 将服务器分成不同的组, 再在 playbook 中调用不同的分组, 同时, 在使用命令行查询所有服务器的日志的时候, 也会更加便捷.

service01 相当于给服务器起的别名, 可以使管理更加便捷.

inventory 默认的位置是 /etc/ansible/hosts, 这样有点麻烦, 我们可以调整 ansible.cfg, 来指定 hosts 文件.

ansible.cfg

ansible 2.0 配置文件依据以下的顺序检索:

* ANSIBLE_CONFIG (an environment variable)
* ansible.cfg (in the current directory)
* .ansible.cfg (in the home directory)
* /etc/ansible/ansible.cfg

可以根据个人的使用习惯设置 cfg 的路径, 我属于轻度用户, 只有这么一个项目依赖 ansbile, 所以的把 ansible.cfg 放在了项目中, 纳入版本控制, 我觉得这样也挺方便的, 便于分享代码.

我的配置文件非常简单, 如下:

[defaults]
hostfile=./hosts
transport=ssh
host_key_checking=false

[ssh_connection]
ssh_args=-o ForwardAgent=yes

其中, hostfile 设置 hosts 文件的位置 因为使用阿里云的弹性服务器, 有的服务器释放后再次申请的时候, 会分配已经使用过的服务器, 这样, 关闭 host_key_checking 可以避免服务器指纹不一致的问题

而我使用 ssh-agent 连接服务器, 所以额外配置了 ssh_args=-o ForwardAgent=yes.

而一般情况下, 我理解除了指定下 hosts 的位置以外, 基本不用设置.

ansible 的配置项蛮多的, 可以通过 Configuration file 查找更多的配置选项.

modules

ansible 提供了大量的原生模块, 当然, 还有大量的社区维护的模块, 基本可以满足使用的需求. 当然, 对我来说绰绰有余.

在我的项目中, 服务器环境是 centos 7.1, 主要使用的模块有 yum, systemd, git, copy, cron等.

ansible 提供了详尽的模块指南, 只需要理解其中的概念基本都可以很快上手.

这里我以简单的 proxy 为例,

proxy 这个 role 实质上是一个 Nginx forward proxy 服务, 从之前的 tree 可以看到包含以下文件:

nginx.conf

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
  worker_connections  2048;
  multi_accept on;
  use epoll;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/proxy.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    server {
        listen       8080;

        location / {
            resolver 8.8.8.8;
            proxy_pass http://$http_host$uri$is_args$args;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;
}

handlers/main.yml

---
- name: restart nginx
  service:
    name: nginx
    state: restarted

tasks/main.yml

---
- name: install nginx
  yum:
    name: nginx
    state: present
    update_cache: yes
  tags: setup

- name: copy nginx configure file
  copy:
    src: ../configures/nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: 0644
  notify:
    - restart nginx

- name: enable nginx services
  systemd:
    name: nginx
    enabled: yes
    state: started

其中, tasks/main.ymlrole 的主文件, 其中首先使用 yum 模块, 安装 Nginx, 接着, 复制配置文件至 /etc 下, 同时, 触发 handers/main.yml 中的任务, 重启 Nginx, 最后, 配置 systemd, 使其跟随开机自动启动服务.

这样就免除了手工配置服务器的过程, 当然, 现在云供应商提供镜像功能, 只需要手工配置一次, 就可以批量复制出大量的服务器, 但是, ansible 可以让你的工作变的更有序, 更便于管理, 何乐不为呢?

playbook

playbook 相当于把一系列的 role 组合成一个任务, 这样, 可以编写细粒度的 role, 通过 playbook 把一系列的任务组合起来, 使代码更加灵活.

我所编写的 playbook 如下所示:

---
# this playbook deploys the runner applications on the [builds] hosts

- name: runtime env deploy
  hosts: builds
  remote_user: root

  roles:
    - runtime
    - code
    - services

hosts 指明所需要构建的服务器组, remote_user 指明执行指令的用户, roles 显而易见的就是所要执行的 role, ansible playbook 会按照指定的执行顺序依次执行 role.

后记

我也只是一个 ansible 的初级使用者, 只是在工作中倒逼, 不得不使用 ansible. roleplaybook 都写的很仓促, 只是为了满足当时的工作(不得不说, ansiblesystemd 对我日常维护服务器带来了极大的便利), 以上的内容只是粗陋的描述了我简陋的使用流程.

当然, 其中缺失了 ssh-agent, systemd 等内容, 等我整理完成, 可能会写一点吧…

ref

  1. ansible official docs
  2. jlund/streisand(playbook example)

Updated: