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

Kubectl Autovervollständigung für die Bash

Das zentrale Administrationsprogramm kubectl bietet die Möglichkeit Bash Completion zu erstellen, so dass die Autovervollständigung funktioniert.

Bash Completion einbauen

Zunächst muss die aktuelle Beschreibung der Autovervollständigung erzeugt und unter /etc/bash_completion gespeichert werden.

sudo kubectl completion bash > /etc/bash_completion.d/kubectl

Sofortige Wirkung

Die neue Autovervollständigung würde erst ziehen, wenn man sich an einer neuen Sitzung der Bash anmeldet. Es gibt aber auch die Möglichkeit mit source dieses zu umgehen.

 source /etc/bash_completion/kubectl

Jetzt sollte die Autovervollständigung in der Bash für kubectl funktionieren.

k als Alias für kubectl

Wer k als Alias für kubectl gesetzt hat wird enttäuscht sein, da es nämlich nicht wie erwartet funktioniert. Für das Komando k sind die Autovervollständigungen schlicht nicht definiert.

Fügen sie complete -F __start_kubectl k mit in ihre .bashrc ein. Dann wird auch das Alias k die Autovervollständigung anzeigen.

echo 'complete -F __start_kubectl k' >>~/.bashrc

Lens

Lens plattformunabhängiges Dashboard für Kubernetes Cluster. Es integriert sogar die Installation von Helm Charts aus einem Helm Repository von der UI. Hier lassen sich vor der Installation Parameter anpassen. Installierte Charts können auch wieder entfernt werden. Getestet habe ich das mit einem lokalen K3D Cluster.

Insgesamt macht das Programm von seinem Umfang und der Optik einen guten Eindruck.

Installation

Die Installation geht unter Manjaro oder Arch Linux schell mit yay:

yay -S --noconfirm lens-bin 

ArgoCD Ingress patchen

In einem ArgoCD Cluster habe ist in dem Ops Repository in dem Ingress ein anderer Host angegeben, als den den ich gerade in dem laufenden Cluster benötige.

Eine Änderung (ein Commit) kam für den schnellen Test nicht in Frage und ein neues Repository wollte ich auch nicht dafür erstellen. Also musste das Ingress gepatcht werden.

Die Liferay Instanz läuft in dem Namespace liferay-prod und der FQDN soll auf k8s-liferay.domain.de geändert werden. Hierfür eignet sich jq hervorragend. Es wird das Value für den Host gesetzt und per Pipe direkt wieder angewendet.

k get -n liferay-prod ing/nginx-ingress -o json | jq '(.spec.rules[].host) |= "k8s-liferay.domain.de"' | kubectl apply -f -

Installation von CodiMD in einen K3D Cluster

CodiMD ist ein Webbasierter Editor für Markdown und Extensions. In diesem Artikel beschreibe ich kurz die Probleme die ich beim Deployment in einem K3D Cluster hatte, bevor ich die Anwendung lokal nutzen konnte.

Installation von CodiMD mit Helm

Bei der Installation von CodiMD sind insgesamt 2 Probleme aufgetaucht, die eine reibungslose Installation verhindert haben.

Docker Registry

Bei meinem Versucht die Installation durchzuführen, schlug immer das Downloaden des Images von CodiMD fehl. Erst die Änderung des Registry Eintrags in dem Helm Chart auf die standard Docker Hub Registry, vermag das Image hackmdio/hackmd zu pullen.

image:
  pullPolicy: Always
  pullSecrets: []
  registry: registry.hub.docker.com
  repository: hackmdio/hackmd
  tag: 2.1.0

Die Storage Class ist nicht gesetzt

PVC konnte nicht geclaimt werden. In der Default Einstellung steht Storage Class auf ‚-‚, was aber anscheinend nicht dem Default aus Kubernetes entspricht, sodass kein Claim gesteckt werden kann. Und somit fährt der CodiMD Container nie hoch. Erst das Setzen der Storage Class auf local-path schafft hier abhilfe.

  imageStorePersistentVolume:
    accessModes:
    - ReadWriteOnce
    enabled: true
    size: 10Gi
    storageClass: local-path
    volumeMode: Filesystem

