Nginx Ingress Controller mit SSL auf Kubernetes einrichten
Der Nginx Ingress Controller gehört zu den am häufigsten genutzten Ingress-Lösungen für Kubernetes. Er verwendet Nginx als Reverse Proxy und Load Balancer, um externe Anfragen sicher an die internen Dienste im Cluster weiterzuleiten. Als zentraler Zugriffspunkt bietet er Funktionen wie SSL/TLS-Beendigung, Lastverteilung, Sitzungsverwaltung und pfadbasierte Weiterleitung für Anwendungen innerhalb von Kubernetes.
In dieser Anleitung richtest du den Nginx Ingress Controller mit SSL-Zertifikaten in einem Kubernetes Engine Cluster ein. Du wirst zwei Beispielanwendungen bereitstellen und sie mit Let’s Encrypt-Zertifikaten absichern, die durch Cert Manager verwaltet werden. Außerdem wird gezeigt, wie du kommerzielle SSL-Zertifikate für TLS-Verschlüsselung integrieren kannst.
Voraussetzungen
Bevor du beginnst, stelle sicher, dass du Folgendes vorbereitet hast:
- Einen laufenden Kubernetes-Cluster mit mindestens zwei Nodes.
- Das Tool Kubectl ist installiert, um deinen Cluster zu verwalten.
- Der Paketmanager Helm ist auf deinem System eingerichtet.
- Eine gültige Domain, beispielsweise example.com.
Nginx Ingress Controller installieren
Füge zunächst das Nginx Ingress Helm-Repository hinzu.
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
Aktualisiere anschließend die Helm-Repositories, um die neuesten Charts zu laden.
$ helm repo update
Installiere nun den Nginx Ingress Controller in deinem Kubernetes-Cluster.
$ helm install ingress-nginx ingress-nginx/ingress-nginx
Nach der Installation wird dem Cluster automatisch ein LoadBalancer-Service hinzugefügt.
$ kubectl get services ingress-nginx-controller
Beispielausgabe:
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   LoadBalancer   10.101.22.249   <pending>     80:31915/TCP,443:30217/TCP   106s
Je nach Cloud-Anbieter kann es einige Minuten dauern, bis der Dienst eine EXTERNAL-IP erhält.
Cert Manager installieren
Installiere die neueste Version des Cert Managers mit folgendem Befehl:
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.yaml
Überprüfe regelmäßig die offizielle Cert Manager-Release-Seite, um sicherzustellen, dass du die aktuellste Version nutzt.
Kontrolliere anschließend die Cert Manager-Ressourcen im Namespace cert-manager:
$ kubectl get all -n cert-manager
Du solltest nun mehrere Pods, Services, ReplicaSets und Deployments sehen, die mit dem Cert Manager zusammenhängen.
Backend-Anwendungen bereitstellen
Als Nächstes werden zwei Beispielanwendungen — app1 und app2 — bereitgestellt, um die Ingress-Konfiguration zu testen. Beide verwenden das Image hashicorp/http-echo, das einen einfachen Text auf einer HTML-Seite ausgibt.
Deployment für App1 erstellen
$ nano app1-deploy.yaml
Füge die folgende Konfiguration ein:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: app1
        image: hashicorp/http-echo
        args: ["-text=Hello from App1"]
        ports:
        - containerPort: 5678
Deployment für App2 erstellen
$ nano app2-deploy.yaml
Füge diesen Inhalt hinzu:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app2
  template:
    metadata:
      labels:
        app: app2
    spec:
      containers:
      - name: app2
        image: hashicorp/http-echo
        args: ["-text=Hello from App2"]
        ports:
        - containerPort: 5678
Wende beide Deployment-Manifeste an:
$ kubectl apply -f app1-deploy.yaml
$ kubectl apply -f app2-deploy.yaml
Überprüfe, ob die Deployments erfolgreich ausgeführt werden:
$ kubectl get deployments
Service-Manifeste erstellen
Service für App1
$ nano app1-svc.yaml
Füge die folgende YAML-Konfiguration hinzu:
apiVersion: v1
kind: Service
metadata:
  name: app1-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app: app1
Service für App2
$ nano app2-svc.yaml
Füge diese Konfiguration hinzu:
apiVersion: v1
kind: Service
metadata:
  name: app2-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app: app2
