2015-09-25 25 views
9

Nella pagina delle best practice Ansible: http://docs.ansible.com/ansible/playbooks_best_practices.html#top-level-playbooks-are-separated-by-role mostra un esempio in cui il playbook master site.yml include un paio di altri playbook di primo livello webservers.yml e dbservers.yml. All'interno di questi quaderni, ognuno di essi include il ruolo comune. Alcuni file di inventario Ho tutti i miei gruppi eseguiti su un singolo host. Un altro file di inventario ho un host per gruppo. Per il caso in cui mai un gruppo è su un host, se eseguo site.yml puoi vedere che il ruolo comune viene riprodotto due volte, uno per webservers.yml e uno per dbservers.yml.Best practice Ansible non ripetere il ruolo comune

Qual è una soluzione per evitare questo? Immagino che tu possa prendere il ruolo comune da webservers.yml e dbservers.yml e invece all'interno di site.yml abbiamo un'attività che ha come target sia il ruolo comune. Ma allora non posso fornire individualmente un webserver o un dbserver con common.

risposta

1

Il mio approccio è quello di non includere i quaderni nei playbook. Almeno non quando lo farebbe comporterebbe un ruolo che si esegue più volte in un singolo lavoro.

Tutto ciò che è necessario includere in più di un playbook viene convertito in un ruolo e tale ruolo può essere incluso in molti playbook. Se finisco con diversi playbook che includono una serie duplicata di ruoli, posso combinare quei ruoli in un singolo ruolo che dipende solo dagli altri ruoli per evitare quella duplicazione.

1

Il mio approccio è creare un file lock sul server per ogni ruolo. Funziona abbastanza bene.

Per esempio io ho un ruolo chiamato common è così che il mio tasks/main.yml assomiglia:

- name: check lock file exist 
    stat: path=/tmp/ansible-common-role 
    ignore_errors: true 
    register: lock_file 

- name: install apt packages 
    apt: name={{ item }} state=present 
    with_items: 
    - python-setuptools 
    when: lock_file.stat.exists == false 

..... 
# other tasks with 
# when: lock_file.stat.exists == false 
..... 

- name: Create lock file 
    file: path=/tmp/ansible-common-role state=touch 
    when: lock_file.stat.exists == false 

Come si può vedere l'esempio di cui sopra, il playbook salterà tutte le attività se è già correva.

3

Determinare le dipendenze del ruolo utilizzando i file meta nella directory dei ruoli. Le dipendenze dei ruoli consentono di inserire automaticamente altri ruoli quando si utilizza un ruolo. Le dipendenze dei ruoli sono memorizzate nel file meta/main.yml contenuto nella directory dei ruoli.

Le dipendenze dei ruoli vengono sempre eseguite prima del ruolo che le include e sono ricorsive. Per impostazione predefinita, i ruoli possono anche essere aggiunti come dipendenza solo una volta - se un altro ruolo lo elenca anche come dipendenza, non verrà eseguito di nuovo. Questo comportamento può essere sovrascritto aggiungendo allow_duplicates: yes al file meta/main.yml.

See an example in the Ansible documentation.

+1

mi piace questo approccio e sembra avere più senso per me. Tuttavia, quando effettivamente provo a implementarlo, non funziona. Il mio ruolo comune viene eseguito più volte. Ho cercato esplicitamente di impostare allow_duplicates: no senza alcun effetto. Sembra che ci siano altre persone con questo stesso problema? https://github.com/ansible/ansible/issues/5971 – user1087973

0

Si potrebbe anche costruire un gruppo temporaneo utilizzando add_host, qualcosa come:

1. target: webservers--> add hosts to group "common_roles" 
2. target: dbservers --> add hosts to gruop "common_roles" 
3. Target: common_roles --> execute whatever common roles you need 
4. regular group by group execution. 
1

Come altri Ho avuto questo problema, e anche se il ruolo è idempotente, ci vuole tempo per l'esecuzione, quindi potremmo volerlo eseguire solo una volta.

Ho utilizzato un approccio simile a @Vor ma ho scelto facts invece di creare file.

Promemoria:

fatti sopravvivere fra i giochi durante una corsa Ansible, ma non saranno salvate attraverso esecuzioni anche se si utilizza una cache fatto.

Esempio

site.yml

--- 
- hosts: all 
    roles: [common] 
- include: db.yml 
- include: web.yml 

db.yml

--- 
- hosts: db 
    roles: 
    - { role: common, when: isdef_common_role is not defined } 
    - db 

web.yml

--- 
- hosts: web 
    roles: 
    - { role: common, when: isdef_common_role is not defined } 
    - web 

roles/common/tasks/main.yml

--- 
- debug: 'msg="{{ inventory_hostname }} common"' 
- set_fact: isdef_common_role=1 

Questo è, infatti, un po 'ridondante (come si deve fare un condizionale includono ogni volta), ma presentano i seguenti vantaggi:

  • funziona sulla maggior parte delle situazioni che posso pensare (ansible-playbook site.yml, ansible-playbook site.yml -l common, ansible-playbook site.yml -l db, ansible-playbook db.yml, ...)
  • permetterà di decidere se si desidera ripetere l'esecuzione del comune

Se non si vuole ripetere la { role: common, when: isdef_common_role is not defined }, si potrebbe mettere condizioni nel ruolo comune utilizzando il seguente:

site.yml: nessuna richiesta di modifica

db.yml, 01.232.: togliere il condizionale dai ruoli

roles/common/tasks/main.yml

--- 
- include: tasks.yml 
    when: isdef_common_role is not defined 
- set_fact: isdef_common_role=1 

roles/common/tasks/tasks.yml

--- 
- debug: 'msg="{{ inventory_hostname }} common"' 
3

@ user1087973 Si sta utilizzando i tag? Se si sta utilizzando i tag, un ruolo comune con diversi tag è considerare come diverso:

Ad esempio:

role_common

Role1: SRV ospite tag_role_1 dipende role_common

ruolo 2: host SRV tag_role_2 dipende da role_common

Il vostro ruolo comune sarà eseguito due volte, perché è considerato come diverso a causa dei tag

Date un'occhiata con --list-tasks e vedrete che

Una corretta soluzione invece di utilizzare i tag è quello di utilizzare diversi file YML e includere nel vostro site.yml

http://docs.ansible.com/ansible/playbooks_best_practices.html#top-level-playbooks-are-separated-by-role

Spero che questo può aiutare