Installation und Verwendung von Cert-Manager in Kubernetes

Zertifikate, insbesondere Probleme mit Zertifikaten, sind eines der meistgehassten Dinge unter den Sysadmins, die ich kenne. In Kubernetes kann Cert-Manager die Zertifikatsverwaltung vereinfachen, indem viele Schritte automatisiert werden. In dieser Anleitung zeige ich dir, wie du Cert-Manager in Kubernetes installierst und verwendest.

Ich habe schon sehr viele Zertifikaten per Hand mit OpenSSL ausgestellt. Daher weiß ich es sehr zu schätzen, dass mir Cert-Manager diese Arbeit in Kubernetes abnimmt.

Was ist Cert-Manager?

Cert-Manager kann als ein Microservice gesehen werden, der in einem Kubernetes-Cluster bereitgestellt wird.Sobald er bereitgestellt und konfiguriert ist, kümmert er sich um das Anfordern, Ausstellen und automatische Erneuern von Zertifikaten.

Wie funktioniert das?

Bei der Installation von Cert-Manager werden auch Cert-Manager-spezifische Custom Resource Definitions (CRDs) wie Definitionen von Zertifikaten, ClusterIssuer und Issuer installiert. Mit diesen CRDs kann man Cert-Manager mitteilen, welche Zertifikate er von wo anfordern soll.

Installation

Cert-Manager kann entweder per Kubernetes-Manifest oder Helm installiert werden. Hier zeige ich dir die Installation über Kubernetes-Manifests, weil es etwas einfacher ist, weniger Schritte erfordert und weniger Dinge zu beachten sind.

Hinweis: Wenn du es per Helm installieren möchtest, empfehle ich dir die offizielle Installationsanleitung.

Im Grunde braucht es nur einen Befehl. Alles, was zu tun ist, ist im Manifest enthalten. Je nachdem, welche Kubernetes-Version du einsetzt, musst du den einen oder anderen Befehl verwenden (höchstwahrscheinlich wird deine Version 1.16 oder höher sein).

Hinweis: Vor der Installation solltest du die aktuellste stabile Version unter https://github.com/jetstack/cert-manager/releases überprüfen und die Version entsprechend ersetzen.

# Für Kubernetes Version 1.16 oder höher
$ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager.yaml


# Für Kubernetes Version 1.15 oder niedriger
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager-legacy.yaml

Um zu prüfen, ob die Installation erfolgreich war, gib folgendes ein:

$ kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-756bb56c5-6bjfr               1/1     Running   0          56d
cert-manager-webhook-66b555bb5-jfghq       1/1     Running   0          56d
cert-manager-cainjector-86bc6dc648-8pnfc   1/1     Running   0          56d

Du solltest die drei Pods im laufenden Zustand sehen.

Konfigurieren eines Issuers

Bevor Cert-Manager deine Zertifikate verwalten kann, musst du einen Issuer konfigurieren, den er verwenden kann. Der Issuer ist in der Regel ein Dritter sein, der Zertifikate ausstellt und dem andere Computer vertrauen.

Cert-Manager unterstützt verschiedene Arten von Issuer:

  • ACME – mit dem ACME-Issuer kannst du Zertifikate von Zertifizierungsstellen anfordern, die das Automated Certificate Management Environment (ACME) Protokoll unterstützen.
  • Vault – mit dem Vault-Aussteller kannst du Zertifikate von einer selbst gehosteten Hashicorp Vault Public Key Infrastructure (PKI) abrufen.
  • SelfSigned – Damit kannst du selbst signierte Zertifikate ausstellen. Diese werden von anderen Clients standardmäßig nicht als vertrauenswürdig eingestuft.
  • CA – mit diesem Aussteller kannst du eine Zertifizierungsstelle innerhalb des Clusters erstellen. Zertifikatsanfragen werden von der lokalen CA signiert. Dieser Aussteller kann hilfreich sein, wenn du gegenseitiges TLS innerhalb des Clusters verwenden möchten.

In dieser Anleitung werden wir den ACME-Issuer verwenden. Mit ACME kannst du Zertifikate von verschiedenen Zertifizierungsstellen beziehen, die das ACME-Protokoll unterstützen – vor allem können Sie damit kostenlose Zertifikate von Let’s Encrypt erhalten. Mittlerweile unterstützen auch einige Enterprise PKI-Lösungen das ACME-Protokoll. Und auch öffentliche CAs wie Digicert unterstützen es.

Issuer oder ClusterIssuer?

Cert-Manager unterstützt zwei Typen von Issuer-Definitionen: ‚Issuer‘ und ‚ClusterIssuer‘. Die ‚Issuer‘-Definition gilt für einen einzelnen Namespace, während die ‚ClusterIssuer‘-Definition für den gesamten Cluster gilt. Je nach deinen Anforderungen solltest du den einen oder anderen verwenden. In dieser Anleitung werden wir den ClusterIssuer mit Let’s Encrypt verwenden.

Let’s Encrypt ClusterIssuer

Wir werden zwei ClusterIssuer für Let’s Encrypt konfigurieren – unter Verwendung der Staging- und der Produktions-API. Zum Testen sollten Sie die Let’s Encrypt Staging-API verwenden, da die Produktions-API ein Rate-Limit hat und dich aussperrt, wenn du zu viele Zertifikate innerhalb einer bestimmten Zeit anforderst.

