Feb 20, 2024 | Kubernetes, Tutorial

Ingress-NGINX mit Cert-Manager absichern

von

In einem der ersten Tutorials auf unserer Seite haben wir dir gezeigt, wie du Ingress-NGINX in deinem Cluster installieren und einrichten kannst. Heute gehen wir einen Schritt weiter und schauen uns an, wie du Ingress-NGINX und deine Services mit Hilfe von TLS-Zertifikaten durch Cert-Manager absichern kannst!

Was ist Cert-Manager?

Cert-Manager ist ein CNCF-Projekt zur automatischen bzw. programmatischen Bereitstellung von TLS-Zertifikaten. Das Programm beobachtet kontinuierlich annotierte Ressourcen (z.B.  Ingress  Objekte) und eine Sammlung an  CustomResourceDefinitions  um Zertifikate für deine Workloads anzufragen, zu erstellenund zu erneuern. Auf der Liste der unterstützten Certificate Authorities finden sich u.A. ACME, GlobalSign, Hashicorp Vault, oder Cloudflare Origin CA. Nachdem diese initiale Frage geklärt ist, können wir uns als Nächstes anschauen, wie man Ingress-NGINX mit Cert-Manager absichern kann!

Installation von Ingress-NGINX

Um Ingress-NGINX absichern zu können, müssen wir Ingress-NGINX installieren – logisch! Wir werden dafür auf Helm zurückgreifen, eine Art Paketmanager für Kubernetes. Analog zur Installation von Softwarepaketen auf einem Betriebssystem folgt auch die Installation von Anwendungen auf Kubernetes mittels Helm einem gewissen Schema:

  1. Konfigurieren des Repositories
  2. Abfragen verfügbarer Pakete und Versionen
  3. Installation des gewünschten Pakets

Mit Helm sieht dieser Vorgang wie folgt aus:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install --namespace ingress-nginx --create-namespace ingress-nginx ingress-nginx/ingress-nginx

Warum 4x ingress-nginx?!

Der dritte Befehl sieht evtl. ein wenig komisch aus – wozu müssen wir viermal „ingress-nginx“ angeben? Die erste Angabe ist für den Namen des Namespaces, in den wir unsere Anwendung installieren möchten. Die zweite Angabe ist für den Releasenamen, den Helm nutzt, um unsere Installation(en) zu managen, und die dritte/vierte Angabe referenziert das genutzte Repository bzw. Paket
Terminieren alle drei Befehle erfolgreich, ist Ingress-NGINX bereits erfolgreich installiert und bereit, Anfragen an die Dienste in unserem Cluster zu bearbeiten. Wir können also mit der Installation von Cert-Manager weitermachen.

Installation von Cert-Manager

Genau wie zur Installation von Ingress-NGINX können wir auch für Cert-Manager Helm nutzen. Wir fügen das entsprechende Repository hinzu, syncen die verfügbaren Paket und installieren Cert-Manager in unser Cluster. Mit der zusätzlichen Einstellung  installCRDs stellen wir sicher, dass die von Cert-Manager genutzten  CustomResourceDefinitions  mitinstalliert werden.

helm repo add jetstack https://charts.jetstack.io/
helm repo update
helm install --namespace cert-manager --create-namespace cert-manager jetstack/cert-manager --set installCRDs=true

Auch Cert-Manager ist erfolgreich installiert, sobald die Helm-Befehle erfolgreich terminieren. Alles, was uns jetzt noch fehlt, ist ein sog.  Issuer .

Erstellung eines Issuers

Wie eingangs erwähnt, unterstützt Cert-Manager viele verschiedene Zertifikatsanbieter. Dafür muss es natürlich wissen, welche Authorität für die Ausstellung eines gewissen Zertifikats genutzt werden soll. Hierfür können Cert-Manager’s  Issuer CRDs genutzt werden. Im Rahmen dieses Tutorials nutzen wir den ACME Issuer, der es uns erlaubt, Let’s Encrypt Zertifikate für unsere Services zu erstellen:

---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
  namespace: cert-manager
spec:
  acme:
    # You must replace this email address with your own.
    # Let's Encrypt will use this to contact you about expiring
    # certificates, and issues related to your account.
    email: daniel@example.com
    # we will only use the staging API for this tutorial
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Secret resource that will be used to store the account's private key.
      name: acme-staging-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx

Dieser Issuer nutzt die Staging API von Let’s Encrypt, um gültige (aber nicht vertrauenswürdige) Zertifikate für unsere Services zu erstellen. Um die Authentizität unserer Services zu überprüfen, werden HTTP01-Challenges genutzt (s. Let’s Encrypt Challenge Types). Wenn wir genau hinschauen, sehen wir, dass wir statt einem Issuer einen  ClusterIssuer nutzen, der clusterweit referenziert werden kann. Als Nächstes können wir die Definition in unser Cluster einspielen:

kubectl apply -f clusterissuer.yml

Damit unser  Ingress in der Lage ist, wie gewünscht zu funktionieren, brauchen wir jetzt noch Konnektivität.

Vorbereitung des Ingress

Möchten wir unseren Ingress über das Internet erreichen und ein TLS-Zertifikat für in generieren (lassen), benötigen wir einen DNS-Eintrag. Für diesen wiederum brauchen wir die Ingress IP unseres Clusters. Diese IP wird von Ingress-NGINX für seinen Clusterdienst vom Typ  LoadBalancer genutzt, um Traffic in unser Cluster zu routen.

Erstellung eines DNS-Eintrags

Wir können die öffentlich verfügbare IP des Ingress-NGINX Dienstes mit folgendem Befehl ausgeben lassen:

kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath={.status.loadBalancer.ingress[0].ip}

Für diese IP benötigen wir nun einen A Eintrag für eine gültige (Sub)domain bei unserem DNS-Provider. Wie genau dieser Eintrag angelegt werden kann, unterscheidet sich von Anbieter zu Anbieter und ist nicht der Fokus dieses Tutorials.

Installation einer Demoanwendung

Das letzte fehlende Puzzlestück ist eine Anwendung, die wir absichern und mit unseren Webbrowsern aufrufen können. Wir werden hierzu podinfo deployen, eine oftgenutzte Demoanwendung mit einem kleinen Webfrontend. Zur Installation nutzen wir erneut Helm:

helm repo add podinfo https://stefanprodan.github.io/podinfo
helm repo update
helm install --namespace podinfo --create-namespace podinfo podinfo/podinfo

Nach einem kurzen Augenblick ist die Anwendung in unserem Cluster installiert, inklusive eines  ClusterIP Dienstes, den wir im nächsten Schritt in unserem Ingress referenzieren können.

Ingress-NGINX mit Cert-Manager absichern

Wir haben nun endlich alle benötigten Voraussetzungen erfüllt und können jetzt im abschließenden Schritt einen Ingress erstellen und absichern:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-staging
  name: podinfo
  namespace: podinfo
spec:
  ingressClassName: nginx
  rules:
  - host: podinfo.cluster.example.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: podinfo
            port:
              number: 9898
  tls: # < placing a host in the TLS config will determine what ends up in the cert's subjectAltNames
  - hosts:
    - podinfo.cluster.example.com
    secretName: podinfo1-tls

Ein paar Punkte fallen auf:

  • wir erstellen den Ingress im selben  Namespace in dem wir auch podinfo installiert haben
  • wir fügen eine Annotation hinzu, die Cert-Manager anweist, unseren zuvor erstellten  ClusterIssuer für die Zertifikatsgenerierung zu nutzen
  • unser Ingress wird Anfragen an https://podinfo.cluster.example.com/ an unseren podinfo Dienst weiterleiten
  • zusätzlich definieren wir einen Hostnamen für den SAN-Eintrag unseres Zertifikats und einen Namen für das Zertifikat selbst

Diese Konfiguration können wir in unser Cluster einspielen:

kubectl apply -f ingress.yml
  • Cert-Manager die Annotation unseres Ingress liest und…
    • …einen weiteren temporären Ingress für die HTTP01-Challenge erstellt
    • …das angefragte  Certificate als CRD erstellt
    • …das zugehörige Secret podinfo1-tls für unseren Ingress erstellt
  • Ingress-NGINX das Ingress Objekt mit der öffentlichen IP verknüpft.

Sind all diese Punkte abgeschlossen, können wir in unseren Webbrowsern https://podinfo.cluster.example.com aufrufen – und werden von der altbekannten Meldung „Your Connection is not secure“ begrüßt.

Screenshot of Google Chrome's 'Your connection is not private' screen

Unser Zertifikat wird von den meisten Webbrowsern nicht anerkannt werden.

Das passiert, weil wir Let’s Encrypt’s Staging API als Certificate Authority konfiguriert haben. Klicken wir auf Show advanced und bestätigen mit Proceed to https://podinfo.cluster.example.com/, werden wir trotzdem zu podinfo weitergeleitet:

A screenshot of podinfo's web UI

Podinfo’s Tintenfisch freut sich, uns zu sehen

Es funktioniert! Podinfo’s Maskottchen applaudiert uns für die korrekte Konfiguration unseres Ingress und ClusterIssuer . Der Vollständigkeit halber können wir in den Zertifikatsdetails unseres Webbrowsers auch noch verifizieren, dass das angefragte Zertifikat von Cert-Manager erstellt wurde:

A screenshot of Google Chrome's certificate details view, confirming that the certificate was issued by Let's Encrypt's Staging issuer

Das Zertifikat wurde von Let’s Encrypts STAGING API ausgestellt.

Zusammenfassung

