Teile und Herrsche – Verteilte Java-Anwendungen mit Docker – 150 Mio. USD Risikokapital



Teile und Herrsche – Verteilte Java-Anwendungen mit Docker – 150 Mio. USD Risikokapital

0 0


docker-talk

A reveal.js based, introductional presentation talk about Docker & Java

On Github bentolor / docker-talk

Teile und Herrsche

Verteilte Java-Anwendungen mit Docker

Benjamin Schmid
Technology Advisor
Dr. Ralph Guderlei
Technology Advisor
? für Hilfe, S für Folien-Notizen
15. Juni 2015
Teile und Herrsche von Benjamin Schmid, Dr. Ralph Guderlei ist lizenziert unter einer Creative Commons-Lizenz (by-nc-sa). Beruht Reveal.JS.
Überall hört und liest man von "docker".

150 Mio. USD Risikokapital

Insgesamt **150 Mio. USD Risikokapital** konnte das Unternehmen an rund um die Open-Source Systemvirtualisierung einnehmen.
Alle Warenzeichen und Logos sind Eigentum ihrer jeweiligen Rechteinhaber.
Zu seinen Unterstützern gehört eine ganze Riege namhafter Unternehmen, wie z.B.: Red Hat, Google, Amazon um ein paar zu nennen. Selbst **Microsoft arbeitet inzwischen** mit Docker zusammen,, um die eigentlich auf Linux beheimatete Technologie auch auf Windows & Azure zu portieren!

Hype?

oder

»The next big thing«?

Ist das Docker nur ein Hype oder wirklich »the next big thing«? Dieser Frage möchten wir heute auf den Grund gehen! Hallo und Ein herzliches Willkommen zu unsere_ — mein Name ist '...'. Speaker 2: Mein Name ist Ralph Guderlei ... und gemeinsam wollen wir heute ein bisschen Licht auf das Schlagwort Docker werfen.

Jump into Docker: Live Demo

$ mvn -o package
$ java -jar target/rest-microservice-1.0.0.jar server
$ sensible-browser "http://localhost:8080/hello-world"
$ docker build -t my/microservice .

$ docker run -d --name web1 my/microservice
$ docker run -d --name web2 my/microservice
$ docker run -d --name web3 my/microservice

$ docker pull haproxy:1.5
$ docker run -d --name balancer \
	--link web1:web1 --link web2:web2 --link web3:web3 \
	-p 8080:80 \
	-v (pwd)/etc:/usr/local/etc/haproxy:ro \
	haproxy:1.5
$ sensible-browser "http://localhost:8080/hello-world"
						
Um die Faszination hinter Dockjer etwas plastischer zu gestalten, fangen wir am Besten doch einfach gleich mal mit einem kleinen Beispiel an. Starten wir doch mit einem Java-basierten Service. Wir haben da schon mal was vorbereitet, das bauen wir mal. Unser Beispiel ist ein kleiner Microservice auf Basis von Dropwizard. Zugegebenermassen: So richtig viel macht unser Service nicht. Trotzdem kann ja mal was schief gehen! Darum wollen wir mal zeigen, wie leicht wir mit Docker daraus ein High Availability Cluster bauen können! Im ersten schritt "Dockerizen" wir dazu unsere Anwendung. Wie das genau geht, schauen wir uns später noch im Detail an. Wir haben unsere Java-Anwendung nun als Docker-Container verpackt. Da wir Ausfallsicherheit haben wollen, starten wir einfach mal drei Instanzen davon. **Dabei müssen wir nichts umkonfigurieren, da diese drei Instanzen in isolierten Container laufen!** Um nun die Ausfallsicherheit zu realisieren, greifen wir auf einen fertigen Container für den Loadbalancer HAProxy zurück. Beim Start machen wir dieser nur noch unsere Konfiguriationsdatei und die drei gestarteten Container bekannt! Und schon haben wir unseren geclusterten "Hochverfügbarkeits"-Cluster deployed!
Und schon haben wir unseren geclusterten "Hochverfügbarkeits"-Cluster deployed! - Wir mussten nichts zusätzlich installieren - Schnell gestartet - Ohne unser Anwendung anpassen zu müssen - Portabel: Könnte so genaus auf Produktion gehen!

