In diesem Artikel werde ich darüber sprechen, wie die Bestellung und Erneuerung von Zertifikaten von Let's Encrypt (und nicht nur) für Ingress in Kubernetes mithilfe des Add-On-Zertifikatsmanagers automatisiert werden kann. Aber ich beginne mit einer kurzen Einführung in das Wesentliche des Problems.Ein bisschen Bildungsprogramm
Das HTTP-Protokoll, das in den frühen 90er Jahren des letzten Jahrhunderts entwickelt wurde, ist so eng in unseren Alltag eingedrungen, dass man sich kaum einen Tag ohne Verwendung vorstellen kann. An sich bietet es jedoch nicht einmal ein Mindestmaß an Sicherheit beim Austausch von Informationen zwischen einem Benutzer und einem Webserver. HTTPS („S“ - sicher) hilft dabei: Durch die Verpackung der übertragenen Daten in SSL / TLS hat sich dieses Protokoll beim Schutz von Informationen vor dem Abfangen bewährt und wird von der Industrie aktiv gefördert.Zum Beispiel hat Google an 2014 festgehaltenPosition "HTTPS überall" und senkt sogar die Priorität von Websites ohne diese in den Suchergebnissen. Diese „Propaganda“ umgeht auch nicht die normalen Verbraucher: Moderne Browser warnen ihre Benutzer vor dem Vorhandensein und der Richtigkeit von SSL-Zertifikaten für besuchte Websites.

