Seite wählen

NETWAYS Blog

Ansible – AWX|Tower State handling on Workflows

The Ansible Tower or its upstream AWX provides an easy to use GUI to handle Ansible tasks and schedules. Playbooks are configured as templates and as the name suggests, they can be modified to the needs, extended by variables, a survey or tags.

Furthermore those templates can be logically grouped, connected and visualised in Workflows.

The downside to those Workflows, all playbooks affected by this are executed separately and can’t access each others variables. On first glance we maybe only spot that we can define variables for the whole workflow but those are not changeable throughout the flow.

But there is a solution, which is the module set_stats. This module allows to save or accumulate variables and make them available for other playbooks within the workflow.

As an example we could use the monitoring environment when setting downtimes.

workflow

As a downtime is created before a maintenance and should be gone when the maintenance is done. This creates a dependency on the first task, which can be solved as we save the result of the first tasks with the set_stats module.


      - name: schedule downtimes
        icinga2_downtimes:
          state: "{{ downtime_icinga_state | default('present') }}"
          host: ***
          author: "{{ icinga2_downtimes_author | default('ansible_downtime') }}"
          comment: "{{ icinga2_downtimes_comment | default('Downtime scheduled by Ansible') }}"
          duration: "{{ icinga2_downtimes_duration | default(omit) }}"
        register: content
 
      - set_stats:
          data:
            downtime: "{{ content }}"

The content of the data will be now available to all playbooks included by the workflow. The variable is also shown as artefacts in the GUI.

artefacts

Keep in mind that the variable will be part of the extra variables for all other playbooks. As covered in the variable precedence it will overwrite any other variable named the same.

With this module you can reorganise your playbooks and connect them in workflows. This allows you to have a more flexible automation than before.

Check out our Blog for more awesome posts and if you need help with Ansible send us a message or sign up for one of our trainings!

Thilo Wening
Thilo Wening
Consultant

Thilo hat bei NETWAYS mit der Ausbildung zum Fachinformatiker, Schwerpunkt Systemadministration begonnen und unterstützt nun nach erfolgreich bestandener Prüfung tatkräftig die Kollegen im Consulting. In seiner Freizeit ist er athletisch in der Senkrechten unterwegs und stählt seine Muskeln beim Bouldern. Als richtiger Profi macht er das natürlich am liebsten in der Natur und geht nur noch in Ausnahmefällen in die Kletterhalle.

Kubernetes: Mehrere Cluster mit kubectl

Während man mit Kubernetes arbeitet oder entwickelt, wird man in den seltensten Fällen alles auf einem Cluster machen. Ob man ein lokales Minikube verwendet, oder Zugriff auf verschiedene Cluster für Produktion und Testing hat, muss man die Daten ja verwalten, und auswählen in welchem Kontext man gerade arbeitet.

Struktur der Konfiguration

Die Konfiguration für kubectl und andere Kubernetes Clients findet man normalerweise in $HOME/.kube/config. Ich möchte hier ein paar Beispiele zeigen, wie man hier neue Cluster hinzufügen kann. Der Inhalt sieht im einfachsten Fall so aus. Hier sind die Daten bzw. Secrets abgekürzt.

apiVersion: v1
kind: Config
current-context: my-cluster
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://my-cluster:6443
  name: my-cluster
contexts:
- context:
    cluster: my-cluster
    user: admin
  name: my-cluster
users:
- name: admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

Hier sind nun folgende Bereiche wichtig:

  • clusters definiert die bekannten Cluster mit API Endpunkt (URL) und dem passenden CA Zertifikat
  • users definiert Zugangsdaten und Authentifizierungsmechanismen, meistens ein Client Zertifikat, Auth-Tokens oder SSO Daten
  • contexts verbindet Cluster und Authentifizierung, und erlaubt auch das setzen des Namespaces
  • current-context zeigt an welcher Context gerade benutzt wird

Die aktuell verwendete Konfiguration kann man sich bequem anzeigen lassen, und dabei werden dann auch die Detaildaten zensiert – wie oben.

kubectl config view

Andere Konfigurations Dateien

Viele Kubernetes Anbieter stellen direkt die fertige Konfigurationsdatei zur Verfügung, die speichert man entweder direkt unter $HOME/.kube/config oder spezifiziert diese explizit.