Um die ClusterIssuers zu konfigurieren, musst du eine yaml-Datei erstellen und diese so anpassen, dass sie zum verwendeten Ingress-Controller passt. Wir werden beide Issuers in dieselbe Datei packen und sie ‚letsencrypt.yml‘ nennen.

---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
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: user@example.com
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Secret resource that will be used to store the account's private key.
      name: staging-issuer-account-key
    # Add a single challenge solver, HTTP01
    solvers:
      - http01:
          ingress:
            # if you use nginx use:
            # class: nginx
            lass: traefik

---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
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: user@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Secret resource that will be used to store the account's private key.
      name: staging-issuer-account-key
    # Add a single challenge solver, HTTP01
    solvers:
      - http01:
          ingress:
            # if you use nginx use:
            # class: nginx
            class: traefik

Um sie zu importieren, geben wir ein:

$ kubectl apply -f letsencrypt.yml
clusterissuer.cert-manager.io/letsencrypt-staging configured
clusterissuer.cert-manager.io/letsencrypt-prod configured

Um zu prüfen, ob sie funktionieren, geben wir ein:

$ kubectl describe ClusterIssuer
Name:         letsencrypt-prod
Namespace:
Labels:       <none>
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         ClusterIssuer
Metadata:
  Creation Timestamp:  2020-05-08T16:25:35Z
  Generation:          1
  Resource Version:    203187
  UID:                 2f04f031-174c-426b-bf0c-c6a3b7658454
Spec:
  Acme:
    Email:            user@example.com
    Preferred Chain:
    Private Key Secret Ref:
      Name:  prod-issuer-account-key
    Server:  https://acme-v02.api.letsencrypt.org/directory
    Solvers:
      http01:
        Ingress:
          Class:  traefik
      Selector:
Status:
  Acme:
    Last Registered Email:  user@example.com
    Uri:                    https://acme-v02.api.letsencrypt.org/acme/acct/85621721
  Conditions:
    Last Transition Time:  2020-05-08T16:25:37Z
    Message:               The ACME account was registered with the ACME server
    Reason:                ACMEAccountRegistered
    Status:                True
    Type:                  Ready
Events:                    <none>

...

Wenn der Status wie oben aussieht, sollte der ClusterIssuer funktionieren.

Zertifikate automatisch über eine Ingress-Definition ausstellen

Um den Let’s Encrypt Issuer mit einem Ingress zu verwenden, musst du deine Ingress-Definitionen anpassen:

  • Die Annotation ‚cert-manager.io/cluster-issuer‘ oder ‚cert-manager. io/issuer‘ muss vorhanden sein und den Namen des zu verwendenden Issuers angeben
  • Der TLS-Abschnitt muss vorhanden sein:
    • Ein oder mehrere Hosts müssen vorhanden sein
    • Der secretName muss angegeben werden (das Zertifikat wird dort gespeichert)
  • Natürlich müssen die angegebenen Hostnamen auf Ihren Kubernetes Ingress zeigen.
---
apiVersion: extensions/v1
kind: Ingress
metadata:
  annotations:
    # Specify which ClusterIssuer to use
    # cert-manager.io/issuer: acme123
    # cert-manager.io/cluster-issuer: letsencrypt-prod
    cert-manager.io/cluster-issuer: letsencrypt-staging
  name: web1.example.com
  namespace: web1-example
spec:
  rules:
  - host: web1.example.com
    http:
      paths:
      - backend:
          serviceName: web1-example
          servicePort: 80
  tls:
  - hosts:
    - web1.example.com
    - web2.example.com
    secretName: web1.example.com-tls

Wenn der Ingress in Kubernetes deployed wird, liest Cert-Manager ihn aus und fordert automatisch das Zertifikat vom ClusterIssuer an. Die ACME CA überprüft dann, ob der Host den Besitz des Hostnamens nachweisen kann, indem sie sich mit ihm verbindet und prüft, ob der Challenge-String gefunden werden kann.

Um zu prüfen, ob das Zertifikat korrekt ausgestellt wurde, kannst du folgendes eingeben:

$ kubectl describe certificate -n test

Name:         web1.example.com-tls
Namespace:    test
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Certificate
Metadata:
  Creation Timestamp:  2020-12-29T07:52:12Z
...
Spec:
  Dns Names:
    web1.example.com
    web2.example.com
  Issuer Ref:
    Group:      cert-manager.io
    Kind:       ClusterIssuer
    Name:       letsencrypt-prod
  Secret Name:  web1.example.com-tls
Status:
  Conditions:
    Last Transition Time:  2020-12-29T07:52:41Z
    Message:               Certificate is up to date and has not expired
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2021-03-29T06:52:40Z
  Not Before:              2020-12-29T06:52:40Z
  Renewal Time:            2021-02-27T06:52:40Z
  Revision:                1
Events:
  Type    Reason        Age    From          Message
  ----    ------        ----   ----          -------
  Normal  GeneratedKey  4m56s  cert-manager  Generated a new private key
  Normal  Requested     4m56s  cert-manager  Created new CertificateRequest resource "web1.example.com-tls-2067939407"
  Normal  Issued        4m32s  cert-manager  Certificate issued successfully

Zertifikate über die Zertifikatsressourcen anfordern

Eine weitere Methode, um Zertifikate anzufordern, ist die Verwendung der ‚Certificate‘ Ressource. Für diese Methode musst du eine Ressource wie die folgende erstellen und Cert-Manager kümmert sich um den Rest. Hierfür empfehle ich dir die offizielle Dokumentation zu lesen.

Weitere Lektüre

Schreibe einen Kommentar