Neuigkeiten von trion.
Immer gut informiert.

Default TLS Zertifikat in Kubernetes

Die Absicherung von HTTP Zugriffen mittels TLS (früher SSL) ist spätestens seit den Enthüllungen von Edward Snowden auch für Anwendungen außerhalb von Banken und Medizin zum Standard geworden. Vor allem Dank des kostenlos nutzbaren Let’s Encrypt sind auch die - früher teils horrenden - Kosten kein Grund mehr, auf TLS zu verzichten.
Die meisten Zertifikatanbieter, die das durch Let’s Encrypt eingeführte ACME Protokoll unterstützen, bieten bei Verwendung der DNS Challenge auch Wildcard Zertifikate an. Wird für einen Kubernetes Cluster primär mit Hostnamen in einer Domain oder Subdomain gearbeitet, so bietet sich ein Wildcard Zertifikat entsprechend an. Damit kann unter Umständen sogar der Einsatz des häufig zusätzlich zur Ingress Implementierung betriebenen Cert Manager entfallen: Dazu würde das Wildcard-Zertifikat als Default TLS Zertifikat im Ingress Controller konfiguriert werden/

Wie das funktioniert, wird im folgenden Beitrag beschrieben.

Grundsätzlich sind die meisten Ingress Implementierungen in der Lage, sich TLS Zertifikate und das zugehörige Schlüsselmaterial aus Kubernetes Secrets zu beziehen. Das zeigt, wie sinnvoll es war, bei dem Design der Secret API direkt Secrets vorzusehen, die definieren, wie TLS Zertifikate als Secrets abzubilden sind.
So ein TLS Secret läßt sich mit kubectl aus dem Zertifikat und dem zugehörigen privaten Schlüssel beispielsweise wie folgt erzeugen:

Erzeugung eines TLS Secrets in Kubernetes
$ kubectl create secret tls sample-secret --cert=tls-certificate.pem --key=private-key.pem

Das so erzeugte Secret besitzt eine durch den Typ tls definierte Struktur: Unter tls.crt wird das Zertifikat bereitgestellt und unter tls.key der private Schlüssel. Damit kann es durch verschiedene Konsumenten genutzt werden, die sich auf die Struktur verlassen können.

Beispiel für Kubernetes TLS Secret
apiVersion: v1
kind: Secret
metadata:
  name: sample-secret
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS...
  tls.key: LS0tLS1C...

Wenn das Zertifikat ein Wildcard Zertifikat ist, kann dies genutzt werden, um Anwendungen TLS gesichert via Ingress unter einer gemeinsamen Domain anzubieten. Vor allem wenn dazu ein Wildcard DNS Eintrag genutzt wird, können damit neue Anwendungen unmittelbar bereitgestellt werden, ohne weitere Konfigurationen außerhalb von Kubernetes vornehmen zu müssen.

Wie die Konfigurationen der typischen Ingress Controller für ein Default TLS Zertifikat aussieht wird in den folgenden Abschnitten für die häufig anzutreffenden Ingress Implementierungen mit nginx, traefik und HA-Proxy gezeigt.
Für alle gilt: Das Secret, um das Zertifikat bereitzustellen, wird am besten im Namespace des jeweiligen Ingress Controller angelegt.

Ingress nginx Default Zertifikat

Der nginx Ingress Controller ist aus guten Gründen häufig anzutreffen:
Im offiziellen Kubernetes Tutorial wird der nginx Ingress Controller verwendet, entsprechend setzen ihn viele abgeleitete Tutorials in Blogs und Videos ein. Auch das Minikube Ingress Addon setzt auf den nginx Ingress Controller.

Der nginx Ingress Controller unterstützt verschiedene CLI Argumente. Für das Default-Zertifikat sieht es dabei so aus: --default-ssl-certificate=<namespace>/<secret-name>

Je nach Installationsverfahren (Minikube Addon, Manifest, Helm Chart) muss die Konfiguration an anderen Stellen vorgenommen werden. Im Helm Chart kann durch eine passende values.yaml oder mit --set der Parameter controller.extraArgs.default-ssl-certificate gesetzt werden, um das obige CLI-Argument zu definieren.

Wird ein Manifest verwendet, muss dies entsprechend angepasst werden:

spec:
  containers:
    - name: controller
      args:
        - /nginx-ingress-controller
        - --default-ssl-certificate=<namespace>/secret-name

