entwickler-gilde.de zieht um – Teil 1

entwickler-gilde.de zieht um – Teil 1

Das erste Mal habe ich 2017 über unser bisheriges WordPress Setup gesprochen.
Seit damals hat sich das Setup konzeptionell nicht geändert.
Eine größere Veränderung war nur die Einführung von 3 redundanten OpenLDAP Servern um die Ausfallsicherheit zu verbessern (ggf. kommt dazu noch ein weiterer Blog Post).

Seit einiger Zeit, bin ich dabei die meisten Services auf ein Docker-Deployment umstellen. Eventuell letztendlich als Workload für einen größeren Kubernetes Cluster.
Hier soll nun als erster Schritt die Migration eines hosted WordPress (in einem LXC Container) zu einem Docker-Deployment beschrieben werden.

Schritt 1 – Snapshots

Als erster Schritt muss sowohl von der Datenbank, als auch vom WordPress Verzeichnis ein Schnappshot erstellt werden.
Die Datenbanken des MySQL Containers werden aktuell schon per cron-job täglich per mysqldump in Snapshots abgespeichert. Es gilt also nun, diese Snapshots aus dem Container zu bekommen. Da ich für mein LXC Setup Proxmox vernwende, können wir in dem Container einen Mount-Point zum Host hinzufügen: 

pct set 111 -mp0 /home/backup/111,mp=/home/backup

In dem LXC Container mit der ID 111 wird hier das Host Verzeichnis /home/backup/111 unter /home/backupgemounted. D.h. nun können wir alle MySQL Dumps direkt in das Verzeichnis auf dem Host verschieben.

Just FYI: Das MySQL Script sieht in etwa so aus:

#!/bin/sh
PWD=`which pwd`
MYSQLDUMP=`which mysqldump`
MYSQL=`which mysql`
TAR=`which tar`
HOST=localhost
USER=root
PASS=XXXXXXXXX
ROOT=/home/backup
TARGET=${ROOT}/data/mysql
CMD_FILE="cmd.sql"

