「Ansible」- Role and Galaxy

3.5 最佳使用方法

(1)鼓励文件的重用,尽量使用 include 和 role 避免重复的代码。
(2)尽量把大的文件分成小的文件。

官方例子:http://github.com/ansible/ansible-examples
分享平台「Ansible Galaxy」:这是用户分享的Playbook,使用前,请进行严格的测试。

#5 role & Ansible Galaxy

5.1 role 和 Ansible Galaxy 的简要介绍

role 是高级版本的 include 语句, include 用 来分享单个 Playbook 文件 , 而 role 可以分享一个文件夹 , 文件夹里面包含 task (任务)、handlers、 file (文件)、 template (模板)和 variable( 变量 )。

role文件夹里面包含了实现一个完整的功能所有文件 。例如 ,安装和配置 Web 服务器 Nginx、或者安装和配置数据库 MySQL 等。Ansible 中的 role 与编程语言中包(package)的概念类似。

Ansible Galaxy 是 Ansible 提供的分享 role 的 网站。

5.2 role 的放置位置

role 文件夹都可以放在哪里呢?

  • 当前子目录roles下(与Playbook同级)
  • 环境变量 ANSIBLE ROLES PATH 定义的文件夹,Ansible 也会搜索该文件夹下放置的 role。
  • Ansible 配置文件中 roles_path 定义的文件夹,roles_path=/opt/mysite/roles:/opt/othersite/roles。如果已经定义了环境变量ANSIBLE_ROLES_PATH ,那么配置变量 roles_path 定义的文件夹就会失效。有效的配置文件有:
    • file that ANSIBLE CONFIG (an environment variable) pointed to
    • ansible.cfg (in the current directory)
    • .ansible.cfg (in the home directory)
    • /etc/ansible/ans 工ble.cfg
  • 默认文件夹/etc/ansible/roles。既没有定义环境变量 ANSIBLE_ROLES_PATH ,也没有在配置文件中定义变量 roles_path

5.3 在 Playbook 中如何调用 role

通过关键字roles来调用role。Ansible会自动在Playbook同级的roles/下查找对应名字的role:

- hosts: all
  remote_user: root
  roles:
    - simple

目录的内容如下:

# 文件目录结构
./roles/
	simple/
		tasks/
			main.yml
			site.yml

roles的优先级高于tasks,但是可以通过 pre_tasks 和 post_tasks 调整 roles 和tasks的顺序:

---
- hosts: all
  remote_user: root

  pre_tasks:
    - shell: "echo pre tasks"
  roles:
    - simple
  tasks:
    - shell: "echo tasks"
  post_tasks:
    - shell: "echo post tasks"

调用带有参数的role:

---
- hosts: all
  remote_user: root
  roles:
    - {role: my_role, ex_param: "wth"}
    - role: demo
      vars:
        p0: "this is p1."
        p1: "this is p34."

与 when 一起使用 role:

---
- hosts: all
  remote_user: root

  roles:
    - {role: simple, when: "ansible_os_family" == "Debian"}
    - role: simple
      when: "ansible_os_family" == 'Debian'

5.4 如何写 role

什么是role?

  • role 就是更高级版本的 include 语句,include 语旬只能重用一个包含任务的 Playbook 文件,而 role 可以分享和重用一个包含多种文件的文件夹,其中,文件可以是任务、handler、静态文件、模板文件以及定义变量的文件等。
  • role 的实现机制并不复杂,只是自动的加载( include )一些文件,并提供一些自动搜索的文件路径。

通过遵循特定的文件夹的结构来定义role,我们定义了一个名字为 x 的 role:

  • 如果文件 role/x/taks/main.yml 存在,则文件中列出的任务都会被加入 Play 中 。
  • 如果文件 role/x/handlers/main.yml 存在 ,则 文件中列出的 handlers 都会被加入Play中。
  • 如果文件 role/x/vars/main.yml 存在,贝IJ文件中列出的变量都会被加入 Play 中 。
  • 如果文件 role/x/defaults/main.yml 存在 ,则文件中列出的变量都会被加入 Play 中。
  • 如果文件 role/x/meta/main.yml 存在,则文件中列出的所有依赖的 role 都会被加入 Play 中。
  • 此外,下面的文件不需要绝对或者是相对路径,和放在同一个目录下的文件一样,直接使用即可。
    1. copy 或者 script 使用 roles/x/files/下的文件
    2. template 使用 roles/x/templates 下的文件
    3. include 使用 roles/x/tasks 下的文件

一个包含完整文件结构的 role 如下面的图所示。这里面任何一个文件都不是必需的,如果文件不存在,则会跳过对该文件的加载。

roles/
	simple/
		defaults/
			main.yml
		files/
		handlers/
			main.yml
		meta/
			main.yml
		tasks/
			main.yml
		template/
		vars/
			main.yml

可是使用ansible-galaxy init role_name来初始化一个role的骨架。

