In einem K3D Cluster das Kubernetes Dashboard deployen

Hat man einen K3D Cluster aufgesetzt, dann liegt es gerade in den Anfängen nahe das Dashboard zu installieren. Für das Kubernetes Dashboard gibt es sogar ein Helm Chart.

Die Installation mit Helm ist ja an und für sich nicht schwierig, nur wird man nach der Installation eine Überraschung erleben. Folgt man der Anleitung:

# Add kubernetes-dashboard repository
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
# Deploy a Helm Release named "my-release" using the kubernetes-dashboard chart
helm install kubernetes-dashboard/kubernetes-dashboard --name my-release

Nach der Installation wird man anders als gedacht, von einem freundlichen internal server error empfangen.

Ingress

Der Ingress-Controler steuert das Routing anhand der vorhandenen Host Informationen im Header. Bei K3S/K3D wird implitziet Traefik v1.7 installiert.

Diese sorg für das genannte Problem und daher müssen wir ein paar Änderungen vornehmen, damit wir das Dashboard mit dem K3D Cluster zum laufen bringen.

Variante 1

Man übergibt direkt in den ingress.annotations die ingress.class=traefik und setzt den Host direkt.

--set ingress.annotations."kubernetes\.io/ingress\.class"=traefik \
--set ingress.enabled=true \
--set ingress.hosts[0]=dashboard.k3d.duckdns.org

Variante 2

Bei der Variante 2 wird das Ingress in dem Helm Chart nicht genutzt und das Ingress klassisch als Kubernetes Manifest gesetzt.

Ingress in dem Helm Chart deaktivieren

Wie bereits angesprochen, müssen wir zunächst das Ingress in dem Helm Chart deaktivieren. Das geschied über den Parameter **–set ingress.enabled=false **

 --set ingress.enabled=false

Traefik Ingress per Kubernetes Manifest

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  labels:
    name: kubernetes-dashboard 
  name: kubernetes-dashboard-secure
  namespace: default
  annotations:
   kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: dashboard.k3d.duckdns.org
    http:
      paths:
      - backend:
          serviceName: dashboard-kubernetes-dashboard
          servicePort: 8080

Das Skript create_cluster_admin.sh

Das Skript create_cluster_admin.sh verwende ich, um einen Service Account mit der Rolle cluster-admin.

create_cluster_admin dashboard

Installation

Insgesamt ergeben sich nun daraus folgende Installationsschritte.

# add repo
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/

# add SA for Dashboard
create_cluster_admin.sh dashboard

# install chart
helm install dashboard kubernetes-dashboard/kubernetes-dashboard --set protocolHttp=true --set metricsScraper.enabled=true --set service.externalPort=8080 --set serviceAccount.name=dashboard --set serviceAccount.create=false

# set traefik ingress
kubectl apply -f ./ingress.yaml

MDV

Das kleine Programm mdv kann Markdown auf der Konsole rendern, sodass ein vereinfachtes lesen gegenüber des Quelltextes auf der Konsole möglich wird.

Installation

Der Terminal Markdown Viewer lässt sich einfach per yay aus dem AUR Repository installieren.

 yay -S --noconfirm terminal_markdown_viewer

Markdown anzeigen

Das Programm befindet sich nach der Installation in /usr/bin/mdv und steht daher mit dem Paket pyhton-markdown im Konflikt.

Mit Scrolling

Man kann den Output von mdv nach less pipen, aber dann werden in der Standardeinstellung die Escape Colorsequenzen nicht angewendet und man hat nur Zeichensalat. Damit less nun diese interpretiert, muss der Parameter -r angegeben werden. Daraus ergibt sich nun folgender Aufruf von mdv:

mdv readme.md | less -r

Eine Vereinfachung ist, wenn man sich einen simplen Wrapper dafür anlegt. Dieser muss in dem ausführbaren Pfad liegen und vor /usr/bin eingebunden sein.

#!/bin/bash
mdv $0 | less -r

Midnight Commander

Mit F3 kann man im MC Dateien anschauen. Die Dateierweiterungen lassen sich konfigurieren, sodass man für die Endung .md für Markdown Dateien einen neuen externen Viewer definieren kann.

Hier kommt nun wieder less -R ins Spiel. Definiert man folgenden Regulären Ausdruck in der Datei ~/.config/mc/mc.ext welche sich über Befehl -> Erweiterungsdatei bearbeiten editieren lässt:

# Markdown
regex/i/\.md?$
    View=/usr/bin/mdv %f | less -R

dann kann man mit F3 auf die Markdown Datei die sich im Hintergrund bei MC anzeigen lassen.

Speicherung der Credentials für GIT auf der Komandozeile

Oft ist es so, dass man auf einem Server (wo man nur die Kommandozeile zur Verfügung hat) sehr mühselig jedes Mal beim Pushen oder Pullen die Credentials einzugeben. GIT kann diese dauerhaft speichern, was den Komfort deutlich erhöhen kann. Ob dieses zu einem Sicherheitsrisiko führt, ist hier nicht Thema und wird nicht weiter betrachtet.

File Storage einrichten

git config --global credential.helper 'store --file ~/.my-credentials'

Ein privates Repository von GitHub per PAT clonen

Möchte man ein privates Repository von GitHub auschecken, so kann man Zugriff auf das Repository über ein PAT (Personal Access Token) erhalten.

Dazu muss folgendes Schema angewendet werden:

git clone https://xxxxzzzzxxxxzzzzxxxxzzzzxxxxzzzzxxxxzz:@github.com/MaxMeier/Projekt.git

Wichtig ist der :, da dieser ein leeres Passwort signalisiert, welches bei einem PAT nicht benötigt wird.

Liferay Plugins Sharepoint und SAML2

Die Plugins Sharepoint REST und das Plugin für die ADFS Anbindung SAML2 benötigten ein spezielle Behandlung, da sie sonst einen Neustart des Osgi Runtime Containers benötigen. Diese ist bei der containercreation im Kubernetes Lifecylcle natürlich nicht möglich.

Deployen

Auto Deploy

Zunächst habe ich die Plugins in ein Verzeichnis in dem Liferay Docker Container kopiert, der von Liferay überwacht wird und bei darf per hot deploy Bundles startet. In den Logs konnte man während des Startvorgangs auch erkennen das sie verarbeitet werden. So weit, so gut. Aber in den Logs tauchten Einträge auf, dass das Plugin für die Fertigstellung der Installation einen Neustart des Osgi Containers benötigt. Das ist eigentlich nicht die Philisofie von Osgi.

Marketplace Verzeichnis

Neben dem bereit gennanten Verzeichnis gibt es ein weiteres Verzeichnis, welches Bundles verarbeitet. Es ist das Verzeichis marketplace. Dieses wird beim Starten von Liferay gesondert behandlet, so dass kein Neustart von Liferay nötig ist.

Rückwärtssuche

Wie viele Wissen, kann man mit STRG + r Suchbegriff in der Historie der Shell danach Suchen. Durch erneutes drücken von STRG + r springt zum vorherigen usw.

Vorwärtssuche

Damit man die Suchrichtung ändern kann, muss man STRG + s verwenden. Falls es nicht funktioniert, dann muss die Suspension der Shell mit

stty -ixon

abgeschaltet werden. Nun kann man mit STRG + r rückwärts und mit STRG + s vorwärts suchen in der Historie.

JSON Inhalte semantisch vergleichen

Wenn man mal in die Situation kommt JSON Dateien zu vergleichen, dann kann es sein, dass dieses JSON unterschiedlich strukturiert sind. Dabei versagen naturgemäß normale Diff Programme wie zum Beispiel Meld oder ähnliche.

Hier kommt jsondiff.com zur hilfe. Es wird hierbei ein semantischer Vergleich vorgenommen und somit lassen sich auch anders strukturierte JSON Dokumente einfach miteinander vergleichen.

Parallel Download

Wer bereits einen lokalen Maven Proxy im Einsatzt hat (siehe Nexus OSS Proxy), der kann Maven beschleunigen. Wenn zum Beispiel das .m2/repository Verzeichnis geleert wurde, dann kann man mit dem Parameter -Dmaven.artifact.threads=30 den Vorgang bei Artefakten aus unterschiedlichen Gruppen IDs verbessern.

Alternativ kann man auch die Umgebungsvariable MAVEN_OPTS setzen:

export MAVEN_OPTS=-Dmaven.artifact.threads=3

Ein echter paralleler Download ist das noch nicht. Es besteht aber ein Ticket in https://issues.apache.org/jira/browse/MRESOLVER-7, aber gelöst ist das Problem aktuell noch nicht.

Drone

Drone im Zusammenspiel mit Gitea kann als CI/CD Pipeline eingesetzt werden. Dank zahlreicher Plugins, lässt sich so auch ein Continuous Delivery Pipeline für das Deployment aufbauen. Hier in diesem Beispiel soll es aber vielmehr um die Installation und Konfiguration gehen. Es wird ein Java Programm, das mit Gradle als Buildtool übersetzt wird, einen Status in Gitea als sogenanntes Badge anzeigen. Dazu wird nach jedem Commit ein Docker Image als Grundlage verwendet, um das Programm mit Gradle zu bauen und testen.

Vorbereitung

Zunächst habe ich einen DNS Eintrag drone.XXXX.org erstellt, damit der Dienst hinter dem Reverse Proxy (NginX) aus dem Netz erreichbar ist.

1. eine OAuth2 Application erstellen

Damit OAuth2 mit Drone und Gitea funktuiniert, muss man in Gitea eine „Anwendung“ anlegen. Dieser Anwendung wird später die Erlaubnis gegeben, Gitea als Basis für die Git Repositories zu dienen. In den Einstellungen unter Settings –> Applications –> Manage OAuth2 Applications wird nun eine neue Anwendung erstellt.

Der Anwendung geben wir den Namen drone, damit eine Zuordnung später möglich ist. Die redirect URL setzt sich aus der Domain plus dem Path /login zusammen.

Feld Wert
Name drone
Redirect URL https://drone.XXXX.org/login

Mit einem Klick auf create application wird nun die Anwendung in Gitea angelegt.

Notieren Sie sofort die angezeigten Werte, da das Secret später nicht mehr angezeigt wird und bei Verlust ein neues Secret erstellt werden muss. Hier beispielhafte Werte die dann angezeigt werden:

Var Value
ClientID 3fdd3921-22f4-49ab-bcb1-2b15854e936f
Client Secret 6neDCDDVXya5eVCb4JJhNZGGGdG-nSoA3f8QKYyjamk=

Beenden Sie nun die Eingabe mit einem Klick auf den Button Save, um die Anwendung endgültig anzulegen.

2. Secret für die Kommunikation zwischen Drone und und dem Runner erstellen

Damit sich der Docker Runner mit Drone unterhält, muss ein zuvor generiertes Secret ausgetauscht werden. Mit openssl lässt sich ein Secret sehr einfach auf der Kommandozeile generieren. Der Aufruf von

openssl rand -hex 16

spuckt etwas wie

c014d553037b2ab672374684bed79fa0

aus. Dieses Secret muss dem Docker Container als RPC_SECRET übergeben werden (siehe unten).

3. Drone Container starten

Als Vorbereitung laden wir den Container mit docker pull runter.

docker pull drone/drone:1

Konfiguration

Der Docker Container benötigt einige Angaben, damit Drone mit dem Gitea zusammenarbeitet. Es werden die ClientID, ClientSecret und das Secret für den Docker Runner benötigt. Die Adresse des Gitea Server, sowie die Server Host Adresse und das Protokoll müssen angegeben werden. Alle weiteren Parameter sind Standard und bedürfen hier keiner weiteren Erklärung.

Die gesamte Konfiguration sieht dann wie folgt aus:

docker run \
  --volume=/var/lib/drone:/data \
  --env=DRONE_AGENTS_ENABLED=true \
  --env=DRONE_GITEA_SERVER=https://git.XXXX.org \
  --env=DRONE_GITEA_CLIENT_ID=3e2f5dd2-2704-11ea-9f11-00248cbd6e48 \
  --env=DRONE_GITEA_CLIENT_SECRET=6neDCDDVXya5eVCb4JJhNZGGGdG-nSoA3f8QKYyjamk= \
  --env=DRONE_RPC_SECRET=c014d553037b2ab672374684bed79fa0 \
  --env=DRONE_SERVER_HOST=drone.XXXX.org \
  --env=DRONE_SERVER_PROTO=https \
  --publish=80:80 \
  --restart=always \
  --detach=true \
  --name=drone \
  drone/drone:1

Achtung: Auch wenn über Port 80 nur HTTP geht, so muss als Protokoll HTTPS angegeben werden, da sonst die Redirect URI nicht korrekt ist und OAuth2 Login nicht funktioniert und eine Fehlermeldung innerhalb von Gitea angezeigt wird.

Grant Access

Durch Aufruf der Seite https://drone.XXXX.org wird man per Redirect auf den Gitea Server weitergeleitet. Hier muss man jetzt noch der Anwendung „drone“ den Zugriff gewähren. Danach wird man auf die Drone Seite weitergeleitet, wo jetzt alle Repositories des Gitea Servers gelistet sein sollten.

4. Docker Runner

Drone benötigt, wie bei GitLab auch, Runner. Es gibt verschiedene Runner, die man nutzen kann, um ein Build durchzuführen. Wie unter https://docker-runner.docs.drone.io/installation/install_linux/ beschrieben, installieren wir nun noch einen Runner auf Docker Basis. Zunächst pullen wir den Runner mit

docker pull drone/drone-runner-docker:1

Den Runner konfigurieren

Der Runner benötigt nicht ganz so viele Parameter wie der Drone Container. Einige werden jedoch dennoch benötigt. Es muss der Host und das Protokoll für den Drone Server angegeben werden. Zusätzlich muss das vorher generierte Secret übergeben werden, so dass sich folgender Aufruf ergibt:

docker run -d \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e DRONE_RPC_PROTO=https \
  -e DRONE_RPC_HOST=drone.XXXX.org \
  -e DRONE_RPC_SECRET=e16578d8ae6306175e49df94ad2c75e4 \
  -e DRONE_RUNNER_CAPACITY=2 \
  -e DRONE_RUNNER_NAME=${HOSTNAME} \
  -p 3000:3000 \
  --restart always \
  --name runner \
  drone/drone-runner-docker:1

Nach dem erfolgreichen Start pollt der Runner den Server https://drone.XXXX.org, welches mit docker logs runner sichtbar wird.

[test@manjaro-server ~]$ docker logs runner
time="2019-12-19T11:06:44Z" level=info msg="starting the server" addr=":3000"
time="2019-12-19T11:06:45Z" level=info msg="successfully pinged the remote server"
time="2019-12-19T11:06:45Z" level=info msg="polling the remote server" arch=amd64 capacity=2 endpoint="https://drone.XXXX.org" kind=pipeline os=linux type=docker

Nun steht der Runner bereit und wartet auf Aufträge die er abarbeiten kann.

Die Projektkonfiguration

Repository aktivieren

In den Settings des Repository muss dieses aktiviert werden, damit Drone auf Events reagieren kann.

Ein Drone YAML Skript erstellen

Drone ließt die Datei .drone.yml im Rootverzeichnis des Repositories aus und handelt nach den dort hinterlegten Anweisungen.

Hier ein sehr einfaches Skript, welches bei jeden Commit einen Test mit Gradle durchführt. Das Skript verwendet ein Archlinux als Basis und installiert Java nach, damit der Gradle Wrapper in dem Repository

kind: pipeline
name: default

steps:
- name: setup
  image: archlinux/base:latest
  commands:
    - echo 'Server = http://cache.XXXX.org:8080/$repo/os/$arch/' > /etc/pacman.d/mirrorlist
    - pacman -Sy --noprogressbar --noconfirm jdk11-openjdk
    - JAVA_HOME=/usr/lib/jvm/java-11-openjdk/ ./gradlew clean build test

Wichtig: –noprogressbar muss angegeben werden, da sonst der Drone Runner sofort das Skript mit SUCCESS beendet. Dieses scheint ein Fehler von Drone zu sein.

Für eine schnellere Verarbeitung der Kommandos habe ich einen lokalen Cache für Pacman eingerichtet. Der Cache ist unter der Domäne cache.XXXX.org auf dem Port zu erreichen. Das Docker Image ist bereits lokal von Docker gecacht und daher ist nun eine Installation der Java und Gradle Pakete innerhalb kurzer Zeit erledigt.

Nun wird Drone beim jedem Commit in das Repository einen eigenständigen Build anstoßen und das Badge entsprechend in Gitea aktualisieren.

Plugins

Für Drone.io gibt es jede Menge Plugins unter https://plugins.drone.io/

Alternativen

Es gibt bereits einen Fork von Drone, der im Wesentlichen eine Erweiterung für Windows Programme mit Cygwin darstellt. Der Fork tea-ci ist unter https://docs.tea-ci.org/usage/overview/ zu finden.

Den JOOQ Parser verwenden

Hier ein praktisches Beispiel wie man den Parser von JOOQ verwenden kann. Gegeben sei ein String der einen Select enthält.

select name from books

Dieser soll aber mit Hilfe vom der JOOQ DSL um ein LIMIT und ein OFFSET von jeweils 10 erweitert werden.

Zunächst muss der Parser den String in DSL Objekt parsen, welches dann mit der DSL entsprechend modifiziert werden kann.

dsl.selectFrom(dsl.parser().parse("select name from books"))
  .limit(10)
  .offset(10)
  .fetch();

Hinweis: Ein kleiner Nachteil ist, dass der Parser den SQL String verstehen muss. Zur Zeit werden noch nicht alle Feinheiten der diversen Dialekte unterstützt.

Weitere Einsatzmöglichkeiten

Da der Parser viele Dialekte versteht, kann man das SQL mit JOOQ transpellieren, dass heißt von den einem Dialekt in einen anderen transformieren.