Die Kosten für ein Zertifikat für eine persönliche Website beginnen bei mehreren zehn Dollar. Es ist nicht immer gerechtfertigt und angemessen, es zu kaufen. Glücklicherweise ist seit Ende 2015 eine kostenlose Alternative in Form von Let's Encrypt (LE) -Zertifikaten verfügbar . Dieses gemeinnützige Projekt wurde von Mozilla-Enthusiasten erstellt, um die meisten Websites verschlüsselt abzudecken.Die Zertifizierungsstelle stellt domänenvalidierte Zertifikate aus(das einfachste unter den auf dem Markt erhältlichen) mit einer Gültigkeitsdauer von 90 Tagen, und seit vielen Jahren ist es möglich, das sogenannte Wildcard-Zertifikat für mehrere Subdomains auszustellen.Um das Zertifikat zu erhalten, verwendet die Site die Algorithmen, die im ACME- Protokoll ( Automated Certificate Management Environment ) beschrieben sind, das speziell für Let's Encrypt erstellt wurde. Bei Verwendung erfolgt die Bestätigung des Domänenbesitzes durch Anforderungen durch Platzierung eines bestimmten HTTP-Codes ( HTTP-01 ) oder Installation von DNS-Einträgen (DNS-01). Weitere Informationen hierzu finden Sie weiter unten.Zertifizierungsmanager
Cert-Manager ist ein spezielles Projekt für Kubernetes, bei dem es sich um eine Reihe von CustomResourceDefinitions (daher die Beschränkung der unterstützten Mindestversion von K8s - v1.12) für die CA-Konfiguration (Zertifizierungsstellen) und die direkte Bestellung von Zertifikaten handelt. Die Installation von CRD in einem Cluster ist trivial und erfordert die Verwendung einer YAML-Datei:kubectl create ns cert-manager
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v0.13.0/cert-manager.yaml
( Es besteht auch die Möglichkeit der Installation mit Helm.)Um den Bestellvorgang zu starten, müssen im Cluster die Ressourcen der Zertifizierungsstellen (CAs) deklariert sein: Issuer
oder ClusterIssuer
, - die zum Signieren der CSR (Certificate Issuance Requests) verwendet werden. Der Unterschied zwischen der ersten und der zweiten Ressource liegt im Umfang:Issuer
kann im selben Namespace verwendet werden,ClusterIssuer
ist ein globales Clusterobjekt.
Übe mit dem Cert-Manager
Nr. 1. Selbstsigniertes Zertifikat
Beginnen wir mit dem einfachsten Fall - der Bestellung eines selbstsignierten Zertifikats. Diese Option ist beispielsweise in dynamischen Testumgebungen für Entwickler oder bei Verwendung eines externen Balancers, der den SSL-Verkehr beendet, weit verbreitet.Die Ressource Issuer
sieht folgendermaßen aus:apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: selfsigned
spec:
selfSigned: {}
Um ein Zertifikat ausstellen zu können, muss die Ressource beschrieben werden Certificate
, wo angegeben wird, wie sie ausgestellt werden soll (siehe Abschnitt issuerRef
unten) und wo sich der private Schlüssel (Feld secretName
) befindet. Danach muss sich Ingress auf diesen Schlüssel beziehen (siehe Abschnitt tls
c spec
):---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: selfsigned-crt
spec:
secretName: tls-secret
issuerRef:
kind: Issuer
name: selfsigned
commonName: "yet-another.website"
dnsNames:
- "yet-another.website"
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app
spec:
tls:
- hosts:
- "yet-another.website"
secretName: tls-secret
rules:
- host: "yet-another.website"
http:
paths:
- path: /
backend:
serviceName: app
servicePort: 8080
Einige Sekunden nach dem Hinzufügen dieser Ressourcen zum Cluster wird das Zertifikat ausgestellt. Sie können den entsprechenden Bericht in der Ausgabe des Befehls sehen:kubectl -n app describe certificate selfsigned-crt
...
Normal GeneratedKey 5s cert-manager Generated a new private key
Normal Requested 5s cert-manager Created new CertificateRequest resource "selfsigned-crt-4198958557"
Normal Issued 5s cert-manager Certificate issued successfully
Wenn Sie sich die geheime Ressource selbst ansehen, enthält sie:- privater Schlüssel
tls.key
, - Stammzertifikat
ca.crt
, - Unser selbstsigniertes Zertifikat
tls.crt
.
Der Inhalt dieser Dateien kann beispielsweise mit dem Dienstprogramm openssl
wie folgt angezeigt werden:kubectl -n app get secret tls-secret -ojson | jq -r '.data."tls.crt"' | base64 -d | openssl x509 -dates -noout -issuer
notBefore=Feb 10 21:01:59 2020 GMT
notAfter=May 10 21:01:59 2020 GMT
issuer=O = cert-manager, CN = yet-another.website
Es ist anzumerken, dass das damit ausgestellte Zertifikat im allgemeinen Fall von denIssuer
verbundenen Clients nicht als vertrauenswürdig eingestuft wird . Der Grund ist einfach: Es gibt keine Zertifizierungsstelle (siehe Hinweis auf der Projektwebsite ) . Um dies zu vermeiden, müssen Sie im Certificate
Pfad zu der geheimen Datei angeben, in der sie enthalten ist ca.crt
. Dies kann eine Unternehmens-CA-Organisation sein, um die für Ingress ausgestellten Zertifikate mit einem Schlüssel zu signieren, der bereits für die Anforderungen anderer Serverdienste / Informationssysteme verwendet wird.Nr. 2. Verschlüsseln wir das Zertifikat mit der HTTP-Validierung
Wie bereits erwähnt, stehen für die Ausstellung von LE-Zertifikaten zwei Arten der Bestätigung des Domänenbesitzes zur Verfügung : HTTP-01 und DNS-01.Der erste Ansatz (HTTP-01) besteht darin, einen kleinen Webserver mit einer separaten Bereitstellung zu starten, der über den Link <YOUR_DOMAIN > / an das Internet gesendet wird . Bekannte / acme-Challenge / <TOKEN> Einige vom Zertifizierungsserver angeforderte Daten. Daher impliziert diese Methode die Verfügbarkeit von Ingress von außen an Port 80 und die Auflösung des DNS-Eintrags der Domäne in öffentliche IP-Adressen.Die zweite Option zum Überprüfen des ausgestellten Zertifikats (DNS-01) stammt vonvon einer API bis zum DNS-Server, auf dem die Domäneneinträge gehostet werden. Der Aussteller erstellt mit den angegebenen Token TXT-Datensätze in der Domäne, die der ACME-Server dann während der Bestätigung erhält. Zu den offiziell unterstützten DNS-Anbietern zählen CloudFlare, AWS Route53, Google CloudDNS und andere, einschließlich der eigenen Implementierung ( acme-dns ).Hinweis : Let's Encrypt hat recht strenge Beschränkungen für Anforderungen an ACME-Server. Um nicht in ein langes Verbot zu geraten, wird empfohlen, zum Debuggen den Zertifikatstyp letsencrypt-staging zu verwenden (der Unterschied besteht nur beim ACME-Server).Also beschreiben wir die Ressourcen:apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: le-crt
spec:
secretName: tls-secret
issuerRef:
kind: Issuer
name: letsencrypt
commonName: yet-another.website
dnsNames:
- yet-another.website
Beachten Sie, dass die Adresse des Staging- Servers als server
y acme
(c Issuer
) angegeben ist . Ersetzen Sie es durch eine Schlacht wird später möglich sein. Mit dieser Konfiguration verfolgen wir den gesamten Bestellpfad:- Die Schöpfung
Certificate
brachte eine neue Ressource hervor CertificateRequest
:
kubectl -n app describe certificate le-crt
...
Created new CertificateRequest resource "le-crt-1127528680"
- In seiner Beschreibung - ein Zeichen auf der Schöpfung
Order
:
kubectl -n app describe certificaterequests le-crt-1127528680
…
Created Order resource app/le-crt-1127528680-1805948596
- Es
Order
beschreibt, mit welchen Parametern der Test besteht und welchen aktuellen Status er hat. Eine solche Überprüfung wird von der Ressource durchgeführt Challenge
:
kubectl -n app describe order le-crt-1127528680-1805948596
…
Created Challenge resource "le-crt-1127528680-1805948596-1231544594" for domain "yet-another.website"
- Schließlich enthalten die Details dieser Ressource Informationen zum Status des Scans selbst:
kubectl -n app describe challenges le-crt-1127528680-1805948596-1231544594
...
Reason: Successfully authorized domain
...
Normal Started 2m45s cert-manager Challenge scheduled for processing
Normal Presented 2m45s cert-manager Presented challenge using http-01 challenge mechanism
Normal DomainVerified 2m22s cert-manager Domain "yet-another.website" verified with "http-01" validation
Wenn alle Bedingungen erfüllt sind (d. H. Die Domain ist von außen zugänglich, es gibt kein Verbot der LE ...) - in weniger als einer Minute wird das Zertifikat ausgestellt. Bei Erfolg wird ein describe certificate le-crt
Datensatz in der Ausgabe angezeigt Certificate issued successfully
.Jetzt können Sie die Serveradresse sicher in Combat ( https://acme-v02.api.letsencrypt.org/directory
) ändern und die bereits signierten echten Zertifikate nicht neu bestellen Fake LE Intermediate X1
, sondern Let's Encrypt Authority X3
.Dazu müssen Sie zunächst die Ressource löschen. Certificate
Andernfalls werden keine Bestellverfahren aktiviert, da das Zertifikat bereits vorhanden und relevant ist. Das Entfernen eines Geheimnisses führt zu seiner sofortigen Rückkehr mit einer Nachricht an describe certificate
: Normal PrivateKeyLost 44s cert-manager Lost private key for CertificateRequest "le-crt-613810377", deleting old resource
Es bleibt, das "Kampf" -Manifest für Issuer
das bereits oben beschriebene anzuwenden Certificate
(es hat sich nicht geändert):apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
Nach dem Empfang der Nachricht Certificate issued successfully
, describe
überprüfen Sie es:kubectl -n app get secret tls-secret -ojson | jq -r '.data."tls.crt"' | base64 -d | openssl x509 -dates -noout -issuer
notBefore=Feb 10 21:11:48 2020 GMT
notAfter=May 10 21:11:48 2020 GMT
issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
Nummer 3. Platzhalter LE mit DNS-Validierung
Wir werden die Aufgabe komplizieren, indem wir sofort ein Zertifikat an alle Subdomains der Site schreiben und diesmal die DNS-Prüfung (über CloudFlare) verwenden.Rufen Sie zunächst das Token in der CloudFlare-Systemsteuerung ab, um die API zu bearbeiten:- Profil → API-Token → Token erstellen.
- Legen Sie die Berechtigungen wie folgt fest:
- Berechtigungen:
- Zone - DNS - Bearbeiten
- Zone - Zone - Lesen
- Zonenressourcen:
- Einschließen - Alle Zonen
- Kopieren Sie den nach dem Speichern erhaltenen Token (zum Beispiel :)
y_JNkgQwkroIsflbbYqYmBooyspN6BskXZpsiH4M
.
Erstellen Sie ein Geheimnis, in dem dieses Token gespeichert wird, und verweisen Sie im Aussteller darauf:apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token
type: Opaque
stringData:
api-token: y_JNkgQwkroIsflbbYqYmBooyspN6BskXZpsiH4M
---
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt
solvers:
- dns01:
cloudflare:
email: my-cloudflare-acc@example.com
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: le-crt
spec:
secretName: tls-secret
issuerRef:
kind: Issuer
name: letsencrypt
commonName: yet-another.website
dnsNames:
- "yet-another.website"
- "*.yet-another.website"
(Vergessen Sie nicht, Staging zu verwenden, wenn Sie experimentieren!)Führen Sie den Vorgang zum Bestätigen des Domainbesitzes durch:kubectl -n app describe challenges.acme.cert-manager.io le-crt-613810377-1285319347-3806582233
...
Status:
Presented: true
Processing: true
Reason: Waiting for dns-01 challenge propagation: DNS record for "yet-another.website" not yet propagated
State: pending
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Started 54s cert-manager Challenge scheduled for processing
Normal Presented 53s cert-manager Presented challenge using dns-01 challenge mechanism
Ein TXT-Datensatz wird im Bedienfeld angezeigt:
... und nach einer Weile ändert sich der Status in:Domain "yet-another.website" verified with "dns-01" validation
Stellen Sie sicher, dass das Zertifikat für jede Subdomain gültig ist:kubectl -n app get secret tls-secret -ojson | jq -r '.data."tls.crt"' | base64 -d | openssl x509 -dates -noout -text |grep DNS:
DNS:*.yet-another.website, DNS:yet-another.website
Die Validierung durch DNS erfolgt in der Regel nicht schnell, da die meisten DNS-Anbieter über einen Datenaktualisierungszeitraum verfügen, der angibt, wie viel Zeit von der Änderung des DNS-Eintrags bis zur tatsächlichen Aktualisierung aller DNS-Server des Anbieters vergeht. Der ACME-Standard bietet jedoch auch eine Kombination aus zwei Überprüfungsoptionen, mit denen der Empfang eines Zertifikats für die Hauptdomäne beschleunigt werden kann. In diesem Fall Issuer
lautet die Beschreibung wie folgt:apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https:
privateKeySecretRef:
name: letsencrypt
solvers:
- selector:
dnsNames:
- "*.yet-another.website"
dns01:
cloudflare:
email: my-cloudflare-acc@example.com
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
- selector:
dnsNames:
- "yet-another.website"
http01:
ingress:
class: nginx
Wenn Sie diese Konfiguration anwenden, werden zwei Ressourcen erstellt Challenge
:kubectl -n app describe orders le-crt-613810377-1285319347
…
Normal Created 3m29s cert-manager Created Challenge resource "le-crt-613810377-1285319347-3996324737" for domain "yet-another.website"
Normal Created 3m29s cert-manager Created Challenge resource "le-crt-613810377-1285319347-1443470517" for domain "yet-another.website"
Nummer 4. Verwenden von Ingress-Spezialanmerkungen
Zusätzlich zum direkten Pfad zum Erstellen von Zertifikaten in cert-manager ist es möglich, eine Komponente namens ingress-shim zu verwenden und Ressourcen nicht explizit zu erstellen Certificate
. Die Idee ist, dass mit Hilfe spezieller Ingress-Anmerkungen das Zertifikat automatisch unter Verwendung des darin angegebenen Zertifikats bestellt wird Issuer
. Das Ergebnis ist ungefähr die folgende Ingress-Ressource:apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt
spec:
tls:
- hosts:
- "yet-another.website"
secretName: tls-secret
rules:
- host: "yet-another.website"
http:
paths:
- path: /
backend:
serviceName: app
servicePort: 8080
Für einen korrekten Betrieb reicht hier nur die Anwesenheit des Emittenten aus, dh es wird eine Entität weniger erstellt.Darüber hinaus gibt es eine veraltete Annotation kube-lego - kubernetes.io/tls-acme: "true"
, -, die eine Issuer
Standardaufgabe erfordert, wenn cert-manager mithilfe von Helm-Parametern (oder in den Startoptionen des Manager-Containers) installiert wird.Wir im Unternehmen verwenden diese Optionen nicht und können sie aufgrund der Undurchsichtigkeit der Ansätze zur Bestellung von SSL-Zertifikaten (und gleichzeitig aufgrund verschiedener auftretender Probleme ) nicht empfehlen. Wir haben uns jedoch entschlossen, sie im Artikel zu erwähnen, um ein vollständigeres Bild zu erhalten.Anstelle einer Schlussfolgerung
Durch einfache Manipulationen mit CRD haben wir gelernt, wie automatisch erneuerbare, selbstsignierte und kostenlose SSL-Zertifikate aus dem Let's Encrypt-Projekt für Website-Domänen geschrieben werden, die im Rahmen von Ingresss in Kubernetes-Clustern gestartet wurden.Der Artikel enthält Beispiele zur Lösung der häufigsten Probleme in unserer Praxis. Die Cert-Manager-Funktionen sind jedoch nicht auf die oben beschriebenen Funktionen beschränkt. Auf der Utility-Website finden Sie Beispiele für die Arbeit mit anderen Diensten - beispielsweise ein Bundle mit Vault oder die Verwendung externer Ausgabezentren (Emittenten).PS
Lesen Sie auch in unserem Blog: