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 erstellen, und 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:
- Konfigurieren des Repositories
- Abfragen verfügbarer Pakete und Versionen
- 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?!
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 selbenNamespace
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
- …einen weiteren temporären
- 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.
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:
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:
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!