Jedem seine eigene Teststage

Den ganzen Zoo auf einem Rechner

Stefan Hildebrandt / @hildebrandttk

Installation

Vorstellung

  • Was hat euch in diesen Workshop geführt?
  • Was sind eure Erwartungen?
  • Welche Erfahrungen habt ihr mit Linux, Virtualisierung und Provisionierung?

Vorgehen

  • Bitte arbeitet in Paaren
  • Nehmt die schnellere Hardware!
  • Teilt eure Ergebnisse über USB-Sticks oder git in einem Branch
  • Selbst entdecken: Es wird nicht alles vorgekaut:
    • dafür gibt es gibt viele Links zu den Handbüchern und einschlägigen Beispielen!
    • bei Problemen oder fehlenden Ideen früh fragen!

Vorgehen

  • Netzwerkresourcen sind beschränkt (UMTS)
    • nutzt die Proxies für http, ubuntu (transparent), maven und docker (später)
  • Beispiele und Folien bis zum aktuellen Stand werden über git bereitgestellt.
    • git url: gitolite@tutorialserver.hildebrandt.tk:tutorium/hc2014
      • in git-url.txt auf dem Stick
      • Snippet aus ssh-config auf dem Stick
      • Unter Windows: Key aus dem git/keys Ordner unter c:\Program File (x86)\Git\.ssh\id_rsa ablegen (ggf. dort liegenden Key sichern)

Motivation

Abweichende Betriebssysteme für

Entwicklung und Betrieb

Komplexe Systemlandschaften

Isolation von third-party-Systemen

"It works on my mashine"-Problem

Mehr Umgebungen

  • für Entwicklung
  • für Test
  • für Buildpipilines

Vagrant

  • Läuft unter Windows, Mac OS X und Linux
  • Verwaltet VMs mit unterschiedlichen Providern
  • Führt Änderungen mit unterschiedlichen Provisionern auf den VMs aus
  • Beschreibung der Aktionen im Quellcode - leicht versionierbar
  • Mehrere VMs in einer Beschreibung

Vagrant - Providers

  • VitualBox (Default)
  • VMware (kommerziel)
  • Docker
  • Hyper-V (kommerziel)
Hands-on

Unsere erste VM

Schritt 1: Generieren des Vagrantfile's

vagrant init

Der Anfang des Vagrantfiles

  • Ruby Code
    # -*- mode: ruby -*-
  • Die aktuelle Version 2 des APIs
    VAGRANTFILE_API_VERSION = "2"
  • Eine Box Namens Base
    config.vm.box = "base"

Schritt 2: Box besorgen

Box manuell importieren

vagrant box add --name base files/ubuntu-14.04-amd64-vbox.box

Download über URL

  • cmd
vagrant box add --name base\
   https://oss-binaries.phusionpassenger.com/vagrant/boxes/latest/ubuntu-14.04-amd64-vbox.box
  • Vagrantfile
config.vm.box_url =
   "https://oss-binaries.phusionpassenger.com/vagrant/boxes/latest/ubuntu-14.04-amd64-vbox.box"

Download aus der vagrant cloud

  • cmd
vagrant box add phusion/ubuntu-14.04-amd64
  • Vagrantfile
config.vm.box="phusion/ubuntu-14.04-amd64"

System installieren und starten

