GNU/Linux >> Znalost Linux >  >> Linux

Použití Ansible k interakci s webovými koncovými body

Vždy hledám chytré věci, které by se daly dělat s Ansible. S tolika nástroji a službami, které využívají aplikační programovací rozhraní (API) na bázi HTTP, je jasné, že programová interakce se službami řízenými API od Ansible je cennou schopností. Může to znít jako pokročilá funkce, ale tento článek vás provede případem použití, který ukazuje, jak i jednoduchá prostředí mohou těžit z výkonu a jednoduchosti modulu URI Ansible.

Interakce s jednoduchými koncovými body

Nejprve vás provedu příručkou, která využívá schopnosti Ansible HTTP k inteligentním rozhodnutím během upgradu webového serveru. Příručka níže:

  1. Spustí skript údržby.
  2. Zkontroluje, zda koncový bod rozhraní API pro kontrolu stavu vrací službu HTTP 503, která je dočasně nedostupná zpráva.
  3. Spustí skript pro upgrade aplikace.
  4. Spustí skript po údržbě, který sdělí webovému serveru, aby začal znovu normálně reagovat.
  5. Znovu zkontroluje rozhraní API pro kontrolu stavu, aby se ujistil, že odpovídá 200 OK .

Zde je příručka:

---

- hosts: all
  tasks:
    - name: Run maintenance start script
      command:
        cmd: /usr/local/sbin/start_maintenance.sh

    - name: Confirm that 503 Unavailable response is returned
      uri:
        url: "http://{{ ansible_host }}/api/v1/healthcheck"
        status_code: 503

    - name: Update application
      command:
        cmd: /usr/local/sbin/update_app.sh

    - name: Run maintenance end script
      command:
        cmd: /usr/local/sbin/end_maintenance.sh

    - name: Confirm that 200 OK response is returned
      uri:
        url: "http://{{ ansible_host }}/api/v1/healthcheck"
        status_code: 200

K oslovení /api/v1/healthcheck používám modul URI Ansible na serveru. První volání URI očekává HTTP 503 má být vrácen stavový kód, protože server by měl být v režimu údržby a neměl by obsluhovat požadavky. Po upgradu volání URI očekává HTTP 200 stavový kód označující, že webový server je opět v pořádku.

Tento jednoduchý přístup zvyšuje bezpečnost mé příručky. Pokud server nepřejde do režimu údržby, pak Ansible neprovede žádné opravy:

fsh$ ansible-playbook -i inventory.ini playbook-healthcheck.yml

PLAY [all] ***********************************************************************************

TASK [Gathering Facts] ***********************************************************************
ok: [nyc1-apiserver-1.example.com]

TASK [Run maintenance start script] **********************************************************
changed: [nyc1-apiserver-1.example.com]

TASK [Confirm that 503 Unavailable response is returned] *************************************
fatal: [nyc1-apiserver-1.example.com]: FAILED! => changed=false 
  connection: close
  content: ''
  content_length: '0'
  content_type: application/octet-stream
  cookies: {}
  cookies_string: ''
  date: Fri, 11 Sep 2020 18:35:08 GMT
  elapsed: 0
  msg: 'Status code was 200 and not [503]: OK (0 bytes)'
  redirected: false
  server: nginx
  status: 200
  url: http://nyc1-apiserver-1.example.com/api/v1/healthcheck

PLAY RECAP ***********************************************************************************
nyc1-apiserver-1.example.com : ok=2    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  

Pokud se server po opravě nezdaří správně, pak Ansible selže s chybou:

fsh$ ansible-playbook -i inventory.ini playbook-healthcheck.yml

PLAY [all] ***********************************************************************************

TASK [Gathering Facts] ***********************************************************************
ok: [nyc1-apiserver-1.example.com]

TASK [Run maintenance start script] **********************************************************
changed: [nyc1-apiserver-1.example.com]

TASK [Confirm that 503 Unavailable response is returned] *************************************
ok: [nyc1-apiserver-1.example.com]

TASK [Update application] ********************************************************************
changed: [nyc1-apiserver-1.example.com]

TASK [Run maintenance end script] ************************************************************
changed: [nyc1-apiserver-1.example.com]

TASK [Confirm that 200 OK response is returned] **********************************************
fatal: [nyc1-apiserver-1.example.com]: FAILED! => changed=false 
  connection: close
  content: |-
    <html>
    <head><title>503 Service Temporarily Unavailable</title></head>
    <body>
    <center><h1>503 Service Temporarily Unavailable</h1></center>
    <hr><center>nginx</center>
    </body>
    </html>
  content_length: '190'
  content_type: text/html; charset=utf-8
  date: Fri, 11 Sep 2020 18:55:01 GMT
  elapsed: 0
  msg: 'Status code was 503 and not [200]: HTTP Error 503: Service Temporarily Unavailable'
  redirected: false
  server: nginx
  status: 503
  url: http://nyc1-apiserver-1.example.com/api/v1/healthcheck

