Atualize um host por vez

AnsibleBeginner
Pratique Agora

Introdução

O Courtyard Sessions já tem um site funcional em dois servidores. A nova programação está pronta, mas atualizar os dois nós ao mesmo tempo poderia deixar os visitantes sem um site disponível. Use o Ansible para inspecionar o estado e publicar o novo pacote em um servidor por vez.

Você precisa saber navegar por diretórios no terminal e ter praticado um pequeno inventário Ansible, variáveis e tarefas file/copy. O gateway, o acesso SSH e os pacotes estão preparados. Este laboratório explica o local de execução, a delegação, os lotes, os links de versão e as verificações HTTP completas antes de usá-los. A duração é uma estimativa do autor que inclui leitura e correções comuns.

Confira onde cada tarefa é executada

Nesta etapa, você criará um playbook de inspeção somente de leitura que mostra a versão ativa de cada servidor e o pool de roteamento realmente ativo.

O Courtyard Sessions já tem um site funcional para visitantes. Abra a aba Website. Leia Good things, around the corner. e clique em The program. A página rola até duas sessões, começando por Coffee in the courtyard. Clique em Download the program (CSV) e abra o arquivo baixado: o cabeçalho é time,session,place, seguido pelas duas sessões exibidas. Um CSV é uma tabela de texto com campos separados por vírgulas. Esse download real deve continuar disponível durante a atualização.

O gateway distribui solicitações HTTP curtas entre dois servidores. Remover um servidor do pool ativo impede que ele receba novas solicitações do gateway; adicioná-lo o devolve ao rodízio. Esse pequeno gateway preparado não drena conexões de longa duração nem reproduz uma plataforma completa de publicação em nuvem. Ambos os servidores são contêineres gerenciados por SSH que compartilham o kernel desta VM de treinamento. O controlador é a máquina que executa o Ansible e o gateway.

Mude para a aba Controller. Comece em /home/labex/project. pwd mostra o diretório atual e cat imprime um arquivo:

pwd
cat inventory.yml
cat group_vars/all.yml

O inventário contém dados estruturados compatíveis com YAML. Seu grupo website contém web1 e web2, cada um com seu endereço real ansible_host e os dados SSH preparados. O grupo control contém controller com conexão local. Use inventory.yml, selecionado pelo ansible.cfg do projeto; o inventory.ini inicial da imagem não é o inventário do curso.

As variáveis de grupo fornecem backend_port (8090), o pool_api exclusivo do controlador, o release_root permitido, o package_root local e os identificadores de versão. baseline_release é courtyard-preview; approved_release é courtyard-weekend. São nomes de diretórios, não versões do Ansible ou do software. Uma porta HTTP identifica um serviço que escuta em um endereço. /identity retorna JSON, texto estruturado que identifica a versão realmente em execução. /pool retorna a lista atual de nós ativos do controlador.

Se um comando mostrar “No such file or directory”, confira a grafia com ls e volte com cd /home/labex/project se necessário. Você pode repetir uma leitura com segurança. Preserve todos os arquivos dos pacotes, dados de conexão, arquivos da versão original e notas privadas do organizador.

Por padrão, o Ansible executa uma tarefa por SSH em cada servidor selecionado. Ali, 127.0.0.1 significa aquele próprio servidor. delegate_to: controller executa aquela tarefa específica no controlador, cujo próprio 127.0.0.1 hospeda a API do pool. A delegação não altera inventory_hostname: ele continua nomeando o servidor gerenciado naquele momento. Assim, uma solicitação do controlador pode se referir ao servidor correto.

Crie inspect.yml. cat > filename grava um arquivo, substituindo um existente com o mesmo nome. <<'YAML' inicia um here-document: cole até o YAML final em uma linha separada. O delimitador entre aspas mantém o texto colado literal; o Ansible processa as expressões quando executa o playbook. A indentação usa espaços. {{ variable }} insere uma variável do Ansible. gather_facts: false pula a coleta de informações de máquina que não pertencem ao exercício.

O módulo uri envia uma solicitação HTTP real; seu método padrão GET lê um recurso. register salva o resultado real com um nome. Nas respostas JSON, .json contém os campos analisados. debug imprime essas observações salvas; não cria a versão nem o estado do pool.