kubectl --kubeconfig /tmp/my-config config view

export KUBECONFIG=/tmp/my-config
kubectl config view

Dabei wird nun diese Datei alleine geladen und ist direkt benutzbar. KUBECONFIG gilt dann für alle weiteren Befehle in der Shell auch.

Verbinden der Konfiguration

Um mehrere Dateien zusammenzuführen kann man nun auch mehrere Dateien laden, und so zusammenführen.

cp ~/.kube/config ~/.kube/config.bak
KUBECONFIG=~/.kube/config.bak:/tmp/my-config kubectl config view --raw >~/.kube/config

Bitte unbedingt die Datei vor dem speichern prüfen, doppelte Namen können zu Fehlern führen und der Context wird dann neu gesetzt.

Für kleinere Korrekturen kann man dann auch problemlos die Datei nachträglich von Hand editieren.

Tools und Shell Erweiterungen

Ich nutze gerne die Tools kubectx und kubens um schnell zwischen verschiedenen Kontexten umschalten zu können, bzw. zu sehen mit was ich gerade arbeite. Dazu gibt es auch die praktische Auto-Vervollständigung für die Shell.

Welchen Kontext bzw. Namespace ich gerade nutze, zeigt mir außerdem mein Bash Prompt auch an. Hier am Beispiel von powerline-shell mit meinen Modifikationen.

Es existieren auch einfachere Möglichkeiten, wie die kube-ps1 von jonmosco auf GitHub.

Mehr Infos

Wir bereiten gerade unsere neue Kubernetes Quick Start Schulung vor um den Teilnehmern einen schnellen Einstieg in die Benutzung von Kubernetes zu bringen. Wenn du Interesse hast mehr mit uns in Kubernetes einzusteigen, schau doch mal nach den Terminen.

Das Headerbild stammt von Loik Marras via unsplash.

Markus Frosch
Markus Frosch
Principal Consultant

Markus arbeitet bei NETWAYS als Principal Consultant und unterstützt Kunden bei der Implementierung von Nagios, Icinga und anderen Open Source Systems Management Tools. Neben seiner beruflichen Tätigkeit ist Markus aktiver Mitarbeiter im Debian Projekt.

Von Fackeln, elektrischen Schafen und Datenpunkten

Hallo und Willkommen im Jahr 2021! sheep

Damit sind wir offiziell 2 Jahre nach dem originalen Zeitablauf von Blade Runner welcher 2019 spielt.
Hmm, nirgends sind Nexus 6 Modelle die Rumlaufen und von elektrischen Schafen träumen.
(Auch keine Flugautos) *seufz*. Egal !!

Kommen wir zu dem eigentlichen Thema diese Woche.
Ich würde euch gern im neuen Jahr kurz erklären wie ihr mit einfachen Bordmitteln & wenig Aufwand aus den den meisten APIs Prometheus Daten exportiert ohne Zusatzsoftware zu installieren.

Explainer!! Was macht man mit den Fackeln https://prometheus.io/ ist eine Software welche mit ihrer eigenen Time Series Database auch Graphen Zeichnen kann und einen ziemlichen Erfolg hat, https://prometheus.io/docs/prometheus/latest/storage/ wenn man allerdings aus seiner Allerweltsapplikation Daten nach Prometheus exportieren will ist man leicht Aufgeschmissen. Viele Anbieter verkaufen teuer Plugins welche dies für Software tun oder es gibt halt keine Schnittstelle.

Ich versuche in meinem Beispiel aufzuzeigen wie man sich selbst einen Prometheus Output baut und ihn mit dem Prometheus node_exporter zu der Haupt Prometheus Instanz bringt.

Was brauchen wir an Software dafür machen wir einen kleinen Einkaufszettel 🙂

Die Zutaten:
1x Software welche eine API zur verfügung stellt – als Beispiel nehmen wir Icinga 2 kann aber eine Software eurer Wahl sein
1x Prometheus node_exporter (muss man leider zusätzlich installieren)
1x crontab – bringt hoffentlich eure Linux Distro von Haus aus mit
1x curl – hoffentlich auch schon von “Werk” ab mit an Bord
1x awk – same here auch hoffentlich schon mit an Bord
1x jq – Okay .. ich geb zu das muss man nachinstallieren (ich versuche mich gerade unter dem Schreibtisch zu verstecken)
https://stedolan.github.io/jq/download/