Stelle anschließend beide Services bereit:
$ kubectl apply -f app1-svc.yaml
$ kubectl apply -f app2-svc.yaml
Überprüfe, ob alle Services korrekt ausgeführt werden:
$ kubectl get services
DNS-Einträge konfigurieren
Melde dich bei deinem DNS-Provider an und öffne die Domainverwaltung. Erstelle einen A-Record für app1, der auf die externe IP-Adresse deines LoadBalancers verweist. Wiederhole den Vorgang für app2 mit derselben IP-Adresse.
Anwendungen über den Nginx Ingress Controller bereitstellen
Erstelle nun Ingress-Ressourcen, um deine Backend-Anwendungen öffentlich zugänglich zu machen.
Ingress für App1
$ nano app1-ingress.yaml
Füge diesen Inhalt ein:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-app1
  annotations:
    cert-manager.io/issuer: letsencrypt-nginx
spec:
  ingressClassName: nginx
  rules:
  - host: app1.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: app1-svc
            port:
              number: 80
Ingress für App2
$ nano app2-ingress.yaml
Verwende den folgenden YAML-Inhalt:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-app2
  annotations:
    cert-manager.io/issuer: letsencrypt-nginx
spec:
  ingressClassName: nginx
  rules:
  - host: app2.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: app2-svc
            port:
              number: 80
Wende beide Ingress-Manifeste an:
$ kubectl apply -f app1-ingress.yaml
$ kubectl apply -f app2-ingress.yaml
Überprüfe, ob die Ingress-Ressourcen verfügbar sind:
$ kubectl get ingress
Es sollten sowohl ingress-app1 als auch ingress-app2 angezeigt werden. Warte, bis in der Spalte ADDRESS die IP deines LoadBalancers erscheint.
SSL-Zertifikate für Nginx Ingress aktivieren
Um HTTPS zu aktivieren, kannst du den Cert Manager so konfigurieren, dass er SSL-Zertifikate automatisch verwaltet. Cert Manager erweitert Kubernetes um benutzerdefinierte Ressourcen für die Ausstellung und Verwaltung von Zertifikaten durch vertrauenswürdige Zertifizierungsstellen wie Let’s Encrypt.
- Issuer: Definiert die Konfiguration eines Zertifikatsausstellers, etwa den Typ (ACME) und die Validierungsmethode (DNS01 oder HTTP01) innerhalb eines Namespaces.
- ClusterIssuer: Funktioniert wie der Issuer, kann jedoch Zertifikate für den gesamten Cluster ausstellen – ideal bei mehreren Namespaces.
- Certificate: Enthält Informationen über die Domainnamen, das zugehörige Secret und den gewählten Issuer.
Liste die verfügbaren CRDs für den Cert Manager auf:
$ kubectl get crd -l app.kubernetes.io/name=cert-manager
Die Ausgabe sollte Ressourcen wie issuers.cert-manager.io, certificates.cert-manager.io und clusterissuers.cert-manager.io enthalten, was bestätigt, dass die CRDs erfolgreich installiert wurden.
Let’s Encrypt-Zertifikate einrichten
Erstelle ein neues Issuer-Manifest namens cert-issuer.yaml, um Let’s Encrypt zu konfigurieren.
$ nano cert-issuer.yaml
Füge diese YAML-Konfiguration ein:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-nginx
spec:
  acme:
    email: hello@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-nginx-prod
    solvers:
    - http01:
        ingress:
          class: nginx
Diese Konfiguration erstellt einen ACME-Issuer mit folgenden Parametern:
- email: Die Kontaktadresse des ACME-Kontos. Verwende keine @example.com-Adresse, da der Issuer sonst inaktiv bleibt.
- server: Die API-URL des Let’s Encrypt-ACME-Dienstes.
- privateKeySecretRef: Gibt das Secret an, in dem der private Schlüssel des ACME-Kontos gespeichert wird.
- solvers: Definiert die Validierungsmethode, meist http01, außer bei Wildcard-Zertifikaten.
Ersetze die Beispiel-E-Mail-Adresse durch deine eigene und speichere die Datei.
Wende den Issuer im Cluster an:
$ kubectl apply -f cert-issuer.yaml
Überprüfe, ob der Issuer korrekt erstellt und initialisiert wurde:
$ kubectl get issuer
Beispielausgabe:
NAME                READY   AGE
letsencrypt-nginx   False   4s
Der Status READY zeigt zunächst False an und wechselt nach kurzer Zeit zu True.
Ingress-Ressourcen für TLS konfigurieren
Verknüpfe nun deine Ingress-Ressourcen mit den Let’s Encrypt-Zertifikaten.
Überprüfe zuerst den aktuellen Status deiner Ingress-Ressourcen:
$ kubectl get ingress
Bearbeite anschließend die Datei app1-ingress.yaml, um eine TLS-Sektion hinzuzufügen:
$ nano app1-ingress.yaml
Ergänze den folgenden Abschnitt unterhalb von spec:
tls:
  - hosts:
    - app1.example.com
    secretName: letsencrypt-nginx-app1
