pixel
Select Page

NETWAYS Blog

Orchestration-Automation in einem Rutsch

Gerade für Testzwecke ist es von Vorteil, wenn man z.B. in der Cloud virtuelle Maschinen (VM’s) ohne großen Aufwand installieren und verwalten kann. Nur kommt noch die Installation von Programmen und Tools dazu, um die Testumgebung fertig zu bekommen, damit Test-Szenarien abgebildet werden können. Tools wie Terraform, Ansible oder Puppet und Bolt kommen da meistens zum Einsatz. Aber wie wäre es, wenn zum Beispiel sein Terraform-Deployment Verzeichnis  mit den .tf files schon vorhanden ist und nur alles in einem Rutsch ausrollen möchte. Da ich mich mit puppet-bolt schon mal auseinander gesetzt hatte, suchte ich nach einer Lösung und wurde fündig, denn Bolt kann terraform apply  ausführen, puppet-agent darauf installieren und der anschließend ein Puppet Manifest ausrollen. In meinem Kurz-Beispiel wird eine Ubuntu  VM erzeugt, Apache2 installiert und eine Webseite erstellt.

Wie das funktioniert erkläre ich in diesem Post:
Voraussetzung:
Terraform, puppet-agent und puppet-bolt müssen installiert sein.

Ich habe mir ein Verzeichnis angelegt z.B. terraform_puppet und in diesem sind folgende Dateien abgelegt:

├── bolt-project.yaml
├── data
│   └── common.yaml
├── files
│   └── site.html
├── hiera.yaml
├── inventory.yaml
├── manifests
├── plans
│   └── init.pp

Wichtig von den Dateien ist die bolt-project.yaml, die inventory.yaml und die init.pp, deren Inhalt sieht folgendermaßen aus:

bolt-project.yaml
---
name: terraform_puppet
modulepath: ~/puppet/modules

inventory.yaml
---
groups:
- name: terraform
targets: []
config:
transport: ssh
ssh:
private-key: ~/.ssh/passwordlesskey/id_rsa
user: ubuntu
host-key-check: false

Die ganze Magie passiert aber in dem Skript init.pp

plan terraform_puppet(String $tf_path) {
$localhost = get_targets('localhost')

# Create infrastructure with terraform apply
run_command("cd ${tf_path} && terraform apply --auto-approve && sleep 20", $localhost)
$ip_string = run_command("cd ${$tf_path} && terraform output instance_ips",
$localhost).map |$r| { $r['stdout'] }
$ips = Array($ip_string).map |$ip| { $ip.strip }

# Turn IPs into Bolt targets, and add to inventory
$targets = $ips.map |$ip| {
Target.new("${$ip}").add_to_group('terraform')
}

# Deploy website
apply_prep($targets, _run_as => 'root', _required_modules => ['apache'])

apply($targets, _run_as => 'root') {
include apache
file { '/var/www/html/index.html':
ensure => 'file',
source => 'puppet:///modules/terraform_puppet/site.html',
}
}
return $ips
# Or diagnose issues across your terraform infrastructure
run_command('uptime', $targets)
}

Ich habe das ganz bei uns im Openstack umgesetzt, es kann aber auch in anderen Cloud Umgebungen übernommen werden und muss diesbezüglich angepasst werden.

So um das ganze jetzt in Gang zu setzen führt man folgendes Kommando in diesem terraform_puppet Verzeichnis aus:

bolt plan run terraform_puppet -i inventory.yaml tf_path=~/terraform/vmdir

Für alle die, die Puppet und Ruby Wissen haben, sollte das selbsterklärend sein, ansonsten grobe kurze Erklärung:

Bolt führt ein Skript aus das ein Terraform apply triggert und die IP als Variable speichert und als inventory Host-Target zu den groups hinzufügt,
damit diese als $target Variable vom Bolt inventory und dann per puppet apply genutzt werden kann. Das puppet Module Apache wird dazwischen auch mit eingelesen und genutzt.
Das schöne ist, die Funktion von bolt apply_prep, diese sorgt dafür, das für das per terraform installierte VM-OS der puppet-agent installiert und ausgeführt werden kann, wenn man das ganze laufen lässt sieht man es als command durchlaufen.
Anschließend wird per bolt apply ein puppet code  per puppet apply ausgeführt, der in unserem Fall den Apache2 installiert und einen index.html an die entsprechende Stelle kopiert (die man vorher unter files selber anlegen muss) und dann den Apache2 Service startet.

