Cloud Orchestrierung von cloudscale.ch mittels Ansible

Wie im Blogpost “Puzzle modernisiert mit cloudscale.ch seine IT Infrastruktur” angekündigt, möchten wir es nicht unterlassen auf einige technologische Erneuerungen einzugehen, welche nicht zuletzt dank der Partnerschaft zwischen cloudscale.ch und Puzzle ITC in Ansible Version 2.8 eingeflossen sind.

Ausgangslage

Als wir uns im Team für cloudscale.ch als primärer Cloud Partner entschieden haben, bestand bereits eine gute Integration in Ansible: Das erste Cloudscale Modul für die Bereitstellung von Servern ist bereits seit Version 2.3 in Ansible vorhanden. Später kam die Unterstützung für das Managen von “Floating IPs” und Anfang dieses Jahres “Volumes” dazu.

Während des Aufbaus unserer Cloud Umgebungen kamen unsererseits Anregungen und Feature-Wünsche an die API hinzu, welche offen in Gesprächen mit cloudscale.ch geschärft werden konnten. Die Umsetzung durch cloudscale.ch brachte unter anderem neue oder erweiterte Schnittstellen (API Dokumentation von cloudscale.ch): So kam beispielsweise die neue “Server Groups” API-Ressource für das Handling der “Anti-Affinity” dazu; das bestehende Handling in des Server API wurde als veraltet markiert.

Ändern der Rechenleistung eines Servers

Eine weitere nennenswerte Erweiterung, auf welche wir nachfolgend näher eingehen, erhielt die Server Schnittstelle. Sie erlaubt nun nicht nur auf dem Webportal, sondern auch auf API-Ebene, die Rechenleistung, sprich das “Flavor”, zu ändern.

Um von dieser neuen Funktionalität zu profitieren, musste das zugehörige Ansible-Modul “cloudscale_server” mit einem Update-Mechanismus (PR #52683) versehen werden.

Da ein Wechsel des “Flavors” nur im gestoppten Zustand möglich ist, wurde die Integration so umgesetzt, dass auf gestoppten Servern das gewünschte “Flavor” sofort angewendet wird. Laufende Server wurden jedoch kurzfristig gestoppt und nach der Anpassung wieder gestartet.

Ein Stoppen und Starten eines Servers ist natürlich aus Betreibersicht nicht immer gewünscht und könnte zu einer Downtime eines Services führen oder gar ein SLA verletzen. Aus diesem Grund wurde zusätzlich der Parameter “force” eingeführt, womit man explizit angibt, ob man mit einem Restart des Servers grundsätzlich einverstanden wäre.

Natürlich kann dieser Wert nach gewohnter Ansible-Manier mit einer Variable versehen, in eine Ansible “Role” “defaulted” und in “host_vars” oder “group_vars” pro Server oder Servergruppe überschrieben werden.

Demo

Von einem einfachen Playbook ausgehend, zeigen wir das Verhalten in einem kurzen Screencast.

---
- hosts: localhost
  gather_facts: no
  vars:
    force: no
    flavor: flex-2
  tasks:
  - name: Provision webservers
    cloudscale_server:
      name: webserver-01
      image: debian-9
      flavor: ”{{ flavor }}”
      ssh_keys: ”{{ lookup('file', '~/.ssh/id_rsa.pub') }}”
      force: ”{{ force }}”

Die Kommandozeile bietet mit der Option --extra-vars die Möglichkeit, Variablen zum Zeitpunkt der Ausführung zu überschreiben. Wir zeigen nun, dass sich der Server nur nach Angabe von force=yes ändern lässt:

Gruppieren von Servern

Die Möglichkeit eine Anti-Affinity-Gruppierung zu erstellen, bestand bereits im Modul cloudscale_server.

Ein Manko dieser Schnittstelle war, dass die parallele Provisionierung mehrerer neuer Server in Anti-Affinität zueinander nur umständlich möglich war. Dies, weil mindestens ein Server bereits bestehen musste um dessen UUID für den neuen Server als Parameter anti_affinity_with übergeben zu können.

Ein Playbook veranschaulicht das Verhalten, bei dem zwei praktisch identische Tasks nötig waren:

---
- hosts: localhost
  gather_facts: no
  tasks:
  - name: start a server
    cloudscale_server:
      name: webserver-01
      image: debian-9
      flavor: flex-4
      ssh_keys: ”{{ lookup('file', '~/.ssh/id_rsa.pub') }}”
    register: server1

  - name: Start another server in anti-affinity to the first one
    cloudscale_server:
      name: webserver-02
      image: debian-9
      flavor: flex-4
      ssh_keys: ”{{ lookup('file', '~/.ssh/id_rsa.pub') }}”
      anti_affinity_with: ”{{ server1.uuid }}”

Diese Limitation wurde durch cloudscale.ch mit der neuen API für „Server Groups“ aufgebrochen.

Neu kann mittels Ansibles cloudscale_server_group eine Gruppe vom Typ “anti-affinity” erstellt und die neuen Server diese Gruppe zugeordnet werden:

---
- hosts: load-balancers
  gather_facts: no
  tasks:
    - name: Ensure load balancer are grouped in anti-affinity
      cloudscale_server_group:
        name: load-balancers
        type: anti-affinity
      run_once: yes

    - name: Ensure load balancer node exists
      cloudscale_server:
        name: ”{{ inventory_hostname }}”
        image: debian-9
        flavor: flex-4
        ssh_keys: ”{{ lookup('file', '~/.ssh/id_rsa.pub') }}”
        server_groups: load-balancers

Fazit

Wir konnten zwar nicht auf jedes neue Feature der Integration von cloudscale.ch in Ansible Version 2.8 eingehen. Anhand einiger Beispiele versuchten wir aber nicht zuletzt auch aufzuzeigen, dass eine Partnerschaft zweier IT-Firmen auch positive Auswirkungen auf Opensource-Projekte, wie in unserem Fall Ansible, haben kann.

Kommentare sind geschlossen.