K3D / K3S Storage class

K3S unterstützt OOTB die Kubernetes Storage Class local-path. Diese ist auch die default Einstellung in Kubernetes, was man mit kubectl get storagesclass leicht überprüfen kann.

k get storageclass
NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path (default)   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  14d

yq ist das Schweizer Messer für YAML Dateien

Leider gibt es zwei Programme die den Namen yq besitzen und auch den selben Zweck erfüllen. Beide Programme behandeln YAML Dateien auf der Konsole.

In diesem Artikel beschreibe ich die Version von Mike Farah. Für Arch basierende Distributionen wie Manjaro gibt es yq allerdings noch nicht.

Das PKGBUILD

Leider gibt es im AUR Repository noch keinen Eintrag, sodass ich kurzerhand das folgende PKGBUILD zusammengestrikt habe.

# Maintainer: Sascha Pfau

pkgname=yq
pkgdesc="portable command-line YAML processor written in Go"
pkgver=3.3.4
pkgrel=0
arch=('i686' 'x86_64')
url="https://github.com/mikefarah/yq"
license=('MIT')
makedepends=('go' 'rsync')
source=("https://github.com/mikefarah/yq/archive/${pkgver}.tar.gz")
sha256sums=('b0c44a742a9b6eed25a48ff04bb30e3e05c6c2d5a0c869f9d0d7f778dfd40f05')

# See https://wiki.archlinux.org/index.php/Go_package_guidelines
prepare(){
  cd "$pkgname-$pkgver"
  mkdir -p build
}

build() {
  cd "$pkgname-$pkgver"
  GOPATH="$srcdir" go build -v 
}

package() {
  install -Dm755 "$pkgname-$pkgver"/$pkgname "$pkgdir"/usr/bin/$pkgname
}

Funktionsübersicht

In der folgenden Tabelle sind die grundlegenden Kommandos aufgeführt.

Kommando Beschreibung
read Werte auslesen
validate
compare YAML Dateien vergleichen
write Werte schreibe
create YAML Dateien erstellen
delete
merge
prefix

Bash completion

Kubernetes Konfiguration bearbeiten

Da Kubernetes die Manifeste in YAML Dateien sichert und einliest, eignet sich yq hervoragend um diese zu bearbeiten. Die herkömmlichen Tools awk, sed etc. kommen hier schnell an ihre Grenzen. Zumal yq auch mit multi document YAML Dateien umgehen kann.

Beispiel

In dem Beispiel verwende ich ein Gitea Konfiguration die aus einem Dokument besteht.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: gitea
  namespace: env
  labels:
    name: gitea
spec:
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: gitea
    spec:
      # Initial rights settings when creating disk can be incorrect
      # for the git user in the gitea container: Use init container to set the rights
      initContainers:
        - name: init-disk
          image: busybox:latest
          command:
            - /bin/chown
            - 1000:1000
            - /data
          volumeMounts:
            - name: gitea
              mountPath: "/data"
      containers:
        - name: gitea
          image: "gitea/gitea:latest"
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
            - containerPort: 22
          volumeMounts:
            - name: gitea
              mountPath: "/data"
            - name: gitea-config
              mountPath: /data/gitea/conf
          resources:
            requests:
              cpu: 10m
              memory: 50Mi
            limits:
              cpu: 1
              memory: 200Mi
      volumes:
        - name: gitea
          persistentVolumeClaim:
            claimName: gitea
        - name: gitea-config
          configMap:
            name: gitea-config
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: gitea-ingress
  namespace: gitea
  annotations:
    traefik.ingress.kubernetes.io/affinity: "true"
spec:
  rules:
    - host: k8s-gitea.domain.duckdns.org
      http:
        paths:
          - backend:
              serviceName: gitea
              servicePort: 443
            path: /
---
apiVersion: v1
kind: Service
metadata:
  name: gitea
  namespace: env
  labels:
    name: gitea
spec:
  ports:
    - name: gitea
      port: 443
      targetPort: 3000
    - name: gitea-ssh
      port: 22
      targetPort: 22
  selector:
    name: gitea
  type: ClusterIP
  sessionAffinity: ClientIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: gitea
  name: gitea
  namespace: gitea
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
---
apiVersion: v1
kind: Namespace
metadata:
  labels:
    name: gitea
  name: gitea

