如何处理Ansible角色中的服务器依赖性?

时间:2016-03-10 20:13:55

标签: nginx ansible ansible-playbook

我是Ansible的新手。我的Ansible剧本有以下目录结构:

$HOME/playbooks
├── project1
├── project2
└── roles

我在角色目录中收集我常用的角色,例如我的“nginx”角色,然后通过在每个项目的ansible.cfg文件中添加以下行,在项目目录中引用这些角色:

# $HOME/playbooks/project1/ansible.cfg
[defaults]
roles_path = $HOME/playbooks/roles

当公共角色任务取决于运行任务的服务器时,如何配置单独的Ansible playbook任务和常见角色任务?在我的例子中,我有一个用于配置我的Web服务器的“webservers.yml”手册和一个用于配置我的文件服务器的“fileservers.yml”手册。我的网站将在我的网络服务器上运行,但我的静态和媒体文件将从一个单独的文件服务器提供。我目前在我的nginx角色的main / task.yml文件中包含以下任务:

# $HOME/playbooks/roles/nginx/tasks/main.yml
- name: create nginx config file
  template: src=nginx.conf.j2
            dest=/etc/nginx/sites-available/{{ domain }}.conf
  notify: restart nginx
  become: True
  tags: nginx

问题是每个服务器上的nginx配置文件会有所不同,因为(我认为)在我的Web服务器上运行的nginx进程需要将静态文件请求重定向到在我的文件服务器上运行的nginx进程。我应该在我的常见nginx角色中保留“创建nginx配置文件”任务,并让它将最小模板复制到每个服务器上,然后在我的网络服务器和文件服务器手册中再次调用该任务,并让每个人都部署服务器特定版本的配置文件(例如nginx.webserver.conf.j2与nginx.fileserver.conf.j2)?我应该将创建配置文件从我的主要角色任务中删除,并在每个剧本中执行它吗? (这种方法对我来说似乎不对)或者有更强大的方法来做到这一点吗?

谢谢!

2 个答案:

答案 0 :(得分:0)

如果每台计算机上的nginx配置不同,那么您应该有清单变量来驱动每台服务器上配置文件的生成。适当地模板化你的nginx.conf文件以处理你的web服务器和文件服务器配置。如果配置完全不同,您应该考虑为每个配置设置单独的角色(nginx_web和nginx_file)或至少单独的jinja模板。

答案 1 :(得分:0)

@ Petro026已经提到的库存或组变量是一种选择。在您的nginx角色或配置模板中,您只需检查这些变量。

但我认为在这种情况下有更好的选择,因为角色是在Web服务器或文件服务器手册的上下文中显式调用的。您可以简单地引入一个影响角色工作方式的角色参数。

- role: nginx
  mode: direct

或者是网络服务器mode: redirect

然后你可以在任务级别上过滤

- some: task
  when: mode == "redirect"

或者根据条件处理模板中的所有内容。

{% if mode == "redirect" %}
# I am a webserver
{% else %}
# I am a fileserver
{% endif %}

现在,结果与使用组或主机变量完全相同,但我认为看到该剧本的人发生的事情更加明显,nginx角色支持不同的模式和定义信息的位置(作为角色参数)。

  

我应该将创建配置文件从我的主要角色任务中删除,并在每个剧本中执行它吗? (这种方法对我来说似乎不对)或者有更强大的方法来做到这一点吗?

这是另一种选择。实际上,把任务放在剧本中似乎是错误的。但是嵌套角色怎么样?这再次为您提供了一个干净的解决方案。

保持您的nginx角色,只删除文件服务器和网络服务器之间不同的部分。

然后你创建两个新角色。一个名为nginx_web,一个nginx_file。现在,在这两个角色中,您都可以设置nginx中常见<role>/meta/main.yml角色的依赖关系:

dependencies:
  - role: nginx
    tags: nginx

现在,您只需要将不同的部分添加到tasks/main.yml nginx_webnginx_file的{​​{1}}中,看起来它只是单个模板任务。您甚至可以保留处理程序以在公共nginx角色中重新启动nginx,并从其他角色调用它。

您现在需要在游戏手册中引用nginx_webnginx_file。在{nginx_web / file中的任务之前,nginx角色自动作为依赖项执行。

更新:描述角色参数

角色可以以不同的方式应用。作为字符串或字典。示例为字符串

roles:
  - roleName

如果您希望添加标签,条件或其他参数等附加信息,可以提供字典。在这种情况下,角色名称将进入dict键role

roles:
  - role: roleName
    tags: someTag
    when: someVar is defined
    become: True
    foo: bar

所有其他数据都会传递到角色内的每个任务。 Ansible将表现为tagsbecomewhen应用于角色内的每个任务。 Ansible不知道的其他所有内容都将被视为变量。

或者你可以把dict写成JSON,因为YAML支持有限的JSON格式。

roles:
  - {role: "roleName", tags: "someTag", when: "someVar is defined", become: True, foo: "bar"}
  

但我觉得这个丑陋而且更喜欢纯粹的YAML定义

后者是documentation

中显示的格式
  

此外,如果您希望通过添加变量来参数化角色,您可以这样做:

---

- hosts: webservers
  roles:
    - common
    - { role: foo_app_instance, dir: '/opt/a',  app_port: 5000 }
    - { role: foo_app_instance, dir: '/opt/b',  app_port: 5001 }