#vagrant up
vagrant ssh
uname -a
cat /etc/*release
cat /proc/cpuinfo
top
df

Daten

  • Benutzer vagrant, Passwort vagrant
  • Benutzer root, Passwort vagrant
  • Dateisystem ist größer angelegt (Autoextend in Virtual Box)
  • „.vagrant“ Verzeichnis neben dem Vagrantfile mit Metadaten zu VM

Steuern der VMs

  • vagrant up
  • vagrant provision
  • vagrant status
  • vagrant reload
  • vagrant destroy

VM Modding

Netzwerk

  • Portweiterleitung
    config.vm.network "forwarded_port", guest: 80, host: 8080
  • Weitere Netzwerkschnittstellen
    config.vm.network "public_network", bridge: 'eth0', ip: "192.168.42.1"

Verzeichnisse

  • Automatisch eingebunden:
    • <PROJEKTORDNER> auf /vagrant
    • Verzeichnisse für Provisionierungswerkzeuge
  • Weitere Verzeichnisse:
    config.vm.synced_folder "src/", "/srv/website"
  • Achtung: Auf Eigenschaften der Implementierung achten!

Provisioning

Provisioner

Shell Provisioner

  • Inline
    config.vm.provision "shell",
       inline: "echo hello"
  • Skript
    config.vm.provision "shell",
       path: "some_script.sh"
Hands-on

Installation von Java

  • Skript
  • Hinweise:
    • rpm liegt unter files
    • Konvertierung mit "alien --script"
    • Installation mit "dpkg -i"

Bash Hints

  • Abbruch bei einem Fehler
    set -e
    set -E
  • Funktionen verwenden
    function say {
       echo $1
    }
    say "Hello World"
    
  • Anleitung
Hands-on - Retro

Installation von Java

  • Wie war Euer Eindruck?
  • Was passiert bei wiederholter Ausführung?
  • Übertragungung auf andere Umgebungen

Puppet

Puppet

  • Das maven unter den Provisionierungstools
  • Puppet Master oder lokale Module
  • große Auswahl an fertigen Modulen
  • etwas angestaubt

Puppet Manifest

  • "node" als Klammer
  • Reihenfolge der Tasks undefiniert
    • Abhängigkeiten müssen explizit definiert werden!
node tutorialserver {
...
}

Puppet - Package

  • Installation von Paketen mittels Paketmanager
  • Abstraktion des konkreten Managers auf dem System
  • Abstraktion des konkreten Paketnamens möglich

Puppet - Package (repo)

package {
   "squid":
      ensure => installed;
}

Puppet - Package (lokal)

package {
 "oracle-xe":
   provider => "dpkg",
   ensure => latest,
   source => "/vagrant/etc/puppet/modules/oracle/files/oracle-xe_11.2.0-2_amd64.deb"
}

Puppet - Exec

  • Ausführen von Kommandos auf dem System
  • je nach System: Shell, Powershell, CMD
  • Voll qualifizierte Befehle notwendig!

Puppet - Exec

exec {
   "apt-update":
      command => "/usr/bin/apt-get -y update",
      timeout => 3600;
}

Puppet - File

  • Verzeichnisse
  • Dateien
  • Links
  • Mit Dateitransfer
  • Mit Templating

Puppet - File: Verzeichnis

file {
   '/var/lib/iptables':
      ensure => 'directory';
}

Puppet - File: Inhalt definieren

file {
   '/etc/apt/apt.conf.d/15update-stamp':
      mode    => '0644',
      owner   => 'root',
      group   => 'root',
      content => 'APT::Update::Post-Invoke-Success {\"touch /var/lib/apt/periodic/update-success-stamp 2>/dev/null || true\";};';
}

Puppet - File: Kopie

file {
   "/etc/profile.d/oracle-env.sh":
      source => "puppet:///modules/oracle/oracle-env.sh";
}
file {
   "/etc/profile.d/oracle-env.sh":
      source => "/vagrant/etc/oracle-env.sh";
}

Puppet - Abhängigkeiten

  • Liste von Abhängigkeiten
  • 1. Buchstabe des Typs immer groß
  • Listen nochmal mit [] versehen

Puppet - Abhängigkeiten

service {
   "apt-cacher-ng":
      ensure => "running",
      require => Package["apt-cacher-ng"];
   "squid3":
      ensure => "running",
      require => [Package["squid"], File ['/etc/squid3/squid.conf']];
}

Puppet Apply Provisioner

config.vm.provision "puppet" do |puppet|
   puppet.manifests_path = "manifests"
   puppet.manifest_file  = "base.pp"
end
Hands-on

Installation von Java mit Puppet

  • Installation von Java mittels eines Puppet Manifests
Hands-on - Retro

Installation von Java mit Puppet

Provisioning Hints

  • Versionierung
  • Touch and Check
exec {
   "update-bash_completion":
      command => "/bin/sed -i '\$acomplete -F _docker docker' \
            /etc/bash_completion.d/docker.io && touch /root/.puppet_update-bash_completion",
      unless => "/usr/bin/test -f /root/.puppet_update-bash_completion";
}

Puppet - Module

  • Bündelt wiederverwendbare Teile
  • Besteht aus Klassen

files
- Dateien für das Module (Siehe Files)
lib
- Funktionen, ... in Ruby
manifests
- init.pp
- ....pp
templates
- erb-Templates für Configfiles, ...

Puppet - Class

  • Klasse zur Kapselung und Adressierung aus den Node-Beschreibungen.

class oracle-jdk::install {
}

Puppet Apply Provisioner - Lokale Module

config.vm.provision "puppet" do |puppet|
   puppet.manifests_path = "manifests"
   puppet.manifest_file  = "base.pp"
   puppet.module_path = "modules"
end
Hands-on

Installation von Java mit selbst erstelltem puppet-Modul

  • Aufgabe wie vorhin
  • Verschieben in ein wiederverwendbares Modul
Hands-on - Retro

Installation von Java mit selbst erstelltem puppet-Modul

Puppet Forge

  • Austauschplattform für puppet Module
  • Einfache Installation von Modulen
    puppet module install <MODULE_NAME>
  • Zur lokalen Verwendung besser herunterladen und im SVM mit versionieren!

Übergabe von Parametern an Puppet-Klassen

class { 'artifactory':
   serverAlias => [ 'artifactory', 'tutorialserver.hildebrandt.tk' ]
}
Hands-on

Installation einer DB mit Puppet Forge

Hands-on - Retro

Installation einer DB mit Puppet Forge

Datenbankinhalt

Testdaten

  • Datenbankschema
  • Dumps
    • Bei Verwendung von Echtdaten an Obfuscating und Verschlüsselung denken!
    • Versionierte Dumps ablegen
    • pipes, zcat, openssl sind deine Freunde

Datenbankschema

  • Für Provisionierung und die Installation sollten alle Änderungen automatisiert eingespielt werden können.
  • Tipp: Die Schemaskripte unbedingt in die Tests einbeziehen!
  • Typische Werkzeuge:

Datenbankschema

  • Je Datei nur eine Transaktion --> jedes DDL-Statement in einer Datei
  • DATEIEN NICHT ÄNDERN! Ausnahmen:
    • Sie können nicht ausgeführt werden
    • Sie sind vollständig obsolet, dann können sie geleert werden

Petclinic

Hands-on

Befüllung der DB

  • Modul für flyway
  • Schema liegt unter javaee7-petclinic/db-dump.sql
Hands-on - Retro

Befüllung der DB

Hands-on

Wildfly

  • Installation von Wildfly in einer VM
    • puppet forge
    • Bei Problemen mit dem Portforwarding melden
Hands-on

Verwendung des Appservers aus einem gradle/maven-Build

  • Durch Portforwarding wird es ein normales Remotedeployment
  • user wildfly:wildfly muss vorhanden sein!
Hands-on - Retro

Verwendung des Appservers aus einem gradle/maven-Build

Hands-on

Verwendung des Appservers aus der IDE

  • Key für Transfer per ssh liegt unter $HOME/.vagrant.d/insecure_private_key
  • Portmapping für Debug-Port
  • Remotedebugging muss in /opt/wildfly/bin/standalone.conf aktiviert werden
Hands-on - Retro

Wildfly in der VM

Der Zoo

Mehrere VMs in einer Umgebung

Konfiguration von mehreren VMs

config.vm.define :database do |database|
   database.vm.hostname = "database"
end
  • Weitere Iterationsschicht
  • Kann spezielle Provider enthalten
  • Oder Unterscheidung in Puppet-Manifest oder ähnlichem

Netzwerke

database.vm.network "private_network", ip: "192.168.50.5"
  • Statische Definition
  • Weitere Parameter sind möglich
Hands-on

Mehrere VMs

  • "appserver" und "database" VM in einem Vagrantfile erstellen
  • "private network" zwischen beiden einrichten
  • Testen der Datenbankverbindung von appserver zu database
  • ggf. Verwendung der mysql-DB aus dem Wildfly
Hands-on

Mehrere VMs - Retro

VM einpacken

  • vagrant package
  • Verwendung einer beliebigen Box aus VirtualBox
    --base NAME
  • Name der erzeugten Box
    --output NAME
Hands-on

VM einpacken

  • VM mit DB versehen, flyway Installation durchführen und einpacken
  • Eingepackte box in vagrant als base-mit-mysql importieren
  • mysql-Beispiel auf diese Box umstellen
Hands-on - Retro

VM einpacken

docker

Was ist docker?

  • Toolset zur Erstellung, Verwaltung von Linux Containern (LXC)
  • Keine virtuelle Maschine!
    • Weniger Overhead auf Linuxrechnern
  • Ziel: Verbereitung von Anwendungen in einheitlicher Laufzeitumgebung
    • Der Linux-Kernel ist hier ausgenommen

Was ist docker?

  • LXC
  • Dateisystem in Schichten
  • Buildwerkzeug zur Erstellung von Images
  • Registry zur Verwaltung von Images

Docker: Wording

  • registry -> Server der Repositories und Images verwaltet
  • repository -> Ausführbares System
  • image -> layer eines Dateisystemimages

Docker auf Windows und OS X mit Vagrant

  • boot2docker
  • Ansonsten leeres Vagrantfile mit der Box: ubuntu-14.04-amd64-vbox-with-docker.box
  • vagrant ssh

Docker in diesem Tutorium

  • Nicht im Fokus dieses Tutoriums
    • Nur kurze Beispiele für einen ersten Eindruck
    • Fragen sind trotzdem willkommen!
  • Lokales Docker Repository
    docker run tutoriumserver.hildebrandt.tk:5000/registry-demo
Hands-on

VM einpacken

  • VM für Docker vorbereiten
  • VM mit vagrant boc einpacken
Hands-on

Docker: Hello World

  • docker run tutorialserver.hildebrandt.tk:5000/busybox echo "hello world"
Hands-on - Retro

Docker: Hello World

  • Was ist hier passiert?
    1. Image wurde geladen
    2. Image wurde lokal hinterlegt
    3. Befehl wurde im Image ausgeführt
Hands-on

Docker: Ausführen von Images

Hands-on - Retro

Docker: Ausführen von Images

Hands-on

Docker Images in vagrant VMs

Hands-on - Retro

Docker Images in vagrant VMs

Hands-on

Vagrant Docker Provider

Hands-on - Retro

Vagrant Docker Provider

Vagrant mit Docker

  • Schnell, meist nur sinnvoll wenn es auf allen Stages genutzt wird
  • Docker als Provisionier
    • Einfachere Variante als Puppet
    • Kann später weiter verwendet werden, wenn docker auch im Staging verwendet wird.
  • Docker als Provider
    • Scheint unnötig komplex!
    • Bietet ggf. Vorteile bei unterschiedlichen Betriebssystemen!?!
    • Bei mehreren Images besser fig nutzen

CI

  • Verwendung von mehren VMs in einem Build
  • On Demand Jenkins Slave in einem Multi VM Ansatz je Branch

Sicherheit - Vagrant

  • SSH-Key öffentlich!
  • Image aus unbekannter Quelle?
  • https://github.com/phusion/open-vagrant-boxes

Retro

Stefan Hildebrandt - consulting.hildebrandt.tk

  • Beratung, Coaching und Projektunterstützung
  • Java EE
  • Testautomatisierung
  • Coaching
  • DevOps
  • Certified Scum Master
Datenschutz Impressum