Nun wo wir die Zutaten kennen kommen wir zu dem eigentlichen Rezept.
*/1 * * * * curl -k -s -u 'user:password' https://localhost:5665/v1/status | jq '.results[1].status.active_host_checks_1min' | awk {'print "node_icinga2_active_checks1m""{" "active=" "\"" "/checks1m" "\"" "}" " "$1'} > /var/lib/node_exporter/textfile_collector/active_checks.prom.$$ && mv /var/lib/node_exporter/textfile_collector/active_checks.prom.$$ /var/lib/node_exporter/textfile_collector/active_checks.prom

Was habe Ich da in der Zeile über dieser eigentlich verbrochen?
Dröseln wir das doch auf, Schritt für Schritt.

Step 1:
*/1 * * * * curl -k -s -u 'user:password' https://localhost:5665/v1/status
Ich gehe im Crontab jede Minute her und greife mir aus der lokalen icinga 2 Instanz per Api den Status per JSON.

Step 2:
| jq '.results[1].status.active_host_checks_1min'
Dann gebe ich den JSON Output an jq weiter. Dies lass ich auf einen Wert aus dem JSON parsen. Idealerweise ein Zahlenwert welchen einen schönen Datenpunkt abgibt.

Step 3:
| awk {'print "node_icinga2_active_checks1m""{" "active=" "\"" "/checks1m" "\"" "}" " "$1'}
Dies reicht leider für Prometheus nicht aus wir müssen das etwas aufbereiten das Prometheus das auch als Datenquelle akzeptiert. Der Inhalt eines .prom Files muss in folgenderweise Formatiert sein. Hier kommt awk für die Aufbereitung ins Spiel.

Was nach dem awk Befehl rauskommt sieht formatiert ungefähr so aus node_icinga2_active_checks1m{active="/checks1m"} 607.

Ich hab mal aus Beschreibungsgründen den vorderen Teil node_icinga2_active_checks1m genannt. Könnte aber auch node_raspberrypi15_active_tempsensor30s sein. Danach folgt {active="/checks1m"} 607 welches nochmal auf den Key=Value + Wert Part hinweist. Ich bin aber ehrlich hier schwimme ich selbst etwas. Wenn mir jemand hier Aufschlüsseln kann was hier “Notwendig” ist wäre ich sehr Dankbar.

Step 4:
> /var/lib/node_exporter/textfile_collector/active_checks.prom.$$ && mv /var/lib/node_exporter/textfile_collector/active_checks.prom.$$ /var/lib/node_exporter/textfile_collector/active_checks.prom
Danach wird der von awk aufbereitete String in eine active_checks.prom Datei geschrieben.

Damit haben wir ein valides Prometheus File welches wir dem node_exporter (Prometheus) übergeben können.
Was hat es nun mit /var/lib/node_exporter/textfile_collector/active_checks.prom auf sich .. Der oben in der Zutatenliste erwähnte Prometheus node_exporter ist im Grunde die Datenschleuder welche konfiguriert, in einem selbst definierten Intervall (scrape_intervall) die active_checks.prom Datei in Richtung Prometheus Hauptinstanz wirft. Die dann wiederum die Werte in ihre Time Series Database einträgt und den Graphen zeichnet.

Da der Prometheus node_exporter selbst unterschiedliche Möglichkeiten hat Daten entgegenzunehmen, wir aber in "textform" Daten ihm liefern legen wir die .prom Datei unter dem Pfad /var/lib/node_exporter/textfile_collector/ ab.

Damit der node_exporter weiß wann er in welchem Intervall die von uns Aufbereiteten Daten an das Haupt Prometheus übergeben soll.
Muss Konfig ihm sagen wann (kurzer Abriss der /etc/prometheus/prometheus.yml)
...
## Add Node Exporter
- job_name: 'icinga2'
   scrape_interval: 60s
   static_configs:
      - targets: ['x.x.x.x:9100'] <= Adresse der Haupt Prometheus Instanz welche in dem Screenshot unten uns dann einen Graphen zeichnet.

