Install Cert-Manager

Der Cert-Manager ist eine Verwaltungskomponente für Zertifikate innerhalb eines Kubernetes Clusters.

Erst mit dem Cert-Manager ist es möglich Zertifikate zu erstellen, verwalten und löschen. Der Cert-Manager bringt über CRDs eigene Objekte für die Verwaltung mit

Installation

Die einfachste Installation kann direkt über Helm erfolgen.

Typischerweise wird für den Cert-Manager ein eigener Namespace (cert-manager) angelegt.

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

Beispiel für die Anwendung

Bei einem extern erreichbaren Webserver soll neben der Konfiguration eines Ingress mit nginx auf Port 80 auch ein Zugang über https (Port 443) ermöglicht werden.

Dazu bedarf es eines Zertifikats von einer Trusted-CA. Bei extern erreichbaren Webseiten bietet sich dafür z. B. Let’s Encrypt an.

Issuer

Um bei Let’s Encrypt Zertifikate abholen zu können bedarf es zunächst eines Issuers über diese Objekt wir die Anmeldung an Let’s Encrypt durchgeführt. Die gespeicherte Anmeldung dient später auch als Berechtigung die Zertifikate zu beantragen.

Der Issuer wird im gleichen Namespace wie der spätere Ingress angelegt.

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: acme
  namespace: example
spec:
  acme:
    email: user@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: acme-issuer
    solvers:
      - http01:
          ingress:
            class: nginx

Sobald das Objekt erstellt ist, wird die Anmeldung durchgeführt. Der Status ist im status des Ingress Objekts sichtbar.

Ingress

Um einen Webserver per https erreichbar zu machen, wird zusätzlich zu der normalen Konfiguration ein Abschnitt spec.tls benötigt in dem der SNI spec.tls.hosts[] und der Name eines Secrets für das Zertifikat angegeben wird.

Damit der Cert-Manager sich um das Zertifikat kümmert muss eine Annotation cert-manager.io/issuer: angelegt werden, in die der Name des zu benutztenden Issuers angegeben wird.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/issuer: "acme"
  name: nginx
  namespace: example
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: nginx
                port:
                  number: 80
  tls:
    - hosts:
        - example.com
      secretName: example.com-tls

Nach Anlegen des Objekts sorgt der Cert-Manager für die Erzeugung des Privaten Schlüssels und eines Certificate Sign Requests (CSR). Den CSR sendet er zur Validierung an den über den Issuer angegeben Dienst und sorgt sich um die Kommunikation mit diesem um das Zertifikat zu holen. Sobald es vorliegt wird es in dem unter secretName angegebenen Secret zusammen mit dem Key abgelegt und steht für den Ingress zu Verfügung. Dieser baut das Zertifikat - sobald es vorhanden ist - ein und stellt die Domain per https zur Verfügung.

ClusterIssuer

Der Issuer steht immer nur in dem Namespace in dem er angelegt wurde zur Verfügung. Um einen Issuer auch über die Namespaces hinweg benutzen zu können gibt es den ClusterIssuer.

Dieser wird - in der Regel - Im Namespace des Cert-Manager abgelegt, kann aber - solang es keine RBAC Einschränkungen gibt - aus allen Namespaces benutzt werden.

Cluster-Issuer

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: acme
  namespace: cert-manager
spec:
  acme:
    email: user@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: acme-issuer
    solvers:
      - http01:
          ingress:
            class: nginx

Tatsächlich unterscheidet sich die Konfiguration des ClusterIssuer nur durch den unterschiedlichen kind von dem Issuer (ClusterIssuer statt Issuer)

Ingress

Auch beim Ingress ist nur die Annotation zu ändern.

Hier wird dann cert-manager.io/cluster-issuer: benutzt.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: "acme"
  name: nginx
  namespace: example
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: nginx
                port:
                  number: 80
  tls:
    - hosts:
        - example.com
      secretName: example.com-tls