Stoppe ein fehlerhaftes Update

AnsibleBeginner
Jetzt üben

Einführung

Ein neues Paket für Courtyard Sessions hat eine überzeugende Startseite, doch der Besucherdownload fehlt. Diese unabhängige Umgebung beginnt mit der ursprünglichen funktionierenden Website auf beiden Backends. Verbessere den vorbereiteten Ansible-Ablauf so, dass ein gescheiterter Kandidat die vorherige nutzbare Version wiederherstellt und vor der Aktualisierung eines weiteren Knotens stoppt.

Bearbeite zuerst Aktualisiere einen Host nach dem anderen oder bringe entsprechende Praxis mit Prüfwerkzeug, Delegierung, seriellen Batches, copy/file-Aufgaben und vollständigen HTTP-Inhaltsprüfungen mit. Dieses Lab erklärt das Erfassen des tatsächlichen Links und die Wiederherstellung mit block/rescue. Die Dauer ist eine Autorenschätzung und keine mit Einsteigern gemessene Bearbeitungszeit.

Stelle die Version wieder her und stoppe den Rollout

In diesem Schritt erfasst du die tatsächliche vorherige Version, stellst den aktuellen Knoten nach einer fehlgeschlagenen Inhaltsprüfung wieder her und stoppst ausdrücklich den nächsten Batch.

Öffne Website. Die ursprüngliche Überschrift lautet Good things, around the corner. Prüfe über The program und Download the program (CSV) die beiden ursprünglichen Angebote. Gateway und beide SSH-Backends sind vom vorherigen Lab unabhängig; frühere Dateien oder laufende Prozesse werden nicht benötigt.

Wechsle zu Controller, das in /home/labex/project startet. Die vorbereiteten Dateien inspect.yml und rollout.yml sind die Werkzeuge des vorherigen Labs. Lies das ausgewählte Paket und den aktuellen Zustand:

cat group_vars/all.yml
ls packages/courtyard-incomplete
ansible-playbook inspect.yml

release_id wählt courtyard-incomplete. Startseite und Identitätsdaten existieren, schedule.csv jedoch nicht. Beide echten Backends melden weiterhin courtyard-preview. Erhalte sämtliche bereitgestellten Paketbytes unverändert: Eine hinzugefügte CSV würde den Fehler verdecken, statt Wiederherstellung zu üben. Führe den ungeschützten Ablauf noch nicht aus.

Ein block gruppiert Aufgaben, die scheitern können; seine rescue-Aufgaben laufen nach einem gewöhnlichen Aufgabenfehler in diesem Block. Erfasse current davor mit stat, das Metadaten des Dateisystems liest. follow: false liest den Link selbst statt seines Zielverzeichnisses. Das gespeicherte previous.stat.lnk_source ist das tatsächliche vorherige Ziel. So stellt die Wiederherstellung die zuvor laufende Version her, statt ein festes Verzeichnis anzunehmen.

Die Wiederherstellung muss den Link zurücksetzen, die restaurierte Startseite und vollständige CSV anfordern und beide mit dem vorherigen Paket vergleichen. Der Filter basename extrahiert aus dem gespeicherten Ziel den Versionsverzeichnisnamen, damit die bestehenden Vergleiche mit lookup('file', ...) das passende lokale Paket lesen. Nur ein gesund wiederhergestellter Knoten darf zurück in den Pool. Fehlt eine wiederhergestellte Ressource oder ist sie falsch, scheitert diese rescue-Aufgabe und der Knoten bleibt draußen; das andere Backend bedient weiterhin Besucher.

Ein erfolgreiches rescue hebt den ursprünglichen Aufgabenfehler für Ansible-Entscheidungen zur Fehlerbehandlung auf. Deshalb stoppt any_errors_fatal allein nach erfolgreicher Wiederherstellung keine weiteren Batches. Ein ausdrückliches fail am Ende von rescue meldet den zurückgewiesenen Kandidaten und beendet den Ablauf vor dem nächsten Batch. Ein Exitstatus ungleich null ist hier beabsichtigt, obwohl die vorherige Website wieder gesund ist. Ungültiges YAML und nicht erreichbare SSH-Hosts lösen diesen rescue-Mechanismus nicht aus; er ist keine allgemeine Rückrollgarantie.