cat > inspect.yml <<'YAML'
- name: Inspect the running website without changing it
  hosts: website
  gather_facts: false
  tasks:
    - name: Read this backend on its own loopback address
      ansible.builtin.uri:
        url: "http://127.0.0.1:{{ backend_port }}/identity"
      register: backend
    - name: Read the pool on the controller
      ansible.builtin.uri:
        url: "{{ pool_api }}/pool"
      delegate_to: controller
      register: pool
    - name: Show the actual release and active pool
      ansible.builtin.debug:
        msg:
          node: "{{ inventory_hostname }}"
          release: "{{ backend.json.release }}"
          active: "{{ pool.json.active }}"
YAML

Execute o playbook. ansible-playbook lê as tarefas e as aplica ao inventário:

ansible-playbook inspect.yml

Cada servidor deve mostrar release: courtyard-preview, e active deve incluir web1 e web2. A formatação e os endereços podem variar. Observe que o primeiro uri é executado no servidor, enquanto a leitura do pool mostra uma delegação como web1 -> controller. Ambas as tarefas são somente de leitura.

Se a indentação YAML estiver incorreta, copie novamente o bloco completo para corrigir o arquivo e tente outra vez. Este playbook nunca deve copiar arquivos nem alterar o pool. Agora você tem uma ferramenta útil para observar novamente o estado depois da publicação.

Publique em um servidor por vez

Nesta etapa, você entregará o pacote web aprovado por SSH, validará o conteúdo real para visitantes e devolverá cada servidor ao serviço antes de iniciar o seguinte.

Permaneça na aba Controller, em /home/labex/project. Liste os pacotes e leia a programação aprovada. ls lista as entradas do diretório:

ls packages
cat packages/courtyard-weekend/schedule.csv

A programação aprovada contém três sessões: Bread and stories, Acoustic afternoon e Print a postcard. Uma página inicial correta não basta: os visitantes precisam do download completo correspondente. O pacote courtyard-incomplete fica reservado para o próximo laboratório; aqui selecione courtyard-weekend, como a variável release_id já faz.

O playbook processa um lote de um host usando serial: 1. Dentro do lote, ele remove o nó do pool, copia o pacote, altera o link da versão ativa, verifica ambos os recursos e recoloca o nó. Só então começa o lote seguinte. order: sorted faz a demonstração começar por web1. any_errors_fatal: true propaga explicitamente uma falha não tratada para interromper o play. Nestes lotes de um host, a falha desse host já faz o lote inteiro falhar. A opção não desfaz tarefas concluídas. O próximo laboratório acrescenta recuperação.

A API do pool aceita HTTP POST em /pool com um corpo JSON: node nomeia o nó gerenciado, e enabled é o booleano false para remover ou true para adicionar. body_format: json serializa corretamente o corpo. As tarefas do pool são executadas no controlador; as tarefas de arquivos, no servidor SSH selecionado.

file com state: directory cria um diretório; o modo '0755' permite que o proprietário escreva e todos leiam ou atravessem o diretório. copy envia o pacote selecionado do controlador àquele servidor. A / final de src copia seu conteúdo, com modo '0644' para arquivos legíveis. file com state: link cria ou atualiza um link simbólico: current aponta para um diretório de versão. O servidor HTTP preparado serve arquivos reais pelo link a cada solicitação. Alterá-lo ativa o site sem reiniciar o servidor e mantém intacto o diretório original.

Nas sondagens HTTP executadas no controlador, hostvars[inventory_hostname].ansible_host obtém explicitamente o endereço do servidor gerenciado. Durante a delegação, uma variável de conexão sem essa referência pode corresponder ao host delegado. return_content: true salva o corpo real em .content.

assert exige que sua expressão that seja verdadeira. lookup('file', ...) lê o arquivo esperado do pacote no controlador; ~ une strings de caminho. rstrip=False preserva as quebras de linha finais para comparar o corpo completo, em vez de um trecho aparado. A página inteira do candidato e o CSV aprovado inteiro devem corresponder antes de recolocar o nó. Um 404 significa que o servidor respondeu, mas o recurso está ausente; um erro de conexão significa que não foi possível alcançar o serviço. Nenhum dos dois indica uma versão saudável.