Im Prometheus (Hauptinstanz) haben wir dann so einen Graphen wie im Screenshot unten, dies kann man auch noch schöner in Grafana zeichnen lassen sprich wenn man in seiner Software ein Grafana Fenster eingebunden hat kann man diese Graphen da hinein verlinken.

Ich hoffe ich konnte euch etwas den Einstieg in das neue Jahr verschönern mit meinem Versuch euch einen Prometheus Datenexport nahe zubringen und ich freue mich über euer Feedback.
Servus bis zum nächsten Mal !

David

David Okon
David Okon
Support Engineer

Weltenbummler David hat aus Berlin fast den direkten Weg zu uns nach Nürnberg genommen. Bevor er hier anheuerte, gab es einen kleinen Schlenker nach Irland, England, Frankreich und in die Niederlande. Alles nur, damit er sein Know How als IHK Geprüfter DOSenöffner so sehr vertiefen konnte, dass er vom Apple Consultant den Sprung in unser Professional Services-Team wagen konnte. Er ist stolzer Papa eines Sohnemanns und bei uns mit der Mission unterwegs, unsere Kunden zu...

Kommende Icinga Web-Funktion: Rememberme

Wir freuen uns immer über Feedback von euch, um Icinga noch besser zu machen. Viele Icinga-Benutzer haben die Meinung geäußert, dass sie gerne eine Rememberme-Checkbox auf der Login-Seite von Icinga Web hätten, damit sie sich nicht jedes Mal anmelden müssen, wenn sie Icinga Web besuchen.
Wir haben an diesem neuen Feature speziell während des Home-Office gearbeitet und planen, es in der nächsten Version von Icinga Web zu veröffentlichen.

Hier sind einige Schritte, wie dies funktioniert:

  • Wir führen ein neues “remember me” Cookie und ein “Stay logged in” checkbox auf der Login Seite ein.
  • Alle sensiblen Benutzerinformationen werden mit einem RSA-Schlüsselpaar verschlüsselt.
  • Das Cookie läuft nach 30 Tagen ab.
  • Die Erneuerung erfolgt automatisch nach einer erfolgreichen “remember me” Authentifizierung und beinhaltet die Neuerstellung des RSA-Schlüsselpaares und des Cookies mit 30 Tagen Ablaufdatum.
  • Die Authentifizierung über das “remember me” Cookie löst unseren normalen Authentifizierungsprozess aus, d. h. die Anmeldung mit dem Benutzernamen und dem Kennwort und die Erstellung eines neuen Sitzungs-Cookies bei erfolgreicher Authentifizierung.
  • Das Cookie wird gelöscht, wenn die Authentifizierung fehlschlägt oder ein Logout ausgelöst wird.

Um die Geheimnisse des Benutzers sicher zu speichern, erzeugen wir auf der Serverseite ein RSA-Schlüsselpaar bei der Erstellung des “remember me” Cookies. Das Schlüsselpaar wird in unserer Web-Datenbank gespeichert. Der Inhalt des Cookies sieht wie folgt aus:

  • Öffentlicher Schlüssel
  • Benutzername und Kennwort, verschlüsselt mit dem öffentlichen Schlüssel

Damit ist der öffentliche Schlüssel unser gemeinsames Geheimnis. Bei der Authentifizierung über das “remember me” Cookie suchen wir den öffentlichen Schlüssel in unserer Datenbank, entschlüsseln die Geheimnisse mit dem privaten Schlüssel und lösen unsere normale Authentifizierung mit dem entschlüsselten Benutzernamen und Passwort aus.

Warum lösen wir die normale Authentifizierung aus?

Die normale Authentifizierung beinhaltet bereits die Überprüfung der Kombination aus Benutzernamen und Passwort. Auf diese Weise prüfen wir, ob der Benutzer existiert oder das Passwort geändert wurde.
Wenn das Cookie bereits existiert und der Benutzer die Seite besucht, entschlüsseln wir die Benutzergeheimnisse und versuchen, uns damit anzumelden. Das funktioniert genauso, als ob der Benutzer diese Informationen manuell eingegeben und auf Login geklickt hätte.