Ersetze rollout.yml durch diese vollständige Version. cat > ersetzt nur dieses Lernenden-Playbook; der Begrenzer in Anführungszeichen erhält die Ansible-Ausdrücke. Übernimm die gezeigten Leerzeichen:

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: Remember the actual previous release link
      ansible.builtin.stat:
        path: "{{ release_root }}/current"
        follow: false
      register: previous
    - name: Update this backend or recover it
      block:
        - 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
      rescue:
        - name: Restore the previous release link
          ansible.builtin.file:
            src: "{{ previous.stat.lnk_source }}"
            dest: "{{ release_root }}/current"
            state: link
        - name: Read the restored homepage
          ansible.builtin.uri:
            url: "http://{{ hostvars[inventory_hostname].ansible_host }}:{{ backend_port }}/"
            return_content: true
          delegate_to: controller
          register: restored_home
        - name: Require the complete previous homepage
          ansible.builtin.assert:
            that: restored_home.content == lookup('file', package_root ~ '/' ~ (previous.stat.lnk_source | basename) ~ '/index.html', rstrip=False)
        - name: Read the restored download
          ansible.builtin.uri:
            url: "http://{{ hostvars[inventory_hostname].ansible_host }}:{{ backend_port }}/schedule.csv"
            return_content: true
          delegate_to: controller
          register: restored_download
        - name: Require the complete previous program
          ansible.builtin.assert:
            that: restored_download.content == lookup('file', package_root ~ '/' ~ (previous.stat.lnk_source | basename) ~ '/schedule.csv', rstrip=False)
        - name: Rejoin only after both restoration checks
          ansible.builtin.uri:
            url: "{{ pool_api }}/pool"
            method: POST
            body_format: json
            body:
              node: "{{ inventory_hostname }}"
              enabled: true
          delegate_to: controller
        - name: Stop subsequent batches after recovery
          ansible.builtin.fail:
            msg: Candidate failed; the previous release is healthy again. Stop this rollout.
YAML

Prüfe die Syntax, bevor du ein Backend veränderst:

ansible-playbook rollout.yml --syntax-check

Versuche anschließend die unvollständige Version. Dieser Befehl soll nach der Wiederherstellung scheitern:

ansible-playbook rollout.yml

Lies den abschließenden Status sofort. $? enthält den Exitstatus des vorherigen Befehls; echo gibt ihn aus. Jeder weitere Befehl würde diesen von der Shell gespeicherten Wert ersetzen:

echo $?

Erwarte einen Status ungleich null, normalerweise 2. Die neue Startseite besteht die Prüfung, der Kandidatendownload liefert HTTP 404, die wiederhergestellte Startseite und CSV bestehen, danach scheitert Stop subsequent batches after recovery absichtlich. HTTP 404 bezeichnet den fehlenden Download. Die SSH-Verbindung bleibt für die Wiederherstellung nutzbar. web2 darf nicht mit den Veröffentlichungsaufgaben beginnen.

Starte das Beobachtungswerkzeug erneut:

ansible-playbook inspect.yml

Beide Backends müssen courtyard-preview melden und aktiv bleiben. Wechsle zu Website, lade neu, öffne The program, lade die CSV erneut herunter und bestätige die beiden ursprünglichen Angebote. Plan a visit muss weiterhin die Informationen zur Barrierefreiheit anzeigen.

Die wiederhergestellte Website bietet weiterhin die beiden ursprünglichen Angebote und den vollständigen Download.

Wiederhergestellte Website von Courtyard Sessions mit dem ursprünglichen Programm

Bei einem gewöhnlichen YAML- oder Dateinamenfehler prüfe mit ls, korrigiere das vollständige Playbook und wiederhole die Syntaxprüfung. Falls eine frühere Bearbeitung den Link bereits vor einer funktionierenden Wiederherstellung umgeschaltet hat, speichere zuerst das richtige Playbook von oben. Mit demselben erlernten Ablauf für eine gesunde Veröffentlichung kannst du das bekannte Originalpaket wiederherstellen, indem du es sowohl als Version als auch als erwartetes Programm auswählst. Die Anführungszeichen halten beide Zuweisungen in einem einzigen --extra-vars-Argument:

ansible-playbook rollout.yml --extra-vars "release_id=courtyard-preview approved_release=courtyard-preview"

Dieser Wiederherstellungsbefehl sollte erfolgreich sein. Bestätige beide Knoten mit inspect.yml und versuche dann den unvollständigen Kandidaten erneut mit dem ursprünglichen Befehl ansible-playbook rollout.yml, um den geforderten Fehler samt Wiederherstellung zu demonstrieren. Setze die VM nicht zurück und schreibe den Kandidaten nicht um. Erhalte die Wiederverwendbarkeit: Pool-Anfragen müssen das bereitgestellte pool_api verwenden, Dateipfade release_root und package_root sowie Veröffentlichungsaufgaben die hier gezeigten direkten Module.

Zusammenfassung

Du hast die tatsächliche vorherige Website nach einem echten Fehler durch einen fehlenden Download wiederhergestellt. Beide Wiederherstellungsprüfungen steuern die Rückkehr in den Pool, und ein ausdrücklicher Fehler stoppt weitere Ansible-Batches selbst nach erfolgreichem rescue.