默认变量和普通变量的区别:

  • defaults/main.yml 申的变量是默认变量。优先级在所有的变量中是最低的 , 用于放置一些需要被覆盖的变量。
  • vars/main.yml 中的变量是 role 变量,优先级比较高,变量在命名的时候一般都加入 role 的名字作为前缀,防止不小心被 Playbook 中定义的变量覆盖。

变量优先级:「Variable precedence: Where should I put a variable?

tasks/main.yml – 如何使用变量、静态文件和模板:

tasks是roles的核心,tasks/main.yml是role的入口文件,除了main.yml之外,还可以有其他的.yml文件,但是需要显式的使用。

  • 使用 x/*/main.yml中的变量和 handler,这与使用在同一个 Playbook 中的资源一样;
  • 使用 x/{files,templates}/下的文件,这使用同一个目录下的文件一样来使用放在这里的变量类似。但是,模块和使用的文件类型要匹配:copy、 script 对应 files 目录下的文件;template 对应 templates 目 录下的文件;
tasks/
	main.yml
templates/
	ntp.conf.j2
vars/
	main.yml

---
# vars/main.yml
ntp_pkgs:
  - libselinux-python
  - ntp

ntp_svc_name: ntpd

---
# x/*/main.yml

# 变量直接使用即可,不需要引用
- name: Install the required package in Redhat
  yum: name="{{ name }}" state=installed
  with_items: '{{ ntp_pkgs }}'
  when: ansible_os_family = 'RedHat'

# template也不需要使用路径,直接使用即可;但是copy模块不能复制ntp.conf.j2,因为它从files目录
# 查找文件。
- name: Copy the ntp.conf template file
  template: src=ntp.conf.j2 dest=/etc/ntp.conf

使用x/*/other_but_main.yml资源。如果x/下面的内容比较复杂,需要对tasks或者vars放入不同的文件进行分类,可以将他们放在不同的文件中,然后在main.yml中使用include和include_vars指令进行引用:

tasks/
	main.yml
	install.yml
	configure.yml
template/
	ntp.conf.j2
vars/
	Debian.yml
	main.yml
	RedHat.yml

---
# RedHat.yml
ntp_pkgs:
	- libselinux-python
	- ntp

ntp_svc_name: ntpd

---
# myrole/tasks/*/main.yml
- name: Add the OS specific variables
  include_vars: RedHat.yml
- name: Include the required packages in Redhat
  yum: name={{ item }} state=installed
  with_items: '{{ ntp_pkgs }}'
  when: ansible_os_family == 'RedHat'

- include: install.yml
- include: configure.yml

5.5 role 的依赖

在你的roles中,可能需要先执行其他的roles,所以要先执行其他roles。依赖关系定义在roles/x/meta/main.yml中 。

当多个 role 依赖同一个 role 时, Ansible 会自动进行过滤,避免重复调用相同参数的 role。在下面的例子中, role db 和 Web 都依赖 role common。如果在 Playbook 中调用 db 和 Web,那么 Ansible 会保证在 role db 和 web 运行前,先运行 role common ,并且只运行一次:

myroles/
	common/
		tasks/
			main.yml
	db/
		meta/
			main.yml
		tasks/
			main.yml
	web/
		meta/
			main.yml
		tasks/
			main.yml

---
# 在 {web,db}/meta/main.yml中
dependencies:
  - {role: common, some_param: "value"}

# 在site.yml 文件中
roles :
  # Role 的 depency 相 当于隐形地加入了 common
  - common
  - db
  - web

5.6 Ansible Galaxy 网站介绍

一个分享role的官方平台。

使用 ansible-galaxy install username.rolename 的形式进行安装。通常在role的页面中提示了安装方法。

使用-p选项可以指定安装目录:ansible-galaxy install -p ./roles geerlingguy.docker

如果要一次安装多个role:ansible-galaxy install -r roles.txt。其中roles.txt的内容如下:

userl.rolel,vl.0.0

user2.role2,v0.5

user2.role3

如果不满足于只从 Ansible Galaxy 中下载 , 那么还可以在 YAML 文件中,使用 src、 name等参数来实现从其他网站中下载 role:

ansible –galaxy install -r requirements.yml

其中,requirements.yml的内容如下:

# from galaxy
- src: yatesr.timezone

# from GitHub
- src: https://github.com/bennojoy/nginx

# from Github
- src: https://github.com/bennojoy/nginx
  version: master
  name: nginx_role

# from ...
- src: https://some.webserver.com/file/master.tar.gz
  name: http-role

分享一个 role 可分为非常简单的三步,具体如下。

  • 在你的 Github 账户下,为你需要分享的 role 单独创建一个GitHub项目。
  • 用 Github 账户登录 Ansbile Galaxy。
  • 在MY ROLES 菜单下,单击”refresh“, GALAXY 就会搜索你 Github 账户下所有的项目,并且将符合 role 目录结构的所有项目列出来。在列表中,有开启/关闭分享 role 菜单的功能 ,根据你的需要,开启 role 的分享就可以了。

5.6 演示 role 的创建和分享

略过。。。还是那个目录结构,按照那个结构写就可以了。最后按照上面的那个进行分享就可以了。