Volles Rohr 2016

Moinsen bin 2016 noch sehr sehr aktiv.

Erst mal fuer alle, welche es verpasst haben. In der aktuellen iX (2016/16) habe ich einen Artikel mitverbrochen. Ich habe ueber Docker Swarm Mode und Kubernetes schreiben duerfen.

Zudem gibt es wieder ungesund viele Vortraege:

Ahoi,
Am Ende des Jahres stehen die IT-Tage 2016 an.
Ich halte da zwei Vorträge.

Einer wird wohl so ein Meta-Vortrag. Mal sehen ob ich es schaffe ohne Terminal einen Vortrag zu halten :)
Der zweite ist über Docker und MySQL/MariaDB. Hier gibt es sicher ein paar HandsOn :)

Viel Spaß
Erkan :)

Volles Rohr Docker

| 3 Kommentare | Keine TrackBacks
Ahoi,
Mache mich gleich auf den Weg zur DevOpsConf (Berlin),
da gibt es unter anderem zwei Talks (Hands-on: Bootstrapping Docker Swarm und (Hands-on-Docker-Security) von mir. Da ich schon in Berlin bin und auch noch die  SLAC am Start ist, gibt es noch den Talk (Docker Infrastrukturen mit Docker Batteries). 
Wo wir schon dabei sind. Es gibt noch die ContainerDays (Hamburg) da darf ich dann  Linuxkernel features building my $CONTAINER halten. 
Wer da ist einfach mal anschubsen, ich bin der in der kurzen Hose ;)

Wer Lust auf Schulung hat. Im Linuxhotel (Essen) sind für Juli die Schulungen um Docker und LXC (endlich) confirmed. Leider kein LXD, aber was soll mensch da machen? :/

Ein aktuelles systemd (z.B. das in Ubuntu 16.04) instrumentiert via TasksMax mittlerweile die pid Cgroups. Quasi ein ulimit -u via Cgroups.

Folgender Commit ändert die Beschränkt die Prozesse/Thread aller Services.

commit 9ded9cd14cc03c67291b10a5c42ce5094ba0912f
Author: Lennart Poettering <lennart@poettering.net>
Date:   Fri Nov 13 19:28:32 2015 +0100

    core: enable TasksMax= for all services by default, and set it to 512

    Also, enable TasksAccounting= for all services by default, too.

    See:

    http://lists.freedesktop.org/archives/systemd-devel/2015-November/035006.html

Damit haben wir leider:

$ systemctl show -p TasksMax docker
TasksMax=512

$ systemctl show -p TasksMax mysql
TasksMax=512

Damit stoßen schon bei mittelmäßiger Belastung an die Grenzen /o\ Also nicht wundern, wenn nach einem Upgarde auf z.B. Ubuntu 16.04 nichts mehr skaliert :)

Folgendes stellt das vorherige Verhalten wieder her.

TasksMax=infinity

Dieser darf jetzt gerne angepasst werden;)

Viel Spaß

Erkan \o/

Update 1: Zumindest in Debian/Ubuntu wird in einem Update wieder TaskMax=infinity sein

Update 2: Ab Version 230 gibt es einen neuen Default: KillUserProcesses=yes. Einfach nachlesen und heulen :)

So habe fertig :)

Artikel ist da. 

Viel Spaß
Erkan:)

Ja der Titel lehnt sich an Deichkind an :) Ein Alleinstellungsmerkmal von LXD/LXC ist LXCFS. Damit sehen Prozesse im Container auch nur die Ressourcen, welche zugewiesen wurden (hier am Beispiel LXD (nicht irritieren lassen ist wirklich LXD:) ):

$ lxc exec container1 -- free -m                             
              total        used        free      shared  buff/cache   available
Mem:          15771           8       15646        1588         116       15646
Swap:          2047         581        1466                  

$ lxc config set container1 limits.memory 256MB              

$ lxc exec container1 -- free -m                             
              total        used        free      shared  buff/cache   available
Mem:            256           8         130        1638         116         130
Swap:          2047         581        1466

\o/

Mal so zum Vergleich Docker kann das (noch?) nicht:

$ docker run --rm -m 256M  ubuntu free -m                    
WARNING: Your kernel does not support swap limit capabilities, memory limited without swap.
             total       used       free     shared    buffers     cached
Mem:         15771      15380        391       1653        411       7310
-/+ buffers/cache:       7658       8113                     
Swap:         2047        580       1467

