Ansible 角色

Mar 20, 2019 23:00 · 1488 words · 3 minute read Ansible DevOps

到底什么是 Ansible 角色,看了很多这方面的文档,但觉得都说的不够清楚。

有时候我们会写出一些步骤繁琐的 Ansible 剧本(playbook),这当然是极好的,再也不需要自己手动一行一行输入命令来部署多台服务器了。但是剧本不一定适用于所有情况,如果要对剧本做一些调整(增加步骤、删减步骤、调换执行顺序等),也很费时间。这时候,我们可以将整个剧本拆成一个一个小片段(任务),将这些任务自由组合,灵活地实现想要的剧本。

https://github.com/ansible/ansible-examples

看一下 Ansible 官方的例子:

$ cd wordpress-nginx
$ tree -L 2
.
├── LICENSE.md
├── README.md
├── group_vars
│   └── all
├── hosts.example
├── roles
│   ├── common
│   ├── mysql
│   ├── nginx
│   ├── php-fpm
│   └── wordpress
└── site.yml

进入 wordpress-nginx 路径,这是一个部署 wordpress 的项目。

首先看一下角色的结构,roles 路径下有 common、mysql、nginx、php-fpm、wordpress 五个不同名称的目录,很明确,每个组件都可以成为一个角色。

接着彻底展开 roles 路径:

$ tree roles
roles
├── common
│   ├── files
│   │   ├── RPM-GPG-KEY-EPEL-6
│   │   ├── epel.repo
│   │   └── iptables-save
│   ├── handlers
│   │   └── main.yml
│   └── tasks
│       └── main.yml
├── mysql
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   └── templates
│       └── my.cnf.j2
├── nginx
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   └── templates
│       └── default.conf
├── php-fpm
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   └── templates
│       └── wordpress.conf
└── wordpress
    ├── tasks
    │   └── main.yml
    └── templates
        └── wp-config.php

每个角色都包含了 tasks、handlers、templates、files 这样的目录。

  • files 必要的文件
  • tasks 任务集
  • vars 这个角色所使用的变量
  • templates 模版集
  • handlers 和 notify 结合使用,由特定条件触发

任务

看一下 mysql 角色的任务集:

$ cat roles/mysql/tasks/main.yml
---
- name: Install Mysql package
  yum: name={{ item }} state=present
  with_items:
   - mysql-server
   - MySQL-python
   - libselinux-python
   - libsemanage-python

- name: Configure SELinux to start mysql on any port
  seboolean: name=mysql_connect_any state=true persistent=yes
  when: ansible_selinux.status == "enabled"

- name: Create Mysql configuration file
  template: src=my.cnf.j2 dest=/etc/my.cnf
  notify:
  - restart mysql

- name: Start Mysql Service
  service: name=mysqld state=started enabled=yes

这就是熟悉的 Ansible 模块命令集合。这个任务执行了:

  1. 安装 MySQL 包
  2. 修改某个配置
  3. 通过模板生成 MySQL 配置文件
  4. 启动 MySQL 服务

可以看到这并不是一个完整的剧本,但是 MySQL 数据库相关的任务都在这。如果之前已经配置好了数据库,那就不需要执行这个任务了。

handlers

注意到 roles/mysql/tasks/main.yml 中第三个任务带上了 notify 这个键,表示如果执行成功的话就会执行名称为 restart mysql 的任务。

想都不用想,这个任务在 roles/mysql/handlers 路径中:

$ cat roles/mysql/handlers/main.yml
---
- name: restart mysql
  service: name=mysqld state=restarted

其他角色的任务集根据名称就可以进行猜想:

  • nginx 部署、配置并启动 Nginx
  • php-fpm 部署、配置并启动 PHP
  • wordpress 下载并部署 WordPress

剧本

所有的片段,都被整合进了 ./site.yml 这个剧本中。

$ cat ./site.yml
---
- name: Install WordPress, MySQL, Nginx, and PHP-FPM
  hosts: all
  remote_user: root
  # remote_user: user
  # become: yes
  # become_method: sudo

  roles:
    - common
    - mysql
    - nginx
    - php-fpm
    - wordpress

这个剧本为角色 x 指定了如下行为:

  • 如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 将被添加到 play 中
  • 如果 roles/x/handlers/main.yml 存在, 其中列出的 handlers 将被添加到 play 中
  • 如果 roles/x/vars/main.yml 存在, 其中列出的 variables 将被添加到 play 中
  • 所有 copy tasks 可以引用 roles/x/files/ 中的文件,不需要指明文件的路径
  • 所有 template tasks 可以引用 roles/x/templates/ 中的文件,不需要指明文件的路径
  • 所有 include tasks 可以引用 roles/x/tasks/ 中的文件,不需要指明文件的路径

这样我们可以自由地调整剧本中片段是否执行和执行顺序。

变量

这个例子中,所有的角色都共用一份变量:

$ cat group_vars/all
---
# Which version of WordPress to deploy
wp_version: 4.2.4
wp_sha256sum: 42ca594afc709cbef8528a6096f5a1efe96dcf3164e7ce321e87d57ae015cc82

# These are the WordPress database settings
wp_db_name: wordpress
wp_db_user: wordpress
wp_db_password: secret

# You shouldn't need to change this.
mysql_port: 3306

# This is used for the nginx server configuration, but access to the
# WordPress site is not restricted by a named host.
server_hostname: www.example.com

# Disable All Updates
# By default automatic updates are enabled, set this value to true to disable all automatic updates
auto_up_disable: false

#Define Core Update Level
#true  = Development, minor, and major updates are all enabled
#false = Development, minor, and major updates are all disabled
#minor = Minor updates are enabled, development, and major updates are disabled
core_update_level: true

在任务集或者模板中的变量({{ var_name }})会在剧本执行时被替换掉。

Ansible 中变量可能存在于各种路径中,多而灵活,可能会发生意想不到的变量覆盖情况,要特别留心变量的优先级!!!

优先级从低到高:

  • command line values (eg “-u user”)
  • role defaults
  • inventory file or script group vars
  • inventory group_vars/all
  • playbook group_vars/all
  • inventory group_vars/*
  • playbook group_vars/*
  • inventory file or script host vars
  • inventory host_vars/*
  • playbook host_vars/*
  • host facts / cached set_facts
  • play vars
  • play vars_prompt
  • play vars_files
  • role vars (defined in role/vars/main.yml)
  • block vars (only for tasks in block)
  • task vars (only for the task)
  • include_vars
  • set_facts / registered vars
  • role (and include_role) params
  • include params
  • extra vars (always win precedence)