Inhaltsverzeichnis

Docker in a nutshell Hands on Docker Docker advanced Docker & Java Docker Distributed Hype vs. Potential

Docker in a nutshell

  • Isolierte Prozessausführung (Sandbox) auf Basis von »Linux Containers (LXC)«
  • Wesentlich effizienter als VMs/Hypervisoren
  • Portables Format für Container mit Versionierung
  • Leichtgewichtige Laufzeit- und Packaging-Tools
  • Cloud-Repository für Container-Vorlagen
**Build** Once, **Configure** Once and **Run Anywhere**

Grundlegende Begriffe

Image: Paketierte Zusammenstellung von Dateien. Damit eine schreibgeschützte Blaupause für eine Systemumgebung.

Container: Eine unabhängige Systemumgebung basierend auf einem Image

Repository: Ein Sammlung von Images auf dem lokalen Docker oder zentralen Registry Server

Docker Komponenten

- Auf der Host-Machine läuft ein Daemon. - Dieser verwaltet sowohl die laufenden Container, als auch die Images. - Der Daemon ist also Zuständig dafür, Container-Instanzen anzulegen, starten und zu stoppen - Über ein CLI Tool kann der Docker Dienst (remote) gesteuert werden. - Aus dem Cloud-Repository lassen sich Images abholen
- Container laufen dank **LXC & Namespaces** als voneinander **vollständig isolierte, aber sonst ganz normale Prozesse** auf dem Host-System. - Es handelt sich um keine vollständige Virtualisierung - Kernel und RAM wird mit dem Host geteilt - Nur die im Image gebundelten Dateien & Tools sind zugänglich (auch Dinge wie `ls`) - Isoliertes Container-Netzwerk - Container sieht nur eigene Prozesse - Durch diesen Ansatz ist alles **cheap**: Anlegen, Verwerfen, Starten, Stoppen

Erstellen von Images

1. **Manuell:** *Commit* eines Containers 2. **Automatisiert:** via `Dockerfile`

In der Regel: Automatisiert, aufbauend auf einem via `docker pull` bezogenem Base-Image

- Images lassen sich auf zwei Arten erstellen: - Commit eines Containers - Generiert via Dockerfile - in der Regel aber: Automatisierte Erstellung anhand des «Build-Files»: `Dockerfile`

Base Images