In meinem letztem Projekt habe ich mal wieder nach einem (Performance)Monitoring Tool gesucht und mit Prometheus sogar fündig geworden. Prometheus kann weit mehr als eine MySQL Instanz ‘monitoren’. Dabei ist die Grundidee von Prometheus Metriken einzusammeln.

Hier ein einfaches Beispiel einer Konfiguration von Prometheus:

global: 
  scrape_interval: 1m
  scrape_timeout: 10s
  evaluation_interval: 1m

scrape_configs:
  - job_name: mysql
    scheme: http
    target_groups:
    - targets: 
        - '10.17.148.31:9104'
      labels:
        zone: mysql

Das ist eigentlich eine langweilige Config. Der Witz von Prometheus ist viele Quellen zu aggregieren und damit auch korrellieren zu können. Sprich viele Jobs und massig Targets. Damit ist Prometheus die zentrale Performancedatenbank, welche die Metriken aller Targets sammelt und speichert.

Bleiben wir bei der einfachen Config von oben. Alle Minute holt sich Prometheus von 172.17.148.31:9104 Metriken (/metrics) und labelt diese mit zone=mysql. Diese Labels können später bei der Abfrage wiederverwendet werden.

Schauen wir uns mal einen Teil der Metriken an:

> curl 10.17.148.31:9104/metrics
...
mysql_global_status_threads_cached 26
mysql_global_status_threads_connected 99
mysql_global_status_threads_created 125
mysql_global_status_threads_running 2
...

Damit hat jeder MySQL Admin was anzufangen. Hinter der Adresse lauscht ein Exporter. Wie soll es anders sein hier als Docker Container. FYI: Nicht so in Produktion machen!

> docker run -d -p 9104:9104 --link=mysql:backend \
  -e DATA_SOURCE_NAME=prometheus:prometheus@secret(backend:3306)/ \
  prom/mysqld-exporter

Das ist etwas old school Docker. Offensichtlich läuft auch die Datenbank in einem Container (mysql) und wir verwenden hier noch das deprecatete --link :)

mysqld-exporter kennt noch weitere Optionen:

$ docker run --rm prom/mysqld-exporter --help
Usage of /bin/mysqld_exporter:
  -collect.auto_increment.columns
      Collect auto_increment columns and max values from information_schema
  -collect.binlog_size
      Collect the current size of all registered binlog files
  -collect.global_status
      Collect from SHOW GLOBAL STATUS (default true)
  -collect.global_variables
      Collect from SHOW GLOBAL VARIABLES (default true)
  -collect.info_schema.processlist
      Collect current thread state counts from the information_schema.processlist
  -collect.info_schema.tables
      Collect metrics from information_schema.tables (default true)
  -collect.info_schema.tables.databases string
      The list of databases to collect table stats for, or '*' for all (default "*")
  -collect.info_schema.tablestats
      If running with userstat=1, set to true to collect table statistics
  -collect.info_schema.userstats
      If running with userstat=1, set to true to collect user statistics
  -collect.perf_schema.eventsstatements
      Collect metrics from performance_schema.events_statements_summary_by_digest
  -collect.perf_schema.eventsstatements.digest_text_limit int
      Maximum length of the normalized statement text (default 120)
  -collect.perf_schema.eventsstatements.limit int
      Limit the number of events statements digests by response time (default 250)
  -collect.perf_schema.eventsstatements.timelimit int
      Limit how old the 'last_seen' events statements can be, in seconds (default 86400)
  -collect.perf_schema.eventswaits
      Collect metrics from performance_schema.events_waits_summary_global_by_event_name
  -collect.perf_schema.file_events
      Collect metrics from performance_schema.file_summary_by_event_name
  -collect.perf_schema.indexiowaits
      Collect metrics from performance_schema.table_io_waits_summary_by_index_usage
  -collect.perf_schema.tableiowaits
      Collect metrics from performance_schema.table_io_waits_summary_by_table
  -collect.perf_schema.tablelocks
      Collect metrics from performance_schema.table_lock_waits_summary_by_table
  -collect.slave_status
      Collect from SHOW SLAVE STATUS (default true)
  -config.my-cnf string
      Path to .my.cnf file to read MySQL credentials from. (default "/home/golang/.my.cnf")
  -log.level value
      Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal, panic]. (default info)
  -log_slow_filter
      Add a log_slow_filter to avoid exessive MySQL slow logging.  NOTE: Not supported by Oracle MySQL.
  -web.listen-address string
      Address to listen on for web interface and telemetry. (default ":9104")
  -web.telemetry-path string
      Path under which to expose metrics. (default "/metrics")