PLAY RECAP ***********************************************************************************
nyc1-apiserver-1.example.com : ok=5    changed=3    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

Jedná se o jednoduché kontroly, které lze zabudovat do téměř každé příručky, aby byly přidány lepší záruky bezpečnosti před provedením rušivé práce nebo aby bylo zajištěno, že rušivá práce byla úspěšná předtím, než ji lze označit za úspěšnou.

Analýza vrátila JSON

Předchozí příklad funguje skvěle pro jednoduché kontroly stavu založené na HTTP. Obvykle však budete chtít načíst některá data z webového koncového bodu a poté s vrácenými daty něco udělat. Například:Co když chci zkontrolovat verzi aplikace prostřednictvím vystaveného koncového bodu a provádět aktualizace pouze v případě, že není aktuální?

Moje demo aplikace má právě takový koncový bod. Při dotazu vrátí aktuální verzi aplikace:

fsh$ http nyc1-apiserver-1.example.com/api/v1/appVersion
HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: keep-alive
Content-Length: 24
Content-Type: application/json
Date: Fri, 11 Sep 2020 18:36:15 GMT
ETag: "5f5bc33b-18"
Last-Modified: Fri, 11 Sep 2020 18:34:35 GMT
Server: nginx

{
    "appVersion": "1.0.1"
}

Poznámka :Zajímá vás ten HTTP příkaz, který jsem spustil? Podívejte se na článek mého sudoera Jonathana Roemera o HTTPie.

Vrácený JSON z tohoto koncového bodu mohu použít k rozhodování ve své příručce Ansible. Předchozí verze této příručky by vždy spouštěla ​​skript aktualizace aplikace. Mohu to však zlepšit tak, že aplikaci aktualizuji pouze tehdy, když nesplňuje mé požadované požadavky na verzi:


---

- hosts: all
  vars:
    desired_app_version: "1.0.1"
  tasks:

    - name: Check API version
      uri:
        url: "http://{{ ansible_host }}/api/v1/appVersion"
      register: api_version_result

    - name: Perform maintenance tasks
      block:
        - name: Run maintenance start script
          command:
            cmd: /usr/local/sbin/start_maintenance.sh

        - name: Confirm that 503 Unavailable response is returned
          uri:
            url: "http://{{ ansible_host }}/api/v1/healthcheck"
            status_code: 503

        - name: Update application
          command:
            cmd: /usr/local/sbin/update_app.sh

        - name: Run maintenance end script
          command:
            cmd: /usr/local/sbin/end_maintenance.sh

        - name: Confirm that 200 OK response is returned
          uri:
            url: "http://{{ ansible_host }}/api/v1/healthcheck"
            status_code: 200

        - name: Check API version after updates
          uri:
            url: "http://{{ ansible_host }}/api/v1/appVersion"
          register: updated_api_version_result
          failed_when: updated_api_version_result['json']['appVersion'] != desired_app_version
      when: api_version_result['json']['appVersion'] != desired_app_version

Tato příručka představuje několik užitečných konceptů Ansible. Nejprve můžete vidět, že modul URI zasahuje do /api/v1/appVersion Koncový bod API a registruje výstup tohoto volání URI do proměnné. Aktualizační úlohy byly přesunuty do bloku, který umožňuje logické seskupování úloh. Přidání kdy klauzule způsobí, že se tento blok spustí pouze v případě, že se aktuální verze aplikace liší od požadované verze aplikace, jak ji vrací /api/v1/appVersion koncový bod. Nakonec jsem do procesu aktualizace přidal další kontrolu. Jakmile budou aktualizace spuštěny, další volání /api/v1/appVersion koncový bod zajišťuje, že aktualizace proběhla úspěšně a že aktuální verze aplikace odpovídá požadované verzi. Používá syntaxi failed_when, která vám umožňuje definovat konkrétní kritéria selhání pro úlohy.

Tato bloková logika Ansible, vyjádřená srozumitelným jazykem, říká:„Spouštějte skripty údržby a instalace aplikace pouze v případě, že aktuální verze aplikace nesplňuje požadovanou verzi aplikace. Po dokončení aktualizace se ujistěte, že byla aplikace skutečně aktualizována.“

Pomocí pouhých několika řádků kódu Ansible jsem napsal výkonný, ale jednoduchý způsob, jak používat JSON vrácený z koncového bodu API k inteligentnímu rozhodování v mých příručkách.

Interakce s ověřeným koncovým bodem

Doposud jsem se zabýval interakcí s koncovými body API, které nevyžadují ověření. Pravděpodobně jste však nejvíce zvyklí na interakci s rozhraními API, která vyžadují určitý typ ověřování, jako je token rozhraní API. Modul URI to podporuje nastavením záhlaví a těla požadavku HTTP.

[ Mohlo by se vám také líbit:9 Ansible průvodců, které vám pomohou usnadnit automatizaci ]