Escreva a implantação completa. O here-document usa o mesmo método da ferramenta de inspeção:

cat > rollout.yml <<'YAML'
- name: Release one website backend at a time
  hosts: website
  order: sorted
  gather_facts: false
  serial: 1
  any_errors_fatal: true
  tasks:
    - name: Drain this backend from the pool
      ansible.builtin.uri:
        url: "{{ pool_api }}/pool"
        method: POST
        body_format: json
        body:
          node: "{{ inventory_hostname }}"
          enabled: false
      delegate_to: controller
    - name: Create this release directory
      ansible.builtin.file:
        path: "{{ release_root }}/releases/{{ release_id }}"
        state: directory
        mode: '0755'
    - name: Copy the selected package over SSH
      ansible.builtin.copy:
        src: "{{ package_root }}/{{ release_id }}/"
        dest: "{{ release_root }}/releases/{{ release_id }}/"
        mode: '0644'
    - name: Activate the selected release
      ansible.builtin.file:
        src: "{{ release_root }}/releases/{{ release_id }}"
        dest: "{{ release_root }}/current"
        state: link
    - name: Read the real candidate homepage
      ansible.builtin.uri:
        url: "http://{{ hostvars[inventory_hostname].ansible_host }}:{{ backend_port }}/"
        return_content: true
      delegate_to: controller
      register: homepage
    - name: Require the complete candidate homepage
      ansible.builtin.assert:
        that: homepage.content == lookup('file', package_root ~ '/' ~ release_id ~ '/index.html', rstrip=False)
    - name: Read the real candidate download
      ansible.builtin.uri:
        url: "http://{{ hostvars[inventory_hostname].ansible_host }}:{{ backend_port }}/schedule.csv"
        return_content: true
      delegate_to: controller
      register: download
    - name: Require the complete approved program
      ansible.builtin.assert:
        that: download.content == lookup('file', package_root ~ '/' ~ approved_release ~ '/schedule.csv', rstrip=False)
    - name: Rejoin only after both business checks
      ansible.builtin.uri:
        url: "{{ pool_api }}/pool"
        method: POST
        body_format: json
        body:
          node: "{{ inventory_hostname }}"
          enabled: true
      delegate_to: controller
YAML

Primeiro confira o YAML e a estrutura das tarefas sem implantar. --syntax-check valida a sintaxe, mas não comprova o resultado funcional:

ansible-playbook rollout.yml --syntax-check

Se houver erros de grafia ou indentação, copie novamente o arquivo inteiro e repita a verificação. Depois execute a implantação real:

ansible-playbook rollout.yml

As tarefas de web1 devem terminar antes das de web2. Ambos os hosts devem terminar com failed=0 e unreachable=0. As solicitações operacionais de remoção ou adição podem mostrar ok; seu sucesso HTTP e efeito real importam mais que o contador changed do resumo. Se um erro de edição interromper a execução, corrija o arquivo inteiro e execute novamente com o mesmo pacote aprovado. Repetir o fluxo remove, verifica e recoloca novamente; não é uma implantação sem operações.

Inspecione o estado com sua ferramenta original:

ansible-playbook inspect.yml

Os dois nós devem informar courtyard-weekend e estar ativos no pool. Mude para a aba Website e recarregue. O título deve ser A little room for a good afternoon. Clique em The program, confira as três sessões, baixe o CSV novamente e abra o arquivo novo para confirmar as três linhas completas. Se já houver um download, o navegador poderá acrescentar um número ao nome. Plan a visit deve continuar levando às informações de acesso sem degraus pela entrada do jardim.

A programação atualizada contém as três sessões aprovadas; o download real do CSV fica junto da lista.

Site atualizado do Courtyard Sessions com as três sessões da programação

Isso demonstra uma atualização funcional de dois nós no ambiente preparado de solicitações curtas. Não estabelece uma garantia de publicação sem interrupções para qualquer tráfego ou aplicativo de produção.

Resumo

Você criou uma ferramenta de inspeção somente de leitura e usou uma implantação sequencial do Ansible para entregar um site real e o download completo da programação. As alterações delegadas do pool e as verificações reais vinculam cada decisão de publicação ao servidor gerenciado correto.