Prometheus aggregiert die Daten. Im eigenem Expression Browser kann auf die Daten zugegriffen werden. Prometheus bringt eine nette Query Language mit, die einem erlauben alle bekannten Abfragen nachzubilden. Einfachste Abfragen wären (selbsterklärend):

mysql_global_status_created_tmp_disk_tables

increase(mysql_global_status_created_tmp_disk_tables[2m])/120

[UPDATE]

Brian Brazil hat einen besseren Vorschlag:

rate(mysql_global_status_created_tmp_disk_tables[2m])

(Einen Überblick über die (Funktionen)[https://prometheus.io/docs/querying/functions/] gibt es auch)

Als Dashboard ist Grafana zu empfehlen. Zwar bietet Prometheus mit PomDash was eigenes an, Aber imho gehört die Zukunft Grafana.

Daneben bietet Prometheus (nicht Gegenstand des Artikels) auch ein (experimentelles) Alerting.

Nicht alles

Prometheus erlaubt den Zugriff auf historische Daten, die eben noch im nachhinein nach Bedarf korreliert werden können. Nutzer von PNP4Nagios verstehen meine Freude :) Eine weitere Stärke von Prometheus ist es nicht nur einen Exporter abzufragen. Die Stärke von Prometheus ist es die Metriken der Exporter aller Nodes des RZs abzufragen \o/

Fazit

An Prometheus gefällt mir die einfache Zusammenführung von Daten. So ist es - bei entsprechenden Exportern - z.B. Netzlatenz, CPU Auslastung und Datenbankperformance über das ganze RZ an einem Punkt zu vergleichen. Und das auch im Nachhinein. Oft fällt mir im Nachhinein ein, was ich gerne korreliren würde und genau das ermöglicht Prometheus.

Es ist sehr leicht eigene Exporter zu schreiben. Nervig ist das jeder Exporter einen eigenen Port braucht :(

Viel Spaß

Erkan

[Update]

Eine nette Präsentation gab es beim MariaDB Berlin Meetup. Besonders die Grafana Bilder sind ans Herz zu legen.

[Update2]

Percona hat ja immer einen guten Riecher für ‘Hot Stuff’. So überrascht es nicht, dass die heute ihr Percona Monitoring and Management (mit Prometheus) vorgestellt haben.

Moin,

ich darf mein zweites Webinar für und bei der iX halten. Es baut auf dem ersten Webinar von mir (Achtung bitte darauf achten, dass es von mir ist :) auf. 
Vereinfacht schauen wir uns die Docker "Batteries" an. Sprich wir schauen uns Docker über viele Hosts an :)

Viel Spaß:)
Erkan 

Im letzten Blogpost haben wir uns angeschaut wie einfach Docker Network die bidirektionale Container-Kommunikation über mehrere Nodes hinweg ermöglicht. Selbstredend haben wir Galera dazu vewendet :)

Im heutigem Blogpost machen wir die selbe Chose nur via Docker Swarm. Docker Swarm wird vorausgesetzt. Der Aufbau eines Docker Swarm "Clusters" (Multi-Node-Setup) kann bei Bedarf gesondert behandelt werden.

Warum schauen wir uns Docker Swarm an?

Im letzten Blogpost wurde jeder Host direkt angesprochen. Das ist langfristig nicht praktisch. Mit Docker Swarm existiert eine Endpunkt um auf den ganzen Mulit-Host-Setup zuzugreifen. Wir wollen gar nicht expliziet wissen/bestimmen wo die Container laufen.

Der Einfachheit halber läuft auf dem Rechner mit der IP 172.17.152.11 der Management Prozess von Swarm (quasi ein Proxy) und horcht auf Port 2376.

Um uns Tipparbeit zu sparen:

export DOCKER_HOST=tcp://172.17.152.11:2376

Damit greifen wir mit docker immer auf den Swarm Management Port zu. Schauen wir uns noch den laufenden Galera Cluster des letzten Blogposts an(gekürzte Ausabe):

$ docker ps -f name=galera3 -f name=galera2 -f name=galera1
CONTAINER ID        IMAGE                      NAMES
751f4f071359        erkules/galera:basic       swarm3/galera3
24d4a2dfe3e2        erkules/galera:basic       swarm2/galera2
d3410d308171        erkules/galera:basic       swarm1/galera1