Geschafft – wir haben unseren Ingress-NGINX mit Cert-Manager abgesichert! Alles, was wir dafür benötigt haben, war ein ClusterIssuer , der Let’s Encrypts (Staging) API nutzt, und eine dazugehörige Annotation in unserem Ingress Objekt. Solltest du noch weiter experimentieren wolle, kannst du als nächsten Schritt Let’s Encrypts Production-API nutzen, indem du den  staging Teil aus der konfigurierten URL des ClusterIssuer herausnimmst. Dann sollte sich auch dein Webbrowser nicht mehr beschweren, dass das Zertifikat nicht vertrauenswürdig ist. Deployst du bereits andere Anwendungen mit Helm, kann es außerdem gut sein, dass es bereits vordefinierte Values oder eingebauten Cert-Manager-Support für deine Anwendung(en) gibt – schau doch einfach einmal nach! Und war das Tutorial jetzt doch etwas zu schnell oder gewisse Punkte noch unklar, zögere nicht, bei unseren MyEngineers durchzuklingeln – sie brennen dafür, dir jederzeit unter die Arme zu greifen!

Erhalte den nächsten Artikel

Mehr Artikel in Kubernetes | Tutorial
NWS Kubernetes Playground Jetzt Verfügbar

NWS Kubernetes Playground Jetzt Verfügbar

Wir freuen uns, Dir heute unseren brandneuen NWS Kubernetes Playground präsentieren zu können! Die interaktive Plattform hilft Dir dabei, Neues über cloud-native Technologien zu lernen, Dein Wissen und Selbstvertrauen in der Arbeit mit Kubernetes auszubauen, und eine...

Migration von Servern auf VMware zu OpenStack

Migration von Servern auf VMware zu OpenStack

In diesem Tutorial befassen wir uns mit der Migration von Servern auf VMware zu OpenStack. Nach der kürzlichen Übernahme VMwares durch Broadcom haben in den vergangenen Wochen viele kleinere Cloud Service Provider (CSPs) Mitteilung zur Kündigung ihrer Mitgliedschaft...

Meistere Kubernetes mit Cilium: Traffic Filterung auf L7 Basis

Meistere Kubernetes mit Cilium: Traffic Filterung auf L7 Basis

Mit der neuen Version des Cilium CNI auf unserem Kubernetes-Service erhältst Du die Möglichkeit, den Datenverkehr anhand von L7-Eigenschaften zu filtern. Das ist normalerweise Service-Meshes vorbehalten und kann bei der Sicherheit deiner Dienste sehr hilfreich sein....

Terraform und OpenStack

Terraform und OpenStack

Viele von Euch sind vermutlich bereits mit der Verwendung von Terraform in Kombination mit Azure oder AWS vertraut. Und obwohl dies die am häufigsten verwendeten Plattformen sind, gibt es - oftmals im Bezug auf Datenschutz (DSGVO) - Unwägbarkeiten und somit weiterhin...

Dynamic Inventory – Eine Ansible und OpenStack Lovestory

Dynamic Inventory – Eine Ansible und OpenStack Lovestory

Für diejenigen unter euch, die mit Ansible möglicherweise nicht allzu vertraut sind: Es ist ein großartiges Tool, um in die Welt der Automatisierung einzusteigen und erleichtert euer Leben im Konfigurationsmanagement erheblich.   Die Kennenlernphase In diesem Tutorial...

ReadWriteMany (RWX) mit dem NFS Ganesha Provisioner

ReadWriteMany (RWX) mit dem NFS Ganesha Provisioner

Einführung Du hast die Anforderung, dass Deine Anwendung für eine Lastverteilung über mehrere Nodes skalieren muss, aber Zugriff auf ein gemeines PVC benötigt? Zu diesem Zweck benötigst Du ein PVC welches RWX-fähig ist. Im Rahmen unserer Managed Kubernetes Cluster ist...

Persistente Volumes in Kubernetes vergrößern

Persistente Volumes in Kubernetes vergrößern

Du willst ein PersistentVolume (PV) in Kubernetes vergrößern? In diesem Blogeintrag erfährst du wie das funktioniert. Was PVs sind und wie man diese anlegt wird im Tutorial Persistente Volumes in Kubernetes erstellen erklärt, auf welchem das vorliegende Tutorial...

Wie Du Deine NETWAYS Managed Database startest

Wie Du Deine NETWAYS Managed Database startest

Im ersten Tutorial hat Sebastian bereits erklärt, was es mit Vitess auf sich hat und welche Möglichkeiten es Dir beim Betrieb Deiner Anwendung, im Vergleich zu einer gewöhnlichen Datenbank, bietet. Im folgenden Text möchte ich nun darauf eingehen, wie Du Dir in...

Was ist Vitess?

Was ist Vitess?

Im Jahr 2010 wurde eine Lösung entwickelt, um die massiven Skalierbarkeitsprobleme von MySQL bei YouTube zu lösen - und somit war Vitess geboren. Später - im Jahr 2018 - wurde das Projekt Teil der Cloud Native Computing Foundation und ist seit 2019 als eines der...