rm -R $TARGET/*
echo "SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('mysql','information_schema','performance_schema')" > ${ROOT}/$CMD_FILE
DBS=`$MYSQL --user=$USER --password=$PASS < ${ROOT}/$CMD_FILE`
DATE=`eval date +%Y-%m-%d`
echo "ROOT: ${ROOT}"
I=0
echo "saved $DATE"
for DB in $DBS; do
        if [ ! $I = 0 ]; then
                #echo "dumping $DB";
                $MYSQLDUMP $DB --events --ignore-table=mysql.event --single-transaction --user=$USER --password=$PASS --add-locks --flush-logs  > $TARGET/$DB.sql
                echo "$DB saved"
                cd $TARGET
                $TAR cfj $DB.tar.bz2 $DB.sql
                rm $DB.sql
                cd $ROOT
                echo ""
        fi
        I=$(( $I + 1 ))
done
echo "$I DBs saved"
echo "done"
rm $ROOT/$CMD_FILE

Als nächster Schritt wird ebenfalls das komplette WordPress Verzeichnis auf dem bisherigem NGINX Container gepackt. Und über einen entsprechenden Mount-Point auf den Host übertragen. 

Wahlweise können die Archive nun bereits auf den Docker Host übertragen werden, auf dem dann demnächst das neue Deployment laufen soll. 

Schritt 2 – Docker Host Setup

Der neue Docker Host verwenden als Front-End Proxy Traefik. Traefik wird hier sowohl das Certificate renewal, als auch ein Caching durchführen.
Der sehr große Vorteil von Traefik ist, dass man ohne einen Reload des Traefik Servers selbst, neue Deployments als neuen HTTP Service zur Verfügung stellen kann.
Traefik lässt sich hierbei so konfigurieren, dass es auf neue Docker Deployments reagiert und bei bestimmten Labels dann eine neue Service-Konfiguration aktiviert. Hierbei empfielt es sich ebenfalls, für Traefik ein separates Docker Network zu erstellen. Ich habe mich hier für den Namen traefik_default entschieden. 

Traefik selbst deploye ich, wie alle anderen Services auch, per docker-compose file. Dies schaut wie folgt aus:

version: "3.3"

networks:
  traefik_default:
    external: true

services:
  traefik:
    image: "traefik:v2.10.7"
    container_name: traefik
    restart: always
    ports:
      - "80:80"
      - "443:443"
      - "8082:8082"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/docker/traefik/acme.json:/acme.json"
      - "/docker/traefik/config:/etc/traefik"
      - "/cache:/cache"
    labels:
      # Dashboard
      - "traefik.http.routers.traefik.rule=Host(`traefik.adm.example.com`)"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls.certresolver=leresolver"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.middlewares=auth_traefik"
      - "traefik.http.middlewares.auth_traefik.basicauth.users=admin:$$apr1$$6…r$$.v…k/"

      # global redirect to https
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"

      # middleware redirect
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      - "traefik.enable=true"
    networks:
      - traefik_default
  

Hinweise:

  • traefik.http.middlewares.auth_traefik.basicauth.users sollte durch eigene, passende Werte gesetzt werden. Hier lässt sich konfigurieren, welche Benutzer per basic-auth auf das Traefik Dashboard Zugriff erhalten. Ggf. beschreibe ich in einem weiteren Blog Post noch, wie sich die User auch per LDAP verwalten lassen. 
  • traefik.adm.example.com ist hier natürliche keine gültige Domain. Der Hostname sollte sich gegen die IP des Docker Hosts auflösen lassen. Z.B. durch einen Wildcard Record gegen *.adm.example.com.
  • acme.json enthält die aktuelle Liste der per ACME erstellten TLS Zertifikate. Eventuell muss hier ein leeres JSON File {} existieren, damit das Deployment funktioniert.
  • Entgegen vieler anderer Tutorials, wird hier Traefik nicht per CLI Parametern konfiguriert, sondern per separatem Config File /docker/traefik/config. Dies ist unter anderem notwendig geworden, weil durch die Nutzung von weiteren Plugins das Setup per CLI Parametern recht unübersichtlich hat werden lassen. 

Die Datei /docker/traefik/config/traefik.yaml sieht wie folgt aus:

################################################################
#
# Configuration sample for Traefik v2.
#
# For Traefik v1: https://github.com/traefik/traefik/blob/v1.7/traefik.sample.toml
#
################################################################

################################################################
# Global configuration
################################################################
global:
  checkNewVersion: true
  sendAnonymousUsage: true

################################################################
# EntryPoints configuration
################################################################

# EntryPoints definition
#
# Optional
#
entryPoints:
  web:
    address: :80
  websecure:
    address: :443
  metrics:
    address: :8082

################################################################
# Access logs configuration
################################################################

# Enable access logs
# By default it will write to stdout and produce logs in the textual
# Common Log Format (CLF), extended with additional fields.
#
# Optional
#
accessLog:
  format: json
  fields:
    names:
      StartUTC: drop
  filters:
    statuscodes: 200,300-302
    retryattempts: true
    minduration: 10ms

################################################################
# API and dashboard configuration
################################################################

# Enable API and dashboard
#
# Optional
#
api:
  dashboard: true
pilot:
  dashboard: true

################################################################
# Docker configuration backend
################################################################
providers:
  # Enable Docker configuration backend
  docker:
    exposedByDefault: false

################################################################
# Certificate resolver configuration
################################################################
certificatesresolvers:
  leresolver:
    acme:
      email: admin@consolving.de
      storage: acme.json
      tlschallenge: true

################################################################
# Metrics configuration
################################################################
metrics:
    prometheus:
      entryPoint: metrics
      addrouterslabels: true
      addServicesLabels: true

experimental:
  plugins:
    simplecache:
      moduleName: "github.com/traefik/plugin-simplecache"
      version: "v0.2.1"
  

Die Aktivierung des Metrics Endpoints ist hier optional und nur notwendig, falls ihr die Traefik Metriken via Prometheus abfragen wollt. Falls nicht, könnt ihr diese Zeilen einfach auskommentieren:

  metrics:
    address: :8082
  

Kleiner Pro-Tipp:
Je nach größe eurer WordPress-Installation empfiehlt es sich, noch einmal zu überprüfen, ob im Verzeichnis, wo die Docker Volumes liegen genug Platz vorhanden ist.

df -h /var/lib/docker/volumes/

Sollte dies nicht der Fall sein, besteht z.B. bei Cloud-Providern ein separates Volume zu mounten. Hierbei lässt sich dann gleich auch das komplette Docker Verzeichnis /var/lib/docker auf ein externes Volume legen. Dies lässt sich durch ein paar einfache Schritte durchführen:

  1. Docker Service stoppen und disablen
  2. Docker Verzeichnix umbennen mv /var/lib/docker /var/lib/docker2
  3. Docker Host runterfahren
  4. Externes Volume mounten unter /var/lib/docker
  5. Docker Host starten
  6. Dateien von /var/lib/docker2 nach /var/lib/docker kopieren und access rights noch mal überprüfen.
  7. Docker Service starten und enablen
  8. /var/lib/docker2 löschen

Fazit

Hiermit ist das initiale Setup durchgeführt. Im nächsten Blog Post werden wir uns das Setup des Container Deployments ansehen.

Philipp Haußleiter

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert