ttyd

Das Projekt https://github.com/tsl0922/ttyd erlaubt den Zugriff auf ein Linux über einen Web Browser. In diesem Beispiel verwende ich die Alpine Version des Images von Docker Hub. Es ist mit rund 4MB sehr klein und ist daher sehr schnell erstellt.

Cluster erstellen

Für das Demo nutze ich K3D. Der Cluster ist mit

k3d cluster create demo -p80:80@loadbalancer

auch schon fertig.

Installation ttyd

Mit kubectl ist ttyd per run zu starten. Per default lauscht ttyd auf dem Port 7681. Das heißt damit man auf die WebShell zugreifen kann muss der Port Forward mit ausgeführt werden.

kubectl run --image=tsl0922/ttyd:alpine --port=7681 ttyd
kubectl port-forward ttyd 7681:7681 --address=0.0.0.0&

Midnight Commander

Als Beispiel für die volle funtkionstüchtigkeit habe ich per apk add mc den MC installiert.

K3D Traefik

Wenn man mit K3D einen neuen Cluster anlegt, dann wird Treafik V1 per Default über Helm anstatt Nginx ausgerollt. Das ist oft nicht von Relevanz, aber einige Anwendung setzen für den Betrieb den NginX als Ingress Controler voraus.

K3D ohne Traefik

Man kann K3S –k3s-server-arg ‘–no-deploy=traefik’ nun K3S veranlassen Traefik nicht auszurollen, um NginX als Ingress Controller zu installieren.

k3d create cluster demo --k3s-server-arg '--no-deploy=traefik' 

Bug in K3D

Es befindet sich in Bug in K3D, sodass der Parameter –no-deploy=traefik an K3S nicht korrekt übergeben wird.

Fehler wurde behoben mit K3D >=4.1.1 siehe https://github.com/rancher/k3d/issues/482

Installation NginX Ingress Controller

K3S schaut beim Start in dem Verzeichnis /var/lib/rancher/k3s/server/manifests/ nach Manifesten. Man kann also hier das CRD für NginX ablegen und das führt. Mehr dazu unter https://rancher.com/docs/k3s/latest/en/helm/.

apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: ingress-controller-nginx
  namespace: kube-system
spec:
  repo: https://kubernetes.github.io/ingress-nginx
  chart: ingress-nginx
  version: 3.7.1
  targetNamespace: kube-system

Volume mappen

Jetzt muss man beim Start von dem K3D Cluster den Parameter volume übergeben, sodass die Datei helm-ingress-nginx.yaml in den Container in den Pfad gemappt wird.

volume "$(pwd)/helm-ingress-nginx.yaml:/var/lib/rancher/k3s/server/manifests/helm-ingress-nginx.yaml"

Damit wird beim Start des Clusters nun NginX als Ingress Controller automatisch deployt.

K3D

In der aktuellen Version von K3D wird in K3S CoreDNS für die Namesauflösung verwendet. Leider ist der Upstream Nameserver auf 8.8.8.8 voreingestellt, sodass es aus den Containern zu Problemen kommen kann, wenn man einen eigenen DNS hat und den für die Namensauflösung der Ingresses in dem Cluster sorgt.

So kann ein Ingress aus einem anderen POD heraus nicht über die Ingress URL aufgerufen werden.

Konfiguration des CoreDNS

Die Konfiguration erfogt über die Datei Corefile im Namespace kube-system.

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        hosts /etc/coredns/NodeHosts {
          ttl 60
          reload 15s
          fallthrough
        }
        prometheus :9153
        forward . 192.168.2.1
        cache 30
        loop
        reload
        loadbalance
    }

Hier ist die Zeile mit forward . 192.168.2.1 Interessant. Diese bestimmt den Upstream DNS Server für CoreDNS. Hier muss also der lokale DNS eingetragen werden, dann kann man das Manifest anwenden und der DNS ist umkonfiguriert. Dann sollte die Namensauflösung in den Containern funktionieren.

Netdata

Netdata beitet ähnlich zu dem Gespann Prometheus/Grafana eine umfassende Monitoring Lösunng an.

Installation

Die Installation von Netdata ist unter dem Kubernetes Cluster mit K3D mit Fallstricken versehen.

Nach erfolgreicher Basisinstallation stellt sich Netdata wie folgt vor:

Worauf muss man nun genau bei der Installation achten? Wer keine weiteren Anpassungen bei dem Kreieren des K3D Cluster vornimmt, der installiert automatisch Traefik v1.7 in den Cluster. Dieses verursacht mit dem bereitgestellten Helm Chart Probleme, da es auf NginX als Ingress-Controller ausgerichtet ist.

Traefik als Ingress-Controller verwenden

Unter Kubernetes lässt sich der zu verwendende Ingress-Controller bestimmen. Dazu muss die kubernetes.io/ingress.class auf traefik gesetzt werden.

Mit Helm 3 hat sich die Syntax geändert, sodass viele Informationen die man im Internet zu dem Thema findet schlicht veraltet sind und somit zu einer Fehlermeldung für. Wie kann man nun die ingress.class mit Helm setzen?

--set ingress.annotations."kubernetes\.io/ingress\.class"=traefik

Es muss die Annotation in Anführungsstrichen gesetzt werden und Punkte müssen mit dem “\” Escaped werden. Also wird somit aus kubernetes.io/ingress.class=traefik folgendes “kubernetes.io/ingress.class”=traefik

DockerHub Registry verwenden

Da es beim 1. Test Probleme mit der Registry gab, habe ich kurzerhand die offizielle Docker Hub Registry verwendet. Diese wird über registry.hub.docker.com angesprochen. Die Registry lässt sich über image.registry steuern.

--set image.registry=registry.hub.docker.com

Danach konnte das image sofort heruntergeladen werden.

Das Repo zu Helm hinzufügen

Die Helm Charts sind auf GitHub unter https://netdata.github.io/helmchart/ gehostet.

helm repo add netdata https://netdata.github.io/helmchart/
helm repo update

Zusammenfassung

Faskst man alles zusammen ergibt sich folgende Befehlsreihenfolge:

helm repo add netdata https://netdata.github.io/helmchart/
helm repo update

helm install netdata netdata/netdata \
  -n netdata \
  --create-namespace \
  --set ingress.hosts[0]=netdata.k3d.duckdns.org \
  --set image.registry=registry.hub.docker.com \
  --set ingress.annotations."kubernetes\.io/ingress\.class"=traefik

Nach dem Deployment kann man Netdata unter https://netdata.k3d.duckddns.org aufrufen,

K3D Kubernetes Cluster

Ein Kubernetes Cluster ist nach außen hin für die laufenden Services abgeschottet. Das heißt man kann nicht von außen auf die laufenden Dieste zugreifen.

Um Dienste zugänglich zu machen, kann man Ports exposen oder ein Ingress verwenden. Mit Ingress (auf einem LoadBalancer) kann über den Host im Header der Service identifiziert werden. Erfolgt nun eine Namensauflösung z.B. https://demo.k3d.duckdns.org auf ihre öffentliche IP Adressen, dann kann ein Reverse Proxy die Anfragen entgegennehmen und an den Cluster intern weiterleiten.

Der Ingress-Controller wertet nun die Information in dem Header aus und entscheidet das Routing innerhalb des Clusters.

In diesem Artikel möchte ich zeigen, wie man mit NginX, Duckdns und K3D eine flexible Lösung erstellt, in der automatisch alle Endpoints über TLS gesichert sind.

NGinX

Damit das Ganze funktioniert sind ein paar Voraussetzungen zu erfüllen:

  • Es muss ein gültiges Zertifikat für die Domain vorliegen (siehe Wildcard Zertifikat mit Lets Encrypt)
  • Eine DynDNS oder entsprechend konfigurierter DNS Server oder Host Einträge müssen vorliegen
  • Der Server Block in NginX muss die Anfrage matchen
  • Ein paar nötige Header müssen gesetzt werden

HTTP auf HTTPS umlenken

Mit einer 301 Antwort kann den Traffic auf HTTPS umlenken.

    # Redirect http -> https
    server {
        listen 80;
        server_name "~^.+\.k3d\.duckdns\.org$";
        return 301 https://$host$request_uri;
    }

Wichtig: Es darf hier nicht $server_name verwendet werden! Es muss $host genommen werden, da es sonst zu Fehlern im Browser kommt. Dann enthält der Header location die RegEx und der Browser spuckt eine Fehlermeldung aus.

Server_Name matching

Da ich nicht für jede neue Anwendung eine eigenständige Konfiguration für NginX schreiben möchte, habe ich NginX so konfiguriert, dass es Pattern Matching in dem Server_Name betreibt.

Ich habe für den lokalen Kubernetes Cluster das Schema https://keycloak.k3d.duckdns.org verwendet.

server {
    listen 443 ssl http2;

    server_name "~^+\.k3d\.duckdns\.org$";
...
}

Die RegEx nimmt alle Anfragen für https://XXXXXX.k3d.duckdns.org entgegen.

Header setzen

Im NGINX Server Block müssen folgende Header gesetzt sein, damit der Ingress-Controller das Routing vornehmen kann.

proxy_set_header X-Forwarded-For $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_set_header Host $host;

Die PROXY_PASS Anweisung leitet nun Anfragen an den Cluster weiter.

proxy_pass http://10.10.10.10:4000;

Der Cluster läuft in diesem Fall auf dem Server mit der IP Adresse 10.10.10.10 und lauscht auf dem Port 4000.

TLS konfigurieren

Für die Absicherung der Verbindung mit TLS, kommt folgender Block in der Konfiguration zum Einsatz. Per Default werden die von dem Cert-Bot aktualiesierten SSL Zertifikate unter halb den Verzeichnisses /etc/letsencryp/live/DOMAIN/ abgelegt. Die Fullchain und der private key werden eingebunden und somit der Endpoint mit TLS abgesichert.

# SSL
ssl_certificate /etc/letsencrypt/live/k3d.duckdns.org/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/k3d.duckdns.org/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

Zusammenfassung der Konfiguration von NginX

Hier nun die gesamte Konfiguration von NginX.

###################################
#                                 #
# Kubernetes Cluster              #
#                                 #
#                                 #
###################################

# Redirect http -> https
server {
    listen 80;
    server_name "~^.+\.k3d\.duckdns\.org$";
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;

    server_name "~^-.+\.k3d\.duckdns\.org$";

    # logging
    error_log /var/log/nginx/kubernetes_error.log debug;
    access_log /var/log/nginx/kubernetes_access.log;

    location / {
        proxy_pass http://10.10.10.10:4000;
        proxy_set_header Connection ""; # to keep alive

        proxy_set_header X-Forwarded-For $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection ‘upgrade’;
        proxy_set_header Host $host;
    }

    # SSL
    include ssl/*.k3d.duckdns.org;
}

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

Einen Cluster Admin Account erstellen

Hat man K3d aufgesetzt, so braucht man oftmals noch ein Token um zum Beispiel den Cluster über dritte Anwendungen zu administrieren.

Einen Kubernetes Serviceaccount erstellen

Zunächst benötigen wir einen Serviceaccout. Diesen kann man kubectl create serviceaccout einfach erstellen. Es werden keine weiteren Parameter benötigt.

kubectl create serviceaccount admin

RBAC – Clusterrolebinding

In Kubernetes werden die Berechtigung über RBAC gesteuert. Es gibt hier 2 Arten der Bindung. Eine Bindung die eine Rolle innerhalb eines Namespaces zuweist oder halt eben das Clusterrolebinding welches die Rolle Clusterweit zuweist.

Das Clusterrolebinding wird mit kubectl create clusterrolebinding kreiert. Als Parameter sind ein Name, die Rolle (hier also cluster-admin) und der zuvor erstellte Serviceaccountname nötig.

kubectl create clusterrolebinding admin --clusterrole=cluster-admin --serviceaccount=default:admin

Das Token extrahieren

Jetzt wird es etwas komplizierter, da wir zunächst den Namen des Serviceaccount benötigen. Dann können wir das Token mit kubectl get secret aus dem Serviceaccount auslesen.

Namen des Serviceaccount ermitteln

 kubectl get serviceaccount admin -o jsonpath='{range .secrets[*]}{.name}{"\n"}{end}' | grep kubeapps-operator-token
 admin-token-bfj2q

Das Base64 kodierte Token auslesen

Den Names des Serviceaccounts verwenden wir nun, um das Base64 kodierte Token mit der Hilfe von go-template zu dekodieren.

kubectl get secret admin-token-bfj2q -o go-template='{{.data.token | base64decode}}'

Bash Skript

Hier habe ich das Ganze als kurze Bash Skript zusammengefasst. Es benötigt nur einen Parameter. Es muss der Name für den Cluster Administrator angegeben werden.

#!/bin/bash

if [ $# -eq 0 ]; then
  echo "give $0 a parameter name" 
  exit
fi

NAME=$1

kubectl create serviceaccount $NAME
kubectl create clusterrolebinding $NAME --clusterrole=cluster-admin --serviceaccount=default:$NAME
kubectl get secret $(kubectl get serviceaccount $NAME -o jsonpath='{range .secrets[*]}{.name}{"\n"}{end}' | grep $NAME-token) -o go-template='{{.data.token | base64decode}}' && echo

Gitea Helm Chart

Seit kurzem gibt es ein Gitea Helm Chart das von Gitea betreut wird. In diesem Artikel zeige ich wie man einfach eine neue Instanz von Gitea mit K3D ausetzen kann.

Install on K3D/K3S Cluster

Die Installation mittels Helm ist einfach. Zunächst muss das Repository von Gitea hinzugefügt werden. Ein obligatorisches helm repo update aktualisiert alle Repositorys, so dass nun eine Installation erfogen kann.

Für die Installation sind minimale Parameter anzupassen:

Parameter Beschreibung Wert
persistence.size PVC Größe Gitea 100Mi
postgresql.persistence.size PVC Größe Postgres 100Mi
ngress.enabled Ingress erlauben true
ingress.hosts[0] Host FQDN gitea.XXX.org
persistence.storageClass StorageClass local-path

Achtung: K3D/K3S erzeugt automatisch eine Storage Class local-path. Der Name der Storage Class muss daher hier in dem Gitea Helm Chart angepasst werden.

helm repo add gitea-charts https://dl.gitea.io/charts/
helm repo update

helm install gitea gitea-charts/gitea \
    -n gitea --create-namespace \
    --set persistence.size=100Mi \
    --set postgresql.persistence.size=100Mi \
    --set ingress.enabled=true \
    --set ingress.hosts[0]=gitea.XXX.org \
    --set persistence.storageClass=local-path

KeyCloak mit WebAuthn

Ziel dieser Reihe soll es werden Anwendungen über WebAuthn zu schützen. Dazu wird ein K3S Cluster mit K3D aufgesetzt. Diese soll über .cluster.local erreichbar sein.

  • Im Ersten Teil beschäftige ich mich mit der Installation einer KeyCloak Instanz in einem K3S Cluster.

  • Im zweiten Teil wird die Demoanwendung (Gitea) deployt

  • Im dritte Teil geht es um die Konfiguration von KeyCloak, sodass die Anwendung von WebAuthn gescchützt wird

K3D Setup

Um den Cluster aufzusetzen werde ich K3D verwenden.

K3D installieren

Die Installation habe ich für Manjaro/Arch Linux bereits in dem Artikel K3D Cluster ausfsetzen beschrieben. Anmerkung: Die aktuelle Version kann nun mit yay bereits aus AUR gezogen werden.

K3D Cluster erstellen

Für diese Reihe erstelle ich einen kleinen Demo Cluster mit 2 Knoten und öffne den Port 8080 für den LoadBalancer. D.h. der NginX Reverse Proxy muss später auf den Host und Port 8080 verweisen, so dass die Anfragen vom KeyCloak dann beantwortet werden können.

k3d cluster create demo -a2 -p 8080:80@loadbalancer -p 8443:443@loadbalancer

Achtung: Die Syntax von K3D hat sich seit Version 3.0.0 geändert und folgt nun den anderen K8S Anwendungen, in dem es Nomen und Verb als Parameter verlangt. Bsp: aus k3d create cluster wurde nun k3d cluster create.

Namespace

Wie immer sollte mna einen eigenen Namespace für die Trennung der Anwendung verwenden. Diesen legen wir zuerst mit:

k create namespace keycloak

an.

Hinweis: K ist bei mir immer ein Alias für kubectl.

Self Signed Certificate ausstellen

Installation Cert-Manager

Die Installation von Cert-Manager wird hier beschrieben.

Selbst Signiertes Zertifikat ausstellen

Zunächst müssen wir ein Manifest erstellen, das einen Issuer und ein Certificate beschreibt. Die Domain wird hier auf *.clouster.local festgelegt.

apiVersion: cert-manager.io/v1alpha2 
kind: Issuer
metadata:
   name: selfsigned-issuer
spec:
   selfSigned: {}

---

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
   name: first-tls
spec:
   secretName: first-tls
   dnsNames:
   - "*.cluster.local"
   issuerRef:
     name: selfsigned-issuer

Jetzt muss das Manifest angewendet werden und der Cert-Manager erstellt für uns das selbst signierte Zertifikat, welches wir in dem Ingress später referenzieren werden.

k apply -n keycloak -f keycloak-cert.yaml

Überprüfung der Ausstellung

Ein paar Schnelltests geben auskunft über die erfolgreiche Erstellung der Zertifikate:

# Zertifikat überprüfen
k -n keycloak get certificate
# Secret überprüfen
k -n keycloak get secret first-tls

Nun zum Abschluss noch mit OpenSSL überprüfen…

openssl x509 -in <(kubectl -n keycloak get secret first-tls -o jsonpath='{.data.tls\.crt}' | base64 -d) -text -noout

…in der Ausgabe erhält man dann die Informationen…

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2e:df:ae:86:5c:27:f9:25:bf:77:ca:d1:7a:3a:48:c6
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: 
        Validity
            Not Before: Sep  2 08:14:52 2020 GMT
            Not After : Dec  1 08:14:52 2020 GMT
        Subject: 
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:c5:e0:f9:be:a6:b9:41:cb:38:e9:11:57:0a:1b:
                    b5:2b:c2:7e:78:87:5f:43:dc:22:c3:7d:8b:a7:f3:
                    c0:d4:f9:bc:75:4e:96:93:66:17:67:f7:e2:02:96:
                    37:19:90:64:6f:fa:c3:1f:c5:21:80:de:e0:aa:76:
                    12:d6:24:a0:f2:7b:37:14:34:a8:eb:9c:1a:17:b0:
                    4f:d8:a4:9b:3a:51:fe:18:30:3e:81:f5:20:01:85:
                    c1:af:61:cf:2e:30:fd:42:3c:00:c0:28:f9:60:37:
                    84:80:84:85:54:33:6c:0f:cb:c2:7e:5f:50:ee:82:
                    a1:4a:35:c3:5b:fe:8a:47:21:75:c5:0e:03:08:f2:
                    2d:fa:98:e8:d6:16:d6:fb:af:97:d8:86:3a:c6:84:
                    63:5d:bd:f1:1b:72:0f:73:f5:09:33:26:aa:bc:8f:
                    8c:9b:fa:a6:11:53:19:69:33:bc:68:47:c3:74:6a:
                    70:86:c5:19:93:83:cc:9e:07:11:0d:6e:9f:f8:5b:
                    67:d7:d8:ef:ca:37:4e:7c:1b:a2:f5:ee:70:eb:55:
                    2f:86:45:02:b4:4d:6d:9a:1b:20:3b:c4:d5:db:f3:
                    66:8c:22:e1:da:94:c4:e6:20:9f:c4:ff:79:b9:26:
                    b6:ae:d0:8f:f2:45:d5:7d:eb:88:7f:39:36:7d:ef:
                    f6:85
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name: critical
                DNS:*.cluster.local
    Signature Algorithm: sha256WithRSAEncryption
         39:b5:cf:d7:08:b1:9d:07:44:ef:79:f3:13:46:11:f9:07:96:
         f3:db:cb:8d:5e:df:14:5f:2f:74:ff:4a:c8:58:af:57:fa:35:
         fb:19:1e:73:af:f5:d2:eb:ec:b9:d1:60:f5:28:c1:39:ba:a1:
         0c:4e:0d:3c:10:83:ba:0f:ef:4f:7a:1c:68:25:3a:3c:bf:de:
         04:24:f0:ca:15:34:6d:66:8f:3b:69:96:fe:b8:03:54:98:a6:
         fe:b8:0f:d4:6f:1b:7a:87:6a:5a:c6:57:ff:62:ee:0f:24:ff:
         e9:e8:e9:b5:4d:ca:ec:27:7c:03:7b:63:2e:ff:4d:3a:c8:5e:
         d8:b4:f5:8a:e8:0c:2c:62:f1:00:c6:4d:fe:cf:45:e2:5b:74:
         55:0a:fe:f7:5a:b4:c0:5a:2c:04:4c:ae:b2:5a:d3:d7:26:ca:
         63:2c:69:2b:81:cd:6e:39:c4:66:5f:67:47:2d:f4:ea:eb:9b:
         31:17:5d:4c:5b:77:26:d4:a4:4c:f1:52:ae:92:84:e9:f4:01:
         7e:f1:f5:cf:1d:54:a5:8c:6b:58:b2:35:b3:44:0d:81:b6:da:
         4e:0b:02:fe:21:21:75:59:53:15:17:67:7e:37:00:59:00:11:
         67:47:4e:5f:0b:1d:c4:1e:4b:5c:d2:80:57:7f:2b:58:01:ba:
         83:fc:c9:ce   

Download Kubernetes Manifest

Wir laden das Manifest keycloak.yaml mit wget runter und modifizieren die Defaultwerte für den Namespace und setzen ein neues Passwort. Der Namespace wird auf den zuvor erstellten Namespace keycloak gesetzt. Das Passwort wird auf 123 gesetzt.

wget -q -O - https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/kubernetes-examples/keycloak.yaml | sed "s/namespace: default/namespace: keycloak/" > keycloak.yaml

Achtung: Username und Passwort sind hier admin. Wer es sicherer mag, der sollte das YAML bearbeiten und die Werte ersetzen.

k apply -n keycloak -f keycloak.yaml   

Das hochfahre der Pods kan mit

watch kubectl -n keycloak get pods

überwacht werden.

Ingress

Da K3S in der Defaulteinstellung Traefik als Ingress Controller verwendet, nutze ich hier nicht die von KeyCloak Team bereitgestelltes Kubernetes Manifest für Ingress.

HTTPS Anfragen für die FQDN keycloak.cluster.local an den Cluster werden werden so an den Service keycloak an Port 8443 weitergeleitet.

apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}

---

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: first-tls
spec:
  secretName: first-tls
  dnsNames:
  - "*.cluster.local"
#  - "*.keyclaok"
  issuerRef:
    name: selfsigned-issuer

Hosts Datei Vorbereiten

Damit das Ganze funtkioniert, muss der FQDN keycloak.cluster.local in die /etc/hosts Datei eingetragen werden:

192.168.2.XXX keycloak.cluster.local

Erster Test mit CURL

curl -k https://keycloak.cluster.local:8443
<!--
  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
  ~ and other contributors as indicated by the @author tags.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~ http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
    <meta http-equiv="refresh" content="0; url=/auth/" />
    <meta name="robots" content="noindex, nofollow">
    <script type="text/javascript">
        window.location.href = "/auth/"
    </script>
</head>
<body>
    If you are not redirected automatically, follow this <a href='/auth'>link</a>.
</body>
</html>

Aufruf mit dem Browser

Nun kann nach dem ersten erfolgreichen Test der KeyCloak über https://keycloak.cluster.local:8443/auth/ bzw. die Admin-Console über https://keycloak.cluster.local:8443/auth/admin/master/console/ aufgerufen werden. Die Credentials für die Admin-Console sind im Kubernetes Manifest (siehe oben) festgelegt worden.

Standard ist hier Username admin und Passwort admin.

Kubernetes mit Manjaro

Diese Liste wird ständig von mir erweitert und unterliegt daher der Änderung.

Lokale Kubernetes Cluster

Name Beschreibung Homepage
minikube Der Standard um Kubernetes lokal zu testen https://minikube.sigs.k8s.io/docs/
k3s Minimale Kubernetes Cluster basierend auf einem einzigen Executable https://k3s.io/
k3d Mit K3D kann man lokal ein Kubernetes Cluster aus mehreren Nodes innerhalb von Sekunden erzeugen. Intern werden Docker Container mit K3S, um die Nodes zu erzeugen. Es ist zu empfehlen hier auf das Beta der Version 3 zu wechseln. https://github.com/rancher/k3d
k3sup K3sup ist ein Tool um K3S lokal oder per SSH auf einem entfernten Rechner zu installieren. Da k3sup in GO geschrieben ist, besteht es auch nur aus einem Binary und besitzt keien weiteren Abhängigkeiten https://github.com/alexellis/k3sup
k3c https://github.com/rancher/k3c
yay --noconfirm -S minikube k3s-bin rancher-k3d-beta-bin

Kubernetes Tools

Introspektion

Name Beschreibung Homepage
k9s Kommandoszeilentool mit dem man sehr einfach und schnell einen bestehenden Cluster untersuchen kann. Universelles Tool das man mit dem Kubernetes Dashboard für die Konsole vergleichen kann. https://github.com/derailed/k9s
kubespy
kubectx
kubefwd Findet alle Services in einem Namespace und erstellt ein Portforwarding für den Dienst ein und erstellt einen Eintrag in der /etc/hosts Datei, sodass sehr einfach auf die laufenden Dienste zugegriffen werden kann https://github.com/txn2/kubefwd
yay --noconfirm -S kubespy kubectx kubefwd-bin

Logging

Name Beschreibung Homepage
stern Mit Stern kann man die Logausgaben meherer Container in mehreren Pods ausgeben lassen. Für eine gute Unterscheidbarkeit werden die Ausgaben der verschiedenen Container in unterschiedlichen Farben eingefärbt. Dieses erlaubt ein schnelleres Debugging in komplexen Setups https://github.com/wercker/stern
yay --noconfirm -S stern-bin

Development

Name Beschreibung Homepage
tilt Mit Hilfe von einem Autodeployment in ein Kubernetes Cluster, werden Codeänderungen sofort wirksam und es werden Fehler überrsichtlich in einer Web UI dargestellt. https://tilt.dev/
yay -S --noconfirm  tilt-bin