Zu beachten ist, dass die NAMES Spalte erweitert ist. Sie zeigt auf welchem Host der Container (swarm1,swarm2,swarm3) läuft.

Entfernen wir erst mal den alten Galera Cluster:

$ docker rm -f swarm3/galera3 swarm2/galera2 swarm1/galera1 
swarm3/galera3
swarm2/galera2
swarm1/galera1

Nun deployen wir einen neuen Cluster. Hierbei nutzen wir das Overlay-Netzwerk vom letzten Blogpost. Neu ist:

  • Wir sagen nicht auf welchem Host der Container laufen soll.
  • Der Container bekommt das Label galera=setup1.
  • Der Container soll auf keinem Host laufen, auf dem noch ein weiterer Container mit diesem Label läuft (affinity:...). Dadurch ist gewährleistet, dass nicht zwei Container des Clusters auf den gleichen Host laufen.

Bootstrapcontainer (galera1):

$ docker run -d --name galera1 --net galera  -e affinity:galera!=setup1 \
   --label galera=setup1 erkules/galera:basic \
   --wsrep-cluster-address=gcomm://galera1,galera2,galera3 --wsrep-new-cluster
1c3f8576cb124261c35412c7e643b341ec6f69d70c6a601b7dde8c3574774c42

galera2

$ docker run -d --name galera2 --net galera  -e affinity:galera!=setup1 \
   --label galera=setup1 erkules/galera:basic \
   --wsrep-cluster-address=gcomm://galera1,galera2,galera3 
611501de09b64475e9356dfb50be7f5bf179919a9e94e60b9d1e466bb7450437

galera3

$ docker run -d --name galera3 --net galera  -e affinity:galera!=setup1 \
   --label galera=setup1 erkules/galera:basic \
   --wsrep-cluster-address=gcomm://galera1,galera2,galera3 
582aaf272bb449733ca1b95cced1ae7b3ef2e20e105d09261a36b6a0912d9f07

Mal schnell verifizieren, dass alles geklappt hat:

$ docker ps   -f  label=galera=setup1 
CONTAINER ID        IMAGE                  NAMES
582aaf272bb4        erkules/galera:basic   swarm2/galera3
611501de09b6        erkules/galera:basic   swarm1/galera2
1c3f8576cb12        erkules/galera:basic   swarm3/galera1


$ docker exec  swarm1/galera2 \
   mysql -e 'show global status like "wsrep_cluster_size"'
Variable_name Value
wsrep_cluster_size 3

Jihaa!!!!

Starten wir noch schnell einen 4. Knoten:

    $ docker run -d --name galera4 --net galera  -e affinity:galera!=setup1 \
      --label galera=setup1 erkules/galera:basic \
      --wsrep-cluster-address=gcomm://galera1,galera2,galera3 
    docker: Error response from daemon: unable to find a node that satisfies galera!=setup1.
    See 'docker run --help'

Das ist gut so. Es kann und soll ja nicht klappen, da wir nur drei Nodes zur Verfügung haben :) Ach so wegen Planetmysql sollte im Blog wohl noch mal MySQL stehen ... dumdidum

Viel Spaß

Erkan

Moinsen,

heute ist die iX mit dem 2. Teil des Docker Tutorials heraus gekommen, den ich mit immenser Unterstützung des Redakteurs wuppen durfte :)

Viel Spaß
Erkan

About Me

Aktuelle Kommentare

  • erkan: Ahoi Mathias und Anaonym, Habe die Slides den Konferenzverantwortlichen zugeschickt. weiter lesen
  • Anonym: Erst einmal auch herzlichen Dank für Deine Vorträg auf der weiter lesen
  • Mathias Velten: Moin, vielen Dank für deine Vorträge auf der DevOpsCon, haben weiter lesen
  • Martin Jochum: Schönes Webniar ... wieder was gelernt! Gruß Martin PS: Nur weiter lesen
  • erkan: Ok falsch ausgedrückt. Ich wollte nicht darüber sprechen, dass die weiter lesen
  • schlitzered: siehe auch den hier, wie es aussieht haben sich die weiter lesen
  • schlitzered: evtl nur ein anzeige problem, schonmal probiert mehr als 256 weiter lesen
  • Georg Öttl : Bin schon gespannt... Ist die 89 Euro sicher wert. weiter lesen
  • erkan: Ahoi Jan, es wird noch mehr kommen und wenn Du weiter lesen
  • Jan: Moin Erkan! Hehe so siehts aus. Ja es ist noch weiter lesen

Aktuelle Assets

  • launchpad.png