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 中。
- 此外,下面的文件不需要绝对或者是相对路径,和放在同一个目录下的文件一样,直接使用即可。
- copy 或者 script 使用 roles/x/files/下的文件
- template 使用 roles/x/templates 下的文件
- 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 – 如何使用变量、静态文件和模板:
- 使用 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的内容如下:
user2.role2,v0.5
user2.role3
如果不满足于只从 Ansible Galaxy 中下载 , 那么还可以在 YAML 文件中,使用 src、 name等参数来实现从其他网站中下载 role:
其中,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 的创建和分享
略过。。。还是那个目录结构,按照那个结构写就可以了。最后按照上面的那个进行分享就可以了。