Das Ergebnis sollte dann die Webseite der index.html sein , wenn man die IP-Adresse der VM im Browser (http://$ipaddress_vm eingibt.

Das ist natürlich nur ein ganz vereinfachtes Beispiel, aber die Möglichkeiten die man damit hat, finde ich genial.

Natürlich bieten wir zum Thema Puppet auch Trainings an, wo man die Grundlagen der Automatisierung mit Puppet vermittelt bekommt.

Viel Spaß und Erfolg beim Ausprobieren.

Johannes Carraro
Johannes Carraro
Senior Systems Engineer

Bevor Johannes bei NETWAYS anheuerte war er knapp drei Jahre als Systemadministrator in Ansbach tätig. Seit Februar 2016 verstärkt er nun unser Team Operations als Senior Systems Engineer. In seiner Freizeit spielt Johannes E-Gitarre, bastelt an Linux Systemen zuhause herum und ertüchtigt sich beim Tischtennisspielen im Verein, bzw. Mountainbiken, Inlinern und nicht zuletzt Skifahren.

Orchestration mit Puppet Bolt

Viele von den SysAdmins kennen das Tool mit dem A und deswegen möchte einen kleinen Einstieg zu Puppet Bolt geben.
Um Bolt nutzen zu können muss auf der Distribution seiner Wahl das Repository https://yum.puppet.com eingebunden sein und das Paket puppet-tools installiert sein. Zusätzlich brauchen wir für unseren kleinen Test das Paket docker und docker-compose, das auf dem System zu Verfügung stehen muss, da wir das die Aktionen auf Docker Containern deployen wollen.

Zuerst werden wir ein Bolt-Projekt Verzeichnis erstellen, wo dann das Modul-Verzeichnis darin erstellt wird:
mkdir my_infra && cd my_infra

Verzeichnis als bolt Arbeitsverzeichnis verifizieren:
bolt project init my_infra
In dem Verzeichnis befindet sich eine bolt-project.yaml womit Einstellungen für das Projekt vorgenommen werden können und eine inventory.yaml für zukünftige Hosts / Hostgruppen

Modul-Verzeichnis anlegen:
mkdir -p apache/plans && mkdir -p apache/files

So sollte die Struktur jetzt aussehen:
|── bolt-project.yaml
├── inventory.yaml
└── apache
├── files
└── plans

Jetzt erstellen wir den Container via Dockerfile, wo bolt später die Pakete installiert:
vim Dockerfile
FROM rastasheep/ubuntu-sshd
RUN apt-get update && apt-get -y install libssl-dev
EXPOSE 80
CMD ["/usr/sbin/sshd", "-D"]

kurze Erklärung: Hier wird ein Docker Container mit einem lauschenden SSH-Service unter Ubuntu erstellt, da Bolt auch über SSH kommuniziert

Dann erstellen wir die docker-compose.yaml, in dieser Datei wird festgelegt, wie viele Container erstellt werden und mit welchen Port diese von Außen erreichbar sind.
vim docker-compose.yaml
version: '3'
services:
target1:
build: .
ports:
- '3000:80'
- '2000:22'
container_name: webserver1
target2:
build: .
ports:
- '3001:80'
- '2001:22'
container_name: webserver2

Hier werden zwei Container erstellt auf dem der Port 22 auf 2000 und 2001 gebunden ist sowie der Port 80 auf 3000/3001.

Um die Container jetzt bauen zu lassen brauchen wir folgenden Befehl:
docker-compose up -d --build
Es werden jetzt Container-Images heruntergeladen und die beiden Container gebaut

Damit Bolt weiß wo das ganze dann angewendet werden soll, vervollständigen wir das inventory.yaml
vim inventory.yaml
groups:
- name: containers
targets:
- uri: 127.0.0.1:2000
name: webserver1
- uri: 127.0.0.1:2001
name: webserver2
config:
transport: ssh
ssh:
user: root
password: root
host-key-check: false

Um jetzt zu testen ob das Inventory File passt, prüft man mit folgendem Kommando:
bolt command run whoami -t all

Damit jetzt auf den Container Pakete installiert werden, müssen wir einen Task anlegen:
vim module/apache/plans/install.yaml
parameters:
targets:
type: TargetSpec

steps:
- name: install_apache
task: package
targets: $targets
parameters:
action: install
name: apache2
description: "Install Apache using the packages task"

Ich denke viel Erklärung braucht es hier nicht sollte selbsterklärend sein

Mit folgendem Kommando kann man den Plan ausführen um Apache auf dem Containern zu installieren:
bolt plan run apache::install -t containers

Das Ergebnis kann man sehen, wenn man im Browser http://127.0.0.1:3000 eingibt

Als keine Einführung in Puppet Bolt sollte das vorerst genügen, weiteres kann noch modifiziert und erweitert werden, siehe Quelle.

Quelle des Artikels: https://puppet.com/docs/bolt/latest/getting_started_with_bolt.html

Johannes Carraro
Johannes Carraro
Senior Systems Engineer

Bevor Johannes bei NETWAYS anheuerte war er knapp drei Jahre als Systemadministrator in Ansbach tätig. Seit Februar 2016 verstärkt er nun unser Team Operations als Senior Systems Engineer. In seiner Freizeit spielt Johannes E-Gitarre, bastelt an Linux Systemen zuhause herum und ertüchtigt sich beim Tischtennisspielen im Verein, bzw. Mountainbiken, Inlinern und nicht zuletzt Skifahren.

NETWAYS wird Puppet Authorized Reseller

Seit vielen Jahren unterstützt NETWAYS bereits erfolgreich Kunden bei der Konzeptionierung, dem Aufbau, der Erweiterung sowie der Migration von Puppet Umgebungen. Dabei lag der Schwerpunkt bislang auf der Open Source Variante, obwohl es im Puppet ENTERPRISE Segment viele interessante und hilfreiche Erweiterungen gibt, die wir im Rahmen der Dienstleistung nicht direkt anbieten konnten.

Diesen Zustand wollten wir ändern! Wir freuen wir uns, dass wir seit Kurzem offizieller Authorized Reseller von Puppet sind. Für unsere Kunden ändert sich an unseren bestehenden Leistungen dadurch nichts. Wir bieten weiterhin die professionellen Dienstleistungen im Open Source Bereich an, die sie von uns gewohnt sind. Der Vorteil dieser Partnerschaft ist eine Erweiterung unseres Portfolios. Anforderungen unserer Kunden können wir jetzt noch besser umsetzen, da wir nun in der Lage sind, ENTERPRISE Lizenzen selbst anzubieten und sämtliche Leistungen damit direkt von uns beziehbar sind.

Puppet als starker Partner

Für unsere Kunden ergibt sich aus dieser Partnerschaft zudem ein zusätzlicher deutlicher Vorteil: Neben den Open Source Themen können wir nun nicht nur die ENTERPRISE Lösungen anbieten, sondern auch mit Puppet und unseren Kunden gemeinsam in den Dialog treten können, um das Configuration Management passgenau beim Kunden zu installieren und zu konfigurieren.

Durch das breite Partner Netzwerk von Puppet können wir auf bisherige Erfahrungen von Puppet in ähnlichen Umgebungen zurückgreifen und mögliche Herausforderungen sowie Anforderungen frühzeitig identifizieren.

Nächster Halt: Solution Provider

Als nächster Schritt steht bei uns jetzt noch aus, dass wir Puppet Solution Provider werden. Damit ergibt sich für unsere Kunden noch eine Vielzahl an weiteren Vorteilen, da unsere Kollegen in diesem Fall offiziell von Puppet zertifiziert werden und somit auch ein Nachweis darüber vorhanden ist. Hierdurch können wir dann auch unser langjähriges Engagement und Know-How, das wir mit Puppet gesammelt haben, schriftlich unter Beweis stellen.

Habt Ihr Interesse an unseren Puppet Dienstleistungen oder Puppet ENTERPRISE? Dann nutzt doch einfach unser Kontaktformular und nehmt Kontakt mit uns auf! Wir freuen uns auf eure Anfragen!

Christian Stein
Christian Stein
Lead Account Manager

Christian kommt ursprünglich aus der Personalberatungsbranche, wo er aber schon immer auf den IT Bereich spezialisiert war. Bei NETWAYS arbeitet er als Senior Sales Engineer und berät unsere Kunden in der vertrieblichen Phase rund um das Thema Monitoring. Gemeinsam mit Georg hat er sich Mitte 2012 auch an unserem Hardware-Shop "vergangen".

Ansible – How to create reusable tasks

Ansible is known for its simplicity, lightweight footprint and flexibility to configure nearly any device in your infrastructure. Therefore it’s used in large scale environments shared between teams or departments. Often tasks could be used in multiple playbooks to combine update routines, setting downtimes at an API or update data at the central asset management.

To use external tasks in Ansible we use the include_task module. This module dynamically includes the tasks from the given file. When used in a specific plays we would assign play specific variables to avoid confusion. For example:


vim tasks/get_ldap_user.yml

- name: get user from ldap
  register: users
  community.general.ldap_search:
    bind_pw: "{{ myplay_ad_bind_pw }}"
    bind_dn: "{{ myplay_ad_bind_dn }}"
    server_uri: "{{ myplay_ad_server }}"
    dn: "{{ myplay_ad_user_dn }}"
    filter: "(&(ObjectClass=user)(objectCategory=person)(mail={{ myplay_usermail }}))"
    scope: children
    attrs:
      - cn
      - mail
      - memberOf
      - distinguishedName

If this task should be used in another playbook to reduce the amount of code or is used again with other conditions or values. Therefore the variables need to be overwritten or if it is another playbook the variables are named wrong.

The solve this problem change the variables to unused generic variables. And assign your own variables in the include_task statement.


vim tasks/get_ldap_user.yml

- name: get user from ldap
  register: users
  community.general.ldap_search:
    bind_pw: "{{ _ad_bind_pw }}"
    bind_dn: "{{ _ad_bind_dn }}"
    server_uri: "{{ _ad_server }}"
    dn: "{{ _ad_user_dn }}"
    filter: "(&(ObjectClass=user)(objectCategory=person)(mail={{ _ad_usermail }}))"
    scope: children
    attrs:
      - cn
      - mail
      - memberOf
      - distinguishedName

The include_task vars parameter provides own variables to the tasks.


vim plays/user_management.yml
[...]
- name: check if user exists in ldap
  include_tasks:
    file: tasks/get_ldap_user.yml
  vars: 
    _ad_bind_pw: "{{ play_ad_pw }}"
    _ad_bind_dn: "{{ play_ad_user }}"
    _ad_server: "{{ play_ad_server }}"
    _ad_user_dn: "OU=users,DC=example,DC=de"
    _ad_usermail: "{{ play_usermail }}"

This can be easily combined with loops, to enhance the reusability of your tasks even more! Checkout this blogpost about looping multiple tasks. Ansible – Loop over multiple tasks

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
Senior 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.

Neues vom Icinga-Installer

Mein letzter Blog Icinga Installation mit Director in 10 Minuten zeigte wie man mit dem Icinga-Installer und etwas Nacharbeit per Hand zu einem arbeitsfähigen Icinga-Server mit Director bekam.

Inzwischen ist eine neue Version 0.5.0 vom Icinga-Installer veröffentlicht, die einem auch komplett die Installation und Konfiguration des Directors inkl. Datenbank-Setup und erstem Kickstart-Lauf abnimmt.

Abschließend noch ein kleiner Tipp, wie unter zur Hilfenahme des Installers, die GUI des Icinga Webs ausschließlich per HTTPS ereichbar gemacht wird. Voraussetzung sind natürlich ein vorhandenes Zertifikat nebst privatem Schlüssel und das CA-zertifikat bzw. ein Chain-File. Diese müssen zuvor an den angegeben Orte im Dateisystem abgelegt werden. Die erforderlichen Einstellungen können nicht interaktiv vorgenommen werden, lassen sich aber in /etc/icinga-installer/custom-hiera.yaml (hier ein Beispiel für ein RedHat basiertes System) festlegen:


---
apache::default_vhost: false
apache::default_ssl_vhost: true
apache::default_ssl_cert: /etc/pki/tls/certs/apache.crt
apache::default_ssl_key: /etc/pki/tls/private/apache.key
apache::default_ssl_ca: /etc/pki/tls/certs/my-ca.crt

Möchte oder muss man eine CA-Chain angeben, lautet die Option apache::default_ssl_chain. Diese ersetzt die Zeile mit default_ssl_ca.

Lennart Betz
Lennart Betz
Senior Consultant

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.