Für die Nutzung des Manifests sind zuvor noch der Host in dem Ingress angepasst werden.

Host lesen

yq r -d1 install.yaml spec.rules[0].host

Gibt den Value des Hosts aus:

k8s-gitea.domain.duckdns.org  

Host überschreiben

yq w -i -d1 install.yaml spec.rules[0].host k8s-gitea.neuedomain.duckdns.org

KeyCloak mit WebAuthn – Teil 2

Im Ersten Teil ( KeyClaok mit WebAuth ) haben wir das Setup für den K3S Cluster vorgenommen und KeyCloak darin deployt.

In diesem Zweiten Teil soll nun unsere Beispielanwendung in den Cluster deployt werden. Hierzu werden wir Gitea per Helm Chart installieren. Die Grundlage dafür kann unter https://chartcenter.io/k8s-land/gitea nachgelesen werden.

Das Repository vom Helm Chart hinzufügen

Für das Helm Chart müssen wir ein Repository für Gitea hinzufügen. Ich verwende in diesem Beispiel das von k8s-land.

helm repo add k8s-land https://charts.k8s.land

Die Values Datei anpassen

Die Values extrahieren und Einstellungen anpassen. Dazu laden wir sie mit dem helm show values Kommando herunter und speichern sie in der Datei values.yaml ab.

helm show values k8s-land/gitea > values.yaml

Die values.yaml werden wir im nächsten Abschnitt anpassen, damit die Anwendung nach unseren Gegebenheiten ordnungsgemäß funktioniert.

Anpassungen

Damit das Chart mit dem Beispiel funktioniert, müssen in der values.yaml Datei einige Änderungen für den Ingress-Controller vorgenommen werden.

Ingress (Traefik)

Wir wollen den Cert-Manager verwenden, um TLS für Gitea bereitzustellen. D.h. der Ingress-Controller lauscht auf Port 443, welcher beim Setup von K3d auf Port 8443 gemappt worden ist.

certManager: true

TLS muss für den Host gitea.cluster.local konfiguriert werden. Wir verwenden das Zertifikat first-tls aus dem ersten Teil der Artikelserie wieder.

  tls:    
  - hosts:    
    - gitea.cluster.local
  secretName: first-tls

Der ServiceType muss auf LoadBalancer umgeändert werden.

serviceType: LoadBalancer

Damit Gitea die korrekten URL und Port setzt, müssen wir es über die Parameter externalHost und externalPort propagieren.

    externalPort: 8443
    externalHost: gitea.cluster.local

MariaDB

Es ist für dieses Beispiel nicht direkt nötig, aber wir setzen hier ein statisches Passwort für den User gitea.

password: gitea

Root Passwort

password: root

Helm Chart installieren

Für das Deployment wird ein eigener Namespace gitea verwendet.

helm install gitea k8s-land/gitea -f values.yaml -n gitea --create-namespace

Diesen geben wir mit dem Parameter -n gitea mit an und dieser wird wegen dem Parameter –create-namespace bei der Installation gleich automatisch angelegt.

Test

Wenn der Service bereitsteht, dann sollte sich Gitea unter https://gitea.cluster.local:8443/ öffnen lassen.

Uninstall

helm uninstall -n gitea gitea
k delete namespace gitea

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.

Cert-Manager

Installation

Wie immer erstelle ich zunächst eine lokale Kopie des Manifests mit wget:

 wget https://github.com/jetstack/cert-manager/releases/download/v0.16.1/cert-manager.yaml -q -O install.yaml

Nun können wir das Manifest anwenden. Wie bereits im Kommentar zu erkennen ist, ist es hier wichtig NICHT den Namespace bei apply anzugeben. Dieses führt später zu Fehlern und es lassen sich kein Zertifikate erstellen.

 k apply -f install.yaml # Achtung hier kein Namespace angeben, da es sonst Fehler gibt

Den Abschluss des Deployments kann mit watch überwacht werden. Es sollte ziemlich schnell gehen, da die Anwendung relativ klein ist.

 watch kubectl get pods --namespace cert-manager