Ansible针对每个数据库名称运行任务一次

3
我正在使用Ansible将多个站点部署到同一台服务器上。每个站点都是Ansible清单中单独的“主机”,这非常有效。
但是,只有两个数据库:生产和测试。如何确保我的数据库迁移任务每个数据库只运行一次?
我已经研究了group_by、run_once和delegate_to功能,但不确定如何将它们结合起来使用。
主机看起来像这样:
[production]
site1.example.com       ansible_ssh_host=webserver.example.com
site2.example.com       ansible_ssh_host=webserver.example.com

[beta]
beta-site1.example.com  ansible_ssh_host=webserver.example.com
beta-site2.example.com  ansible_ssh_host=webserver.example.com

[all:children]
production
beta

目前的操作指南如下:

---
- hosts: all
- tasks:

  # ...

  - name: "postgres:  Create PostgreSQL database"
    sudo: yes
    sudo_user: postgres
    postgresql_db: db="{{ DATABASES.default.NAME }}" state=present template=template0 encoding='UTF-8' lc_collate='en_US.UTF-8' lc_ctype='en_US.UTF-8'
    tags: postgres
    register: createdb
    delegate_to: "{{ DATABASES.default.HOST|default(inventory_hostname) }}"

  # ...

  - name: "django-post:  Create Django database tables (migrate)"
    django_manage: command=migrate app_path={{ src_dir }} settings={{ item.settings }} virtualenv={{ venv_dir }}
    with_items: django_projects
    #run_once: true
    tags:
    - django-post
    - django-db
    - migrate

通常,“每组一次”不是受支持的语义,试图将所有内容放入单个操作可能会带来更多麻烦。只想澄清一下,您希望第一个任务在每个主机上运行一次,第二个任务在两个组中各运行一次,总共运行两次? - nik.shornikov
2个回答

3
我发现最好的方法是将任务的执行限制在组中的第一个主机上。因此,您需要将组名和数据库添加到group_vars文件中,例如:
group_vars/production
---
dbtype=production
django_projects:
    - name: project_1
      settings: ...
    - name: project_n
      settings: ...

group_vars/beta

---
dbtype=beta
django_projects:
    - name: project_1
      settings: ...
    - name: project_n
      settings: ...

hosts

[production]
site1.example.com       ansible_ssh_host=localhost ansible_connection=local
site2.example.com       ansible_ssh_host=localhost ansible_connection=local

[beta]
beta-site1.example.com  ansible_ssh_host=localhost ansible_connection=local
beta-site2.example.com  ansible_ssh_host=localhost ansible_connection=local


[all:children]
production
beta

并将任务执行限制在匹配该组的第一个主机上:
- name: "django-post:  Create Django database tables (migrate)"
  django_manage: command=migrate app_path={{ src_dir }} settings={{ item.settings }} virtualenv={{ venv_dir }}
  with_items: django_projects
  when: groups[dbtype][0] == inventory_hostname 
  tags:
    - django-post
    - django-db
    - migrate

2
因此,以下内容将阐述为什么我说“每组一次”通常不被支持。当然,我希望看到一个更干净的开箱即用的方法,如果“每组一次”不是你想要的,请告诉我。
主机:
[production]
site1.example.com       ansible_ssh_host=localhost ansible_connection=local
site2.example.com       ansible_ssh_host=localhost ansible_connection=local

[beta]
beta-site1.example.com  ansible_ssh_host=localhost ansible_connection=local
beta-site2.example.com  ansible_ssh_host=localhost ansible_connection=local

[beta:vars]
dbhost=beta-site1.example.com

[production:vars]
dbhost=site1.example.com

[all:children]
production
beta

以下是一个示例playbook,它将在每个组(两个真实组)上执行一些操作,其中包括dbhost

---
- hosts: all
  tasks:
  - name: "do this once per group"
    sudo: yes
    delegate_to: localhost
    debug:
      msg: "do something on {{hostvars[groups[item.key].0]['dbhost']}} for {{item}}"
    register: create_db
    run_once: yes
    with_dict: groups
    when: item.key not in ['all', 'ungrouped']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接