Modelo de balanceador de carga multi-datacenter Ansible

7

Estou migrando o gerenciamento de uma configuração multi-datacenter existente para o Ansible, mas não tenho certeza qual é a melhor maneira de modelá-lo, já que sou novo nele.

Eu tenho três datacenters D1, D2 e D3. Em cada uma delas, a mesma configuração é repetida de forma idêntica:

  • Um balanceador de carga nginx (lb.D [n]) vinculado a um IP público
  • Dois servidores de aplicativos (como [1-2] .D [n]) que recebem tráfego somente do balanceador de carga local
  • Um escravo (somente leitura) Servidor de BD (db.D [n]) a partir do qual os servidores de aplicativos lêem.

O arquivo de hosts que eu fiz até agora é parecido com isto:

# DC1 -----------
[dc_1_webservers]
10.43.0.10

[dc_1_appservers]
10.43.0.20
10.43.0.21

[dc_1_dbservers]
10.43.0.30

[dc_1:children]
dc_1_webservers
dc_1_appservers
dc_1_dbservers

# DC2 -----------
[dc_2_webservers]
10.43.10.10

[dc_2_appservers]
10.43.10.20
10.43.10.21

[dc_2_dbservers]
10.43.10.30

[dc_2:children]
dc_2_webservers
dc_2_appservers
dc_2_dbservers

# DC3 -----------
[dc_3_webservers]
10.43.20.10

[dc_3_appservers]
10.43.20.20
10.43.20.21

[dc_3_dbservers]
10.43.20.30

[dc_3:children]
dc_3_webservers
dc_3_appservers
dc_3_dbservers

[webservers:children]
dc_1_webservers
dc_2_webservers
dc_3_webservers

[appservers:children]
dc_1_appservers
dc_2_appservers
dc_3_appservers

Eu deixei intencionalmente apenas endereços IP aqui porque gostaria de entender como uma solução Ansible pura funcionaria, em vez de recorrer ao DNS.

O problema é preencher corretamente o upstream do proxy reverso do nginx, de forma que apenas os servidores de aplicativos locais de cada DC sejam adicionados quando a função nginx for executada e o modelo de arquivo de configuração for copiado na máquina do balanceador de carga . Em particular, é possível fazer algo assim?

# file /etc/nginx/sites-enabled/loadbalancer.conf in lb.D[n] (i.e. lb.D2)
 upstream backend  {
 # Iterate over the app servers in the current data center (i.e. D2)
 {% for host in [datacenters][current_datacenter][appservers] %}
     # Add each local app server IP to the load balancing pool 
     # (i.e. 10.43.10.20 and 10.43.10.21 for DC2)
     server {{ hostvars[host]['ansible_eth0']['ipv4']['address'] }};
 {% endfor %}
 }

Por um lado, não tenho certeza se o arquivo hosts faz todo o sentido (devo adicionar variáveis às entradas individuais? Na configuração atual, não posso fazer algo como [dc] [3] [appservers], embora eu Não tenho certeza de que é onde a solução está.)

Muito obrigado!

EDIT 1:

A estrutura do manual é a seguinte:

main.yml
hosts
vars.yml
servers/
    webservers.yml
    appservers.yml
roles/
   base/
     files/
       ssh/
       newrelic/
     tasks/
       main.yml
     handlers/
       main.yml
   webserver/
     files/
       ssl_certs/
     templates/
       nginx/
          loadbalancer.j2
     tasks/
       main.yml
     handlers/
       main.yml
   appserver/
     files/
       pip/
         requirements.txt
     templates/
       supervisor/
          gunicorn.j2
     tasks/
        main.yml
     handlers/
        main.yml

O ponto de entrada main.yml é apenas duas linhas:

---
- include: servers/webservers.yml
- include: servers/appservers.yml

webservers.yml reúne fatos sobre os appservers (imaginei que seria necessário atingir meu objetivo, embora eu não esteja totalmente certo de como ainda), e então primeiro invoco uma função base que apenas instala algumas chaves SSH compartilhadas, NewRelic ligações e outras coisas que são comuns a todas as máquinas em nossa nuvem e, em seguida, invocam a função real do servidor da Web.

---
- name: Gather data about appservers
  hosts:  appservers
  gather_facts: yes
  tasks:
    - debug: Gather Facts

- name: Configure all frontend web servers
  hosts: webservers
  sudo: yes
  roles:
    - { role: base }
    - { role: webserver }

Essa função "webserver" instala o nginx, copia os certificados SSL e finalmente copia o modelo de configuração nginx do jinja2.

 - name: Install nginx configuration file.
    template: src=files/loadbalancer.j2 dest=/etc/nginx/sites-available/{{ project_name }} backup=yes
    
por Davide 21.05.2015 / 02:30

1 resposta

3

Você pode utilizar variáveis mágicas group_names e groups para procurar grupos definidos no seu inventário:

---
- hosts: webservers
  vars:
    dcs: [dc_1, dc_2, dc_3]
  tasks:
  - debug:
      msg: |
        upstream backend {
        {%- for dc in dcs %}
        {%-   if dc in group_names %}
        {%-     for host in groups[dc+'_appservers'] %}
        server {{host}};
        {%-     endfor %}
        {%-   endif %}
        {%- endfor %}
        }

Este manual fornece a seguinte saída.

TASK: [debug ]     **************************************************************** 
ok: [10.43.0.10] => {
    "msg": "upstream backend { server 10.43.0.20; server 10.43.0.21;}"
}
ok: [10.43.10.10] => {
    "msg": "upstream backend { server 10.43.10.20; server 10.43.10.21;}"
}
ok: [10.43.20.10] => {
    "msg": "upstream backend { server 10.43.20.20; server 10.43.20.21;}"
}

Altere server {{host}}; conforme necessário.

    
por 26.05.2015 / 15:59

Tags