Alternativ kann mit kubectl patch gearbeitet werden.

$ kubectl patch deployment "ingress-nginx-controller" \
    -n "ingress-nginx" \
    --type "json" \
    --patch '[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--default-ssl-certificate=default/certificate"}]'

Wird Minikube verwendet, so gibt es dafür ein dediziertes Kommando:

$ minikube addons configure ingress
-- Enter custom cert (format is "namespace/secret"): ...
✅  ingress was successfully configured

Anschließend kann das Addon durch minikube addons enable ingress aktiviert werden. Falls es bereits aktiviert war, sollte es zunächst durch disable deaktivier werden.

traefik Ingress Default Zertifikat

Der in go entwickelte und auch sehr beliebte Traefik Proxy ermöglicht ebenfalls die Konfiguration eines Default-TLS-Zertifikats. Allerdings ist die Konfiguration etwas aufwendet.

Zunächst wird eine gesonderte ConfigMap benötigt, die als Quelle für eine YAML Datei zur Konfiguration der eigentlichen trafik Anwendung dient. In dieser YAML Datei können feingranulare Einstellungen vorgenommen werden, so auch für die TLS Zertifikatquellen. Sowohl diese Datei als auch die darin referenzierten Zertifikate müssen noch im jeweiligen traefik Container als File-Mount bereitgestellt werden.

traefik Default-TLS Konfiguration
apiVersion: v1
kind: ConfigMap
metadata:
  name: traefik-tls
  namespace: traefik
data:
  tls.yaml: |
    tls:
      certificates:
        - stores:
            default
              defaultCertificate:
                certFile: /certs/default/tls.crt
                keyFile: /certs/default/tls.key

Die Einbindung erfolgt für die ConfigMap und das Secret mit dem zu verwendenden TLS Material wie bei Kubernetes üblich. Je nach verwendetem Betriebsmodell von traefik, z.B. als Deployment, Pod oder DaemonSet muss die Konfiguration des PodTemplate bzw. Pod angepasst werden.
Der folgende Ausschnitt zeigt die Anpassungen im YAML Manifest.

spec:
  template:
    spec:
      containers:
      - name: traefik
        volumeMounts:
        - name: tls-config
          mountPath: /data/config
        - name: default-secret
          mountPath: /certs/default


      volumes:
      - name: tls-config
        configMap:
          name: traefik-tls
      - name: default-secret
        secret:
          secretName: domain-tls

Diese Datei kann dann als Patch für ein Deployment oder DaemonSet genutzt werden, wird traefik als einzelner Pod betrieben muss entsprechende die Ebene "spec.template" entfernt werden. Nachdem der Patch angewandt wurde muss noch die gemountete Konfigurationsdatei als Startparameter für den traefik Container gesetzt werden. Beides zeigt das naechste Snippet.

kubectl -n traefik patch deployment traefik --type strategic --patch-file tls-patch.yaml
kubectl  -n traefik patch deployment traefik --type=json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--providers.file.directory=/data/config"}]'

HA Proxy Kubernetes Default Zertifikat

Analog zu dem nginx Ingress Controller stellt auch der HA-Proxy einen CLI Parameter zur Verfügung, um das Standard-Zertifikat zu konfigurieren.
Vergleichbar mit dem Patch von traefik im vorherigen Abschnitt muss der Parameter am Container als Argument gesetzt werden. Statt des imperativen Vorgehens ist hier ein YAML Patch als Beispiel zu sehen:

spec:
  containers:
    - name: controller
      args:
        - --default-ssl-certificate=<namespace>/default-tls-secret

Bei der Verwendung von Helm kann entsprechend die Helm Values datei um den Parameter controller.extraArgs.default-ssl-certificate erweitert werden bzw. bei der Installation des Helm Charts kann dies angegeben werden:

--set controller.extraArgs.default-ssl-certificate=<namespace>/<secret-name>

HA Proxy unterstützt dankenswerterweise den direkten Zugriff auf das Secret.

Fazit

Mit Wildcard TLS Zertifikat und Wildcard DNS lassen sich sehr leichtgewichtig verwaltbare Kubernetes Cluster betreiben. Alle typischen Ingress Implementierungen unterstützen die Verwendung von Kubeernetes Secrets um ein Standardzertifikat zu konfigurieren.




Zu den Themen Kubernetes, Docker und Cloudarchitektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Zur Desktop Version des Artikels