Das vollständige Manifest sieht wie folgt aus:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-app1
  annotations:
    cert-manager.io/issuer: letsencrypt-nginx
spec:
  ingressClassName: nginx
  rules:
  - host: app1.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: app1-svc
            port:
              number: 80
  tls:
  - hosts:
    - app1.example.com
    secretName: letsencrypt-nginx-app1
Füge denselben TLS-Abschnitt auch in die Datei app2-ingress.yaml ein:
tls:
  - hosts:
    - app2.example.com
    secretName: letsencrypt-nginx-app2
Wende anschließend die geänderten Manifeste an, um TLS für beide Hosts zu aktivieren:
$ kubectl apply -f app1-ingress.yaml
$ kubectl apply -f app2-ingress.yaml
Prüfe, ob deine Ingress-Ressourcen jetzt auch Port 443 aktiviert haben:
$ kubectl get ingress
Beispielausgabe:
NAME             CLASS    HOSTS               ADDRESS     PORTS    AGE
app1-ingress     nginx    app1.example.com    192.0.2.1   80,443   10m
app2-ingress     nginx    app2.example.com    192.0.2.1   80,443   10m
Zertifikatsressourcen prüfen
Überprüfe, ob die SSL-Zertifikate erfolgreich erstellt wurden:
$ kubectl get certificates
Beispielausgabe:
NAME              READY   SECRET                   AGE
letsencrypt-app1  True    letsencrypt-nginx-app1   5m
letsencrypt-app2  True    letsencrypt-nginx-app2   5m
Wenn die Spalte READY True anzeigt, wurden die Zertifikate erfolgreich ausgestellt. Falls sie False bleibt, überprüfe deine Ingress-Konfiguration und führe die Manifeste erneut aus, um neue Zertifikate anzufordern.
SSL-Konfiguration testen
Sobald die Zertifikate aktiv sind, teste die HTTPS-Verbindung im Browser:
Wenn du die Hosts über HTTP aufrufst, leitet der Ingress Controller automatisch auf HTTPS um.
Kommerzielle SSL-Zertifikate importieren
Wenn du ein SSL-Zertifikat von einer kommerziellen Zertifizierungsstelle erworben hast, kannst du dieses manuell importieren. Wandle dafür sowohl das Zertifikat als auch den privaten Schlüssel in Base64 um.
$ base64 -w 0 /path/ssl-certificate.pem
$ base64 -w 0 /path/cert-private-key.pem
Ersetze /path durch den tatsächlichen Pfad deiner Zertifikatsdateien.
Erstelle anschließend ein Kubernetes-Secret-Manifest:
$ nano ssl-secret.yaml
Füge folgende YAML-Konfiguration hinzu:
apiVersion: v1
kind: Secret
metadata:
  name: prod-ssl-secret
type: kubernetes.io/tls
data:
  tls.crt: 
  tls.key: 
Stelle sicher, dass:
- tls.crt das Base64-kodierte SSL-Zertifikat enthält.
- tls.key den Base64-kodierten privaten Schlüssel beinhaltet.
Speichere die Datei und wende sie an. Anschließend kannst du in deinem Ingress-Manifest unter spec.tls.secretName auf dieses Secret verweisen, um das kommerzielle SSL-Zertifikat zu aktivieren.
Fehlerbehebung
- Nginx 502 Gateway Error: Überprüfe deine Ingress-Konfiguration und stelle sicher, dass die referenzierten Services verfügbar und erreichbar sind.
- Let’s Encrypt-Zertifikate werden nicht generiert (READY = False): Kontrolliere deine Issuer- und Zertifikatseinstellungen, verwende eine gültige E-Mail-Adresse und prüfe die Logs des Issuers für weitere Hinweise.
Fazit
In dieser Anleitung hast du den Nginx Ingress Controller mit SSL-Zertifikaten auf einem Kubernetes Engine Cluster eingerichtet. Deine Umgebung kann nun eingehenden Datenverkehr sicher über HTTPS an die Cluster-Services weiterleiten – sowohl mit Let’s Encrypt- als auch mit kommerziellen SSL-Zertifikaten.