Svou příručku údržby mohu posunout o krok dále tím, že deaktivuji a znovu povolím upozornění na každého hostitele v mém monitorovacím systému. To vyžaduje odeslání POST požadavek na koncový bod API na monitorovacím serveru. Požadavek musí obsahovat můj token API a hostitele v těle zakódovaném JSON. Ansible to zjednodušuje. Zde je konečná příručka:

---

- hosts: all
  vars:
    desired_app_version: "1.0.1"
    api_token: "8897e9a6-b10c-42c8-83a2-c83e9c8b6703"
  tasks:

    - name: Check API version
      uri:
        url: "http://{{ ansible_host }}/api/v1/appVersion"
      register: api_version_result

    - name: Perform maintenance tasks
      block:
        - name: Disable host in monitoring
          uri:
            url: "http://nyc1-monitoring-1.example.com/api/v1/startMaintenance"
            method: POST
            headers:
              X-API-KEY: "{{ api_token }}"
            body_format: json
            body:
              host: "{{ ansible_host }}"

        - name: Run maintenance start script
          command:
            cmd: /usr/local/sbin/start_maintenance.sh

        - name: Confirm that 503 Unavailable response is returned
          uri:
            url: "http://{{ ansible_host }}/api/v1/healthcheck"
            status_code: 503

        - name: Update application
          command:
            cmd: /usr/local/sbin/update_app.sh

        - name: Run maintenance end script
          command:
            cmd: /usr/local/sbin/end_maintenance.sh

        - name: Confirm that 200 OK response is returned
          uri:
            url: "http://{{ ansible_host }}/api/v1/healthcheck"
            status_code: 200

        - name: Check API version after updates
          uri:
            url: "http://{{ ansible_host }}/api/v1/appVersion"
          register: updated_api_version_result
          failed_when: updated_api_version_result['json']['appVersion'] != desired_app_version

        - name: Re-enable host in monitoring
          uri:
            url: "http://nyc1-monitoring-1.example.com/api/v1/stopMaintenance"
            method: POST
            headers:
              X-API-KEY: "{{ api_token }}"
            body_format: json
            body:
              host: "{{ ansible_host }}"

      when: api_version_result['json']['appVersion'] != desired_app_version

Nyní používám modul URI k odesílání POST HTTP požadavky (místo výchozího GET požadavky) do /api/v1/startMaintenance a /api/v1/stopMaintenance koncové body na nyc1-monitoring-1.example.com . Tyto požadavky obsahují můj token API pro monitorovací server v záhlaví a název hostitele serveru je součástí těla. Pokud kterýkoli požadavek selže s jiným než 200 stavový kód, pak selže celý Ansible playbook.

Poznámka :V praxi budete chtít použít něco jako Ansible Vault k uložení tokenu API namísto umístění přímo do playbooku.

Tato poslední sada úkolů mi umožňuje zcela automatizovat můj pracovní postup upgradu:Provádění kontrol verzí, interakce s externím monitorováním za účelem deaktivace výstrah pro systém a zajištění, že server vrátí správné stavové kódy HTTP před a po opravě. Nyní mám kompletní pracovní postup, který automatizuje mnoho běžných kroků, které dodržuji při provádění upgradů systému.

[ Potřebujete více o Ansible? Absolvujte bezplatný kurz technického přehledu od společnosti Red Hat. Ansible Essentials:Jednoduchost v technickém přehledu automatizace. ] 

Zabalení

Tento článek začínal jednoduchou příručkou, která prováděla základní webové kontroly proti neověřeným koncovým bodům API. Provedl jsem vás analýzou odpovědí JSON a dokonce i interakcí s ověřenými koncovými body API nastavením vlastních záhlaví a obsahu těla u požadavků HTTP. Ansible usnadňuje interakci s webovými službami a jsem si jistý, že pro tento typ přístupu najdete využití, a to i v jednoduchých prostředích.

Pokud se chcete dozvědět více a chcete se postavit čelem, zde je několik nápadů, které můžete sami implementovat:

  • K interakci s vaší oblíbenou webovou službou založenou na rozhraní API použijte modul URI.
  • Podívejte se, zda dokážete zjistit, jak provést ověření pomocí klientských certifikátů.
  • Zjistěte, jak odeslat formulář na web pomocí Ansible.

Linux
  1. Použití Wget s FTP ke stahování/přesouvání webových stránek rekurzivně

  2. Obnovuji své vzrušení z práce s Ansible

  3. Nastavte režim vynucení SELinux pomocí Ansible

  1. Víceprůchodové virtuální stroje pomocí Ansible

  2. Jak vytvořit uživatele Linuxu pomocí Ansible

  3. Používáte Notify-Send s Cronem?

  1. Kontrola stavu webové stránky pomocí Curl?

  2. Jak provádět čichání paketů pomocí Libpcap s ukázkovým kódem C

  3. Příklad použití getnstimeofday v jádře Linuxu