- [~100 offizielle Images](https://hub.docker.com/explore/) - 100.000+ Images insgesamt - 200+ Millionen Downloads
- drei Klassen: - Betriebsysteme - Laufzeitumgebungen (Java, Ruby) - Anwendungen (Datenbanken, Wordpress) - untrusted, Signatur-Infrastruktur im Aufbau

Images bauen: Dockerfile

FROM java:8
MAINTAINER Inspector Gadget

                            # Kommando im Container ausführen
RUN apt-get update && apt-get dist-upgrade -y &&  \
    apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

                            # JAR und Config-File in Image aufnehmen
WORKDIR /opt
ADD target/rest-microservice-1.0.0.jar app.jar
ADD src/main/resources/example.yml     app.yml

                            # announce exported port 8080 and 8081
EXPOSE 8080 8081
                            # Wichtig: Separate Volumes für Daten
VOLUME ["/srv/"]

                            # JAR ausführen beim Start des Containers
ENTRYPOINT java -jar app.jar server
							
Hier unser Eingangs präsentiertes Beispiel: - Zuerst mal starten wir von einem Base-Image - Mit `RUN` könenn wir Kommando _innerhalb_ des Containers ausführen - Dann fügen wir Dateien von ausserhalb in den Container hinzu: Hier unsere App-JAR und Konfigurationsdatei - `EXPOSE` und `ENTRYPOINT` sind Meta-Informationen die Beschreiben, wie der Container verwendet werden soll. Konkret: Welche Ports aus dem Container später zugänglich sein sollen und Was beim Container-Start ausführen. In der Regel 1 Prozess. - `VOLUME`: Betrachten wir später

Hands on Docker

#### Neues Image erstellen Auf Basis unseres `Dockerfile` erzeugen wir unser Image: ``` docker images docker build -t my/dockerapp:latest . docker images ``` Dabei sehen wir wie die Schritte einzeln abgearbeitet werden; bei jedem der Schritte entsteht ein neuer Layer. Mehr dazu später.
- Welche Images sind da? - `Dockerfile` -> Neues Image
#### Container erstellen & starten Nun starten einen neuen (anonynmen) Container auf Basis des Images: Einmal interaktiv, einmal als Daemon ``` docker run -it my/dockerapp [ctrl-c] docker run -d my/dockerapp ```
- Wir _legen_ neuen Container via `docker run` an - Das startet ihn auch gleich. - Dank `-it` interaktiv im Vordegrund
#### Container managen Nun schauen wir mal was so los ist. Wir die eingangs gestarteten Container laufen noch, welche wir erst mal unsanft killen. docker ps docker kill balancer web1 web2 web3 docker ps Regulär stoppt man Container aber höflich mit `docker stop`. Wieder starten über `docker start` … nicht ~~`docker run`~~ . docker stop name docker ps docker ps -as docker start name
- Wir schauen uns die laufenden Container an. - Wir stoppen wieder unseren Container: - `ps` zeigt ihn nicht mehr. - mit `ps -as` sehen wir auch die gestoppten. - Erneutes starten erfolgt dagegen via `docker start`. nicht ~~`docker run`~~ - **Achtung:** auch diese belegen Platz!
#### Diagnostik von Container Unsere Container laufen im Hintergrund. Wie kommen wir an Infos, wenn mal etwas nicht funktioniert? docker inspect name | grep IP sensible-browser "http://ip:8080/hello-world" docker logs name docker exec -it name /bin/bash
Unsere Container laufen. Wie bekommen wir Infos? 1. Auf unserem Container läuft ja eine Web-Anwendung auf Port 8080, die wollen wir mal ausprobieren. 2. Über `docker inspect` bekommt man jede Menge Infos. 3. Mit `docker logs` die Ausgaben. 4. Oder wir können mit `docker exec` einen Prozess im Kontext des Container starten Fazit: - `logs` zeigt uns die Konsolenausgaben - `exec` erlaubt in den Container einzutauchen; z.B. eine bash Shell, um sich umzuschauen

Docker advanced

- *Filesystem*, bestehend aus gestapelten *Layern* (union filesystem) - **Image** sind *schreibgeschützt* - *Union File System* vereint die verschiedenen Image Layers uns stellt auf oberster Ebene einen *schreibbaren Layer* bereit. Das ist dann ein **Container**. - Image = Layers + Meta-Informationen, Ports, Volumes, Start-Kommando - Dockerfile: Jeder Schritt erzeugt ein separaten Layer -> `docker history` - Layer-ID == Container/Image ID - Versionierung vergleichbar zu Git-Hash: `ac408c338`

Layers & Union File System

- Filesystem aus gestapelten **Layern** (Union File System) - **Images** sind schreibgeschützte Layers & Meta - Schreibbarer Layer dazu ➱ **Container**. - Dockerfile: Jeder Schritt = **neuer Layer** ➱ `docker history` - **Versionierung:** Layer-ID = Container/Image ID ➱ `ac408c338`

Data Volumes

Datenhaltung unabhängig vom Container-Lebenszyklus. Überlebt: Löschen & Updates. Erlaubt: Sharing.

Option 1: _Container Volumes_ docker create -v /mydata --name mydata java:8 /bin/true docker run -d --volumes-from mydata my/dockerapp Option 2: _Lokale Verzeichnisse_ docker run -v $(pwd)/etc:/usr/local/etc:ro haproxy:1.5
Data volumes are designed to persist data, independent of the container's life cycle. - Zustandslose Services trivial, wie sieht es mit Datenbanken aus? - Umgang mit persistenten Daten: Volumes - Beispiel: Update einer Datenbank, Daten sollen erhalten werden If you have some persistent data that you want to share between containers, or want to use from non-persistent containers. Let's create a new named container with a volume to share. It reuses the `java:8` image so that all containers are using layers in common, saving disk space.

Container verknüpfen

``` docker run -d --name web1 my/dockerapp docker run -d --link web1:web1 haproxy ```
_web1_ wird damit in _haproxy_ verfügbar via - Umgebungsvariablen: `WEB1_PORT` - IP & Hostnamen: `/etc/hosts`
Erzeugt Umgebungsvariablen wie `DB_PORT`, host-Einträge, ermöglicht Zugriffe auf Netzwerk-Ports. Typisches Szenario: Zugriff auf Datenbanken.

Einstiegs-Demo revisited

docker build -t my/microservice

docker run -d --name web1 my/microservice
docker run -d --name web2 my/microservice
docker run -d --name web3 my/microservice

docker run -d --name balancer \
    --link web1:web1 --link web2:web2 --link web3:web3 \
    -p 8080:80 \
    -v (pwd)/etc:/usr/local/etc/haproxy:ro \
    haproxy:1.5
...und damit haben wir alle Elemente aus der Eingangs-Demo kennen gelernt.

Docker Kommandos

##### Images managen | Kommando | Beschreibung | |-----------------|--------------------------------------------| | `docker images` | Liste der lokal vorhandenen Images | | `docker pull` | Image-Download aus dem Repository | | `docker build` | Docker Image via `Dockerfile` erstellen | | `docker commit` | Containers als neues Image comitten | ##### Container kontrollieren | Kommando | Beschreibung | |-----------------|--------------------------------------------| | `docker run` | Erzeugen eines neuen Containers | | `docker start` | Starten eines bestehenden Containers | | `docker stop` | Stoppen eines Containers | | `docker ps -a` | Liste _aller_ Container | | `docker kill` | Stoppen mit Nachdruck |
##### Diagnose & Tools | Kommando | Beschreibung | |-------------------|----------------------------------------------------------| | `docker inspect` | Low-Level Informationen über Container/Images | | `docker log` | Terminal-Ausgaben des Containers | | `docker exec` | Prozess im Container starten, z.B. interaktive Shell | | **`docker diff`** | Was wurde im Container geändert? | | `docker history` | Image: Welche Schichten & wie entstanden? |
Zum Abschluß noch ein kurzer Überblick über die wichtigsten Komandos als Eindruck. Die meisten der Kommandos haben wir kennen gelernt und gehen daher die Liste nicht noch einmal durch. Erwähnenswert ist z.B. noch `docker diff`. Eines der leistungsfähigen Aspekte von Docker.

Docker & Java

Anwendungsfälle

- **Entwicklung**: - Lokale, isolierte & portable Umgebung - Infrastruktur analog zu Produktion - fixe Versionen für Tools & Laufzeitumgebungen - **CI-Server:** Tests in _isolierten_ Referenzumgebungen - **Betrieb**: - einfaches Deployment - Resourcenschonender Parallel-Betrieb vieler Instanzen - **Architektur**: Microservice als Uberjar statt Appserver
#### Entwicklungsumgebung: - run multiple development environments from the same host that each have unique software, operating systems, and configurations - set up local development environments that are exactly like a live server - allow anyone to work on the same project with the exact same settings - Docker als Deployment-Artefakt - einfache Automatisierung möglich - daraus folgen die Anwendungsfälle ...
**Microservice Frameworks** - Spark Framework - Dropwizard - Spring Boot - Vert.x
- Spark: Micro-Framework - Dropwizard: Best of JEE - Spring Boot: Stand-alone Apps - Vert.X: Reactive Apps
**Java Tool Plugins** - **Build:** Maven, Gradle, … - **CI-Server:** Jenkins, TeamCity, … - **IDEs:** IntelliJ, (Eclipse)
- Maven: 4 plugins - CI-Server: Kommt eigentlich überall - IDE Integration: Eclipse "Docker Explorer" nur angekündigt

Best Practices

für Docker Images

- **Immutable infrastructure** - Konfiguration extern halten - Kein blindes `docker pull` - Ein Prozess pro Image - `docker exec` statt ssh-Server - Logging nach `STDOUT`/`STDERR`
- Konfiguration; externe Volumes nutzen - Immutable: Keine Änderung nach docker build; keine Log-Files im Container, Footprint gering halten. Idee: Container == Wegwerfgut. - no, you will not use a community-contributed image without looking at what it will do - Versionierung ermöglicht einfaches Rollback

Docker Distributed

Orchestrierung - Docker Compose

haproxy:
  image: haproxy:1.5
  ports:
    - 8080:80
  volumes:
    - ./etc/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
  links:
    - web1
    - web2
    - web3

web1:
  image: exxcellent/docker_talk
						

Cluster-Betrieb

  • Verteilung & Scheduling
  • Service Discovery
  • Load Balancing
Aus einem mach viele - bisher auf einen Host beschränkt - verteilte Anwendung -> viele Hosts Wenn man mehrere Rechner hat kommt man zu einer Reihe von Problemen: - wie verteilt man die Anwendung? - woher weiß man, auf welchem Rechner eine Anwendung/Service laufen? - wie wird die Last auf die einzelnen Instanzen verteilt?
## Docker out of the box ##### Pures `localhost`: (bis Docker 1.8) - `--link` und Volumes nur auf lokalem Host - Kein cross-host Netzwerk ##### Add-on Tools - Unübersichtliches, dynamisches Ökosystem - Sehr oft nur Einzelteile einer Gesamtlösung - Eher fragil; volles Verständnis notwendig

Tools

- Mesos + Marathon/Aurora - Kubernetes - Rancher - Docker Machine/Compose/Swarm (BETA) - Weaveworks

Beispiel - verteiltes System

Vereiltes System aus - load balancer 1x - web/rest-Knoten 1..n - Message Queue 1x - Worker 1..m - Datenbank 1x Jeder Kasten ein Docker-Container: - Rot: leicht skalierbar, gut im Cluster zu verteilen - Grün: eher ausserhalb wegen Erreichbarkeit (LB) oder Datenhaltung (DB)

Hype vs. Potential

Docker & Windows

##### Heute: (Linux container) - boot2docker - Docker auf Microsoft Azure ##### Zukunft: (Windows container) - Windows Server Containers - Hyper-V Container
- Einstieg auch auf Windows: boot2docker sehr komfortabel. Startet eine Virtualbox in welcher die Container laufen. - Nicht auf Linux beschränkt. Microsoft arbeitet bereits eng mit Docker zusammen: - Ein windows Docker client gibt es bereits: Deployment von Linux VMs - Auf Azure kann man Linux Container starten - Docker-Anbindung an Windows-Server-Containern und Hyper-V-Containern auf dem Weg

Status

von Docker
  • nur Teil einer Gesamtlösung
  • Dynamisches Umfeld
  • 1.x-Technologie & Folgeprobleme
  • Unklare Ausrichtung ➱ Rocket, Open Container, LXD
- »Let’s Dockerize everything« ➱ ziemlich wild & übermütig - Brauche ich Docker? - Signifikante Vorteile von Container/speziell Docker? - Habe ich technische Ressourcen für komplexe, ungelöste Probleme? - Unklare Ausrichtung Docker führt zu Alternativen

Fragen,

die sich durch Docker ergeben
  • Nachvollziehbarkeit & Delivery Model
  • Datenhaltung
  • Zuständigkeiten
  • Security (root, Patches)
- Delivery Model: Binary Blob oder Dockerfile? Wie nachvollziehbar? - Datenhaltung: Kein Koch-Rezept hier. Fokus = Immutable infrastructure - Docker images == platform-specific binaries - Zuständigkeit: Operations oder Developer - Security - docker === root; normalerweise daher auch immer `sudo docker` - Gestackte Images -> Viele ungeupdate Basisimages - (Security) Patch Strategie & Support

Potential Docker

Automatisierung Provisioning, Config, Delivery

ImmutabilityUmgebung = Code. Disposable

ServerkonsolidierungSystem-agnostisch

DeploymentEinfach; Container als Einheit

#### Brauche ich Docker? - Was sind signifikante Vorteile? - Ressourcen für komplexe, ungelöste Probleme?
_»Let’s Dockerize everything«_ ➱ ziemlich wild & übermütig!
#### Automatisierung: - Automatiiserung Systembereitstellung, Configuration & Delivery #### Immutability - Konfiguration = Code. Setup entfällt #### Serverkonsolidierung: - It can get more applications running on the same hardware than other technologies; it makes it easy for developers to quickly create, ready-to-run containered applications; and it makes managing and deploying applications much easier. - System-agnostisch - Instanz & Server damit Wegwerfware #### Deployment: - vereinfacht Bereitstellung - Container = Baustein für komplexe Infrastrukturen - Applikationszentriert statt Infrastruktur-Zentrierte Sicht

Tools

###### GUIs - Docker [Kitematic](https://kitematic.com/) - [Panamax](http://panamax.io/), ... ##### Spezielle Linux-Distros - [RancherOS](http://rancher.com/rancher-os/) - [CoreOS](https://coreos.com/), ... ###### Private Image Registry - Docker [Distribution](https://github.com/docker/distribution) - [Artifactory](http://www.jfrog.com/open-source/), ... ###### Networking - [Weaveworks](http://weave.works/) - CoreOS [Flannel](https://github.com/coreos/flannel), ...
###### Service discovery - CoreOS [etcd](https://github.com/coreos/etcd) - Apache [Zookeeper](https://zookeeper.apache.org/) - [Consul](https://www.consul.io/) ###### Cluster / Orchestrierung - [Rancher](http://rancher.com/rancher-io/) - [Kubernetes](http://kubernetes.io/) - [Shipyard](http://shipyard-project.com/) - Docker [Compose](https://docs.docker.com/compose/) / [Swarm](http://docs.docker.com/swarm/) - Apache [Mesos](http://mesos.apache.org/) / [Marathon](https://mesosphere.github.io/marathon/) - [MaestroNG](https://github.com/signalfuse/maestro-ng) - CoreOS [fleet](https://github.com/coreos/fleet), ...
###### Config Mgmt. - [Ansible](http://www.ansible.com/) - [Puppet](https://puppetlabs.com/) - [Chef](https://www.chef.io/) - [Capistrano](http://capistranorb.com/) ###### Interessante Java-Tools - [Dropwizard](http://dropwizard.io) - [Spark](http://sparkjava.com) - [Vert.x](http://vertx.io) - [Spring Boot](http://http://projects.spring.io/spring-boot) - [Docker Maven-Plugins](https://github.com/alexec/docker-maven-plugin/blob/master/COMPETITORS.md)
Image Credits: _Southampton Container Port_ [Geni](http://commons.wikimedia.org/wiki/File:Southampton_container_port_2_ships.JPG) / [CC-BY-SA-4.0](https://creativecommons.org/licenses/by-sa/4.0/), _Blades_ [zagrobot](https://www.flickr.com/photos/zagrobot/2731084578) [CC-BY-2.0](https://creativecommons.org/licenses/by/2.0/)