Du kannst die Entwicklung dieser Funktion auf Github verfolgen. Wenn Du einen anderen Vorschlag oder einen neuen Feature Vorschlag hast, den Du gerne sehen würdest, kannst Du gerne ein Issue auf Issue auf Github öffnen.

 

Sukhwinder Dhillon
Sukhwinder Dhillon
Junior Developer

Sukhwinder ist seit Januar 2020 bei NETWAYS und macht bei uns seine Ausbildung als Fachinformatiker für Anwendungsentwicklung. In seiner Freizeit fährt er gerne Fahrrad, trifft sich mit Freunden, oder sitzt vorm Computer und lernt etwas Neues.

Ansible – Loop over multiple tasks

ansible logo

The last time I wrote about Ansible and the possibility to use blocks to group multiple tasks. Which you can read here. Sadly this feature does not work with loop, so there is no clean way to loop over multiple tasks in a play without writing the same loop statement at tasks over and over.

But when we come across the need of tasks which depend on each other, for example, we execute a script with a certain parameter and its result is necessary for the upcoming tasks.

Let’s go through a common example, creating a site consists of a few steps. Creating the directory, creating the vhost and then enabling the site.


- name: "create {{ site }} directory"
  file:
    ensure: directory
    dest: "/var/www/{{ site }}"
    
- name: "create {{ site }}"
  template:
    src: vhost.j2
    dest: "/etc/apache2/sites-available/{{ site }}"
  register: vhost

- name: "enable {{ site }}"
  command: /usr/sbin/a2ensite "{{ site }}"
  register: result
  when: vhost.changed
  changed_when: "'Enabling site' in result.stdout"
  notify: apache_reload

We could use a loop for each tasks and afterwards find the right result for the next task to depend on. But the styleguide will warn you if you try to use Jinja2 syntax in when statements.

So the best solution to this is to use include_tasks, which can include a file with tasks. This task is allowed to have a loop directive and so we can include it multiple times.
Lets see how this would apply to our scenario:


- set_fact:
    sites:
      - default
      - icingaweb2

- name: create vhosts
  include_tasks: create-vhosts.yml
  loop: "{{ sites }}"
  loop_control:
    loop_var: site


In the Result we can see clearly that all tasks are applied for each element in the sites variable.


TASK [set_fact] *********************************************
ok: [localhost]

TASK [create vhosts] ****************************************
included: /Users/twening/Documents/netways/ansible_test20/create-vhosts.yml for localhost => (item=default)
included: /Users/twening/Documents/netways/ansible_test20/create-vhosts.yml for localhost => (item=icingaweb2)

TASK [create default directory] *****************************
ok: [localhost]

TASK [create default] ***************************************
ok: [localhost]

TASK [enable default] ***************************************
ok: [localhost]

TASK [create icingaweb2 directory] **************************
ok: [localhost]

TASK [create icingaweb2] ************************************
ok: [localhost]

TASK [enable icingaweb2] ************************************
ok: [localhost]

PLAY RECAP **************************************************
localhost                  : ok=10   changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


Check out our Blog for more awesome posts and if you need help with Ansible send us a message or sign up for one of our trainings!

Thilo Wening
Thilo Wening
Consultant

Thilo hat bei NETWAYS mit der Ausbildung zum Fachinformatiker, Schwerpunkt Systemadministration begonnen und unterstützt nun nach erfolgreich bestandener Prüfung tatkräftig die Kollegen im Consulting. In seiner Freizeit ist er athletisch in der Senkrechten unterwegs und stählt seine Muskeln beim Bouldern. Als richtiger Profi macht er das natürlich am liebsten in der Natur und geht nur noch in Ausnahmefällen in die Kletterhalle.

Veranstaltungen

Di 18

Icinga 2 Fundamentals Training | Online

Mai 18 @ 09:00 - Mai 21 @ 17:00
Jun 15

stackconf online

Juni 15 - Juni 17
Jun 22

Ansible Fundamentals Training | Online

Juni 22 @ 09:00 - Juni 24 @ 17:00
Jun 22

Kubernetes Quick Start | Online

Juni 22 @ 09:00 - 17:00
Jun 25

Ansible AWX (Tower) Training | Online

Juni 25 @ 09:00 - 17:00