Das ultimative Ziel der Anwendungsentwicklung besteht natürlich darin, Apps im Internet verfügbar zu machen. Für einen Entwickler vereinfacht Kubernetes diesen Prozess bis zu einem gewissen Grad, indem es den Ingress-Controller als Mechanismus zum Weiterleiten von Anforderungen an die Anwendung bereitstellt. Allerdings ist nicht alles so selbstbedienbar, wie Sie es sich wahrscheinlich wünschen: Sie benötigen weiterhin einen Eintrag im Domain Name System (DNS), um den Domänennamen für die App der IP-Adresse des Ingress-Controllers zuzuordnen, und ein TLS-Zertifikat, um Verbindungen mit HTTPS zu sichern. In den meisten Organisationen besitzen Sie DNS oder TLS nicht selbst und müssen sich daher mit der (oder den) operativen Gruppe(n!) abstimmen, die darüber verfügen.
Für die Betreiber wird es dadurch nicht unbedingt einfacher. In den meisten Organisationen ist die Notwendigkeit zur Aktualisierung von DNS-Einträgen so selten, dass entsprechende Verfahren – sowohl Geschäftsregeln als auch die eigentlichen technischen Schritte – eher spärlich oder gar nicht vorhanden sind. Dies bedeutet, dass Sie, wenn Sie einen DNS-Eintrag hinzufügen müssen, zuerst die Dokumentation suchen, einen Kollegen fragen oder (im schlimmsten Fall) es selbst herausfinden müssen. Sie müssen außerdem sicherstellen, dass Sie sämtliche Sicherheitsregeln des Unternehmens einhalten und dass der eingehende Datenverkehr für die Firewalls ordnungsgemäß gekennzeichnet ist.
Glücklicherweise gibt es eine Möglichkeit, sowohl Entwicklern als auch Betreibern das Leben zu erleichtern. In diesem Beitrag zeigen wir, wie Betreiber eine Kubernetes-Bereitstellung konfigurieren können, um Entwicklern die Aktualisierung von DNS-Einträgen und die Generierung von TLS-Zertifikaten in einer Kubernetes-Umgebung im Self-Service zu ermöglichen. Indem Sie die Infrastruktur frühzeitig ausbauen, können Sie sicherstellen, dass alle notwendigen geschäftlichen und technischen Anforderungen erfüllt werden.
Wenn die Lösung vorhanden ist, muss ein Entwickler, um eine Anwendung im Internet verfügbar zu machen, lediglich einen Ingress-Controller gemäß einer bereitgestellten Vorlage erstellen, die einen vollqualifizierten Domänennamen (FQDN) innerhalb einer von der Kubernetes-Installation verwalteten Domäne enthält. Kubernetes verwendet die Vorlage, um dem Ingress-Controller eine IP-Adresse zuzuweisen, den DNS- A
-Eintrag zu erstellen, um den FQDN der IP-Adresse zuzuordnen, TLS-Zertifikate für den FQDN zu generieren und sie dem Ingress-Controller hinzuzufügen. Die Bereinigung ist ebenso einfach: Wenn der Ingress entfernt wird, werden die DNS-Einträge bereinigt.
Die Lösung nutzt die folgenden Technologien (Anweisungen zur Installation und Konfiguration finden Sie weiter unten):
Bevor Sie die Lösung konfigurieren, benötigen Sie:
LoadBalancer
). Die Lösung verwendet Linode, aber auch andere Cloud-Anbieter funktionieren.kubectl
als Befehlszeilenschnittstelle für Kubernetes.Wir setzen außerdem voraus, dass Sie über grundlegende Kenntnisse von Kubernetes verfügen (wie Sie ein Manifest anwenden, ein Helm-Diagramm verwenden und kubectl
-Befehle ausgeben, um die Ausgabe anzuzeigen und Probleme zu beheben). Das Verständnis der grundlegenden Konzepte von Let‘s Encrypt ist hilfreich, aber nicht erforderlich; einen Überblick finden Sie in unserem Blog . Sie müssen auch nicht wissen, wie der Cert-Manager funktioniert, aber wenn Sie daran interessiert sind, wie er (und Zertifikate im Allgemeinen) mit dem NGINX Ingress Controller funktionieren, lesen Sie meinen neuesten Beitrag „Automatisierung der Zertifikatsverwaltung in einer Kubernetes-Umgebung “.
Wir haben die Lösung sowohl auf macOS als auch auf Linux getestet. Wir haben es nicht auf dem Windows-Subsystem für Linux Version 2 (WSL2) getestet, erwarten aber keine Probleme.
Notiz: Die Lösung ist als Beispiel für einen Proof of Concept gedacht und nicht für den Produktionseinsatz. Insbesondere berücksichtigt es nicht alle Best Practices für Betrieb und Sicherheit. Informationen zu diesen Themen finden Sie in der Cert-Manager- und ExternalDNS -Dokumentation.
Befolgen Sie die Schritte in diesen Abschnitten, um die Lösung bereitzustellen:
Klonen Sie das NGINX Ingress Controller-Repository:
$ git clone https://github.com/nginxinc/kubernetes-ingress.gitCloning into 'kubernetes-ingress'...
remote: Enumerating objects: 45176, done.
remote: Counting objects: 100% (373/373), done.
remote: Compressing objects: 100% (274/274), done.
remote: Total 45176 (delta 173), reused 219 (delta 79), pack-reused 44803
Receiving objects: 100% (45176/45176), 60.45 MiB | 26.81 MiB/s, done.
Resolving deltas: 100% (26592/26592), done.
Überprüfen Sie, ob Sie eine Verbindung zum Kubernetes-Cluster herstellen können.
$ kubectl cluster-infoKubernetes control plane is running at https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443
KubeDNS is running at https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Stellen Sie mit Helm den NGINX Ingress Controller bereit. Beachten Sie, dass wir drei nicht standardmäßige Konfigurationsoptionen hinzufügen:
controller.enableCustomResources
– Fordert Helm auf, die benutzerdefinierten Ressourcendefinitionen (CRDs) zu installieren, mit denen Sie die NGINX VirtualServer und VirtualServerRoute Custom Resources anlegen.controller.enableCertManager
– Konfiguriert den NGINX Ingress Controller für die Kommunikation mit Cert-Manager -Komponenten.controller.enableExternalDNS
– Konfiguriert den Ingress Controller für die Kommunikation mit ExternalDNS-Komponenten.$ helm install nginx-kic nginx-stable/nginx-ingress --namespace nginx-ingress --set controller.enableCustomResources=true --create-namespace --set controller.enableCertManager=true --set controller.enableExternalDNS=trueNAME: nginx-kic
LAST DEPLOYED: Day Mon DD hh:mm:ss YYYY
NAMESPACE: nginx-ingress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The NGINX Ingress Controller has been installed.
Überprüfen Sie, ob der NGINX Ingress Controller ausgeführt wird, und notieren Sie sich den Wert im Feld „EXTERNAL-IP“
. Dies ist die IP-Adresse für den NGINX Ingress Controller (hier: www.xxx.yyy.zzz
). Die Ausgabe ist der Lesbarkeit halber auf zwei Zeilen verteilt.
$ kubectl get services --namespace nginx-ingressNAME TYPE CLUSTER-IP ...
nginx-kic-nginx-ingress LoadBalancer 10.128.152.88 ...
... EXTERNAL-IP PORT(S) AGE
... www.xxx.yyy.zzz 80:32457/TCP,443:31971/TCP 3h8m
In der Lösung verwendet cert-manager beim Abrufen eines TLS-Zertifikats den Challenge-Typ DNS-01 und verlangt, dass Sie bei der Erstellung der ClusterIssuer-Ressource das Cloudflare-API-Token bereitstellen. Das API-Token wird dabei als Kubernetes-Secret hinterlegt.
Stellen Sie mit Helm den Cert-Manager bereit :
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.9.1 --set installCRDs=trueNAME: cert-manager
LAST DEPLOYED: Day Mon DD hh:mm:ss YYYY
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager v1.9.1 has been deployed successfully!
Stellen Sie das Cloudflare-API-Token als Kubernetes-Geheimnis bereit und ersetzen Sie es durch <Ihr API-Token>
:
$ kubectl apply -f - <<EOFapiVersion: v1
kind: Secret
metadata:
name: Cloudflare-api-token-secret
namespace: cert-manager
type: Opaque
stringData:
api-token: "<your-API-token>"
EOF
secret/Cloudflare-api-token-secret created
Erstellen Sie ein ClusterIssuer-Objekt und geben Sie Cloudflare-api-token-secret
(im vorherigen Schritt definiert) als Ort zum Abrufen des Tokens an. Wenn Sie möchten, können Sie „example-issuer“
im Feld „metadata.name“
(und „example-issuer-account-key“
im Feld „spec.acme.privateKeySecretRef.name“
) durch einen anderen Namen ersetzen.
$ kubectl apply -f - <<EOFapiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: example-issuer
namespace: cert-manager
spec:
acme:
email: example@example.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: example-issuer-account-key
solvers:
- dns01:
Cloudflare:
apiTokenSecretRef:
name: Cloudflare-api-token-secret
key: api-token
EOF
clusterissuer.cert-manager.io/example-issuer created
Überprüfen Sie, ob der ClusterIssuer bereitgestellt und bereit ist (der Wert im Feld READY
ist True
).
$ kubectl get clusterissuerNAME READY AGE
example-issuer True 3h9m
Wie cert-manager erfordert das ExternalDNS-Projekt ein Cloudflare-API-Token zur Verwaltung von DNS. Derselbe Token kann für beide Projekte verwendet werden, das ist jedoch nicht erforderlich.
Erstellen Sie die ExternalDNS-CRDs für den NGINX Ingress Controller, um die Integration zwischen den Projekten zu ermöglichen.
$ kubectl create -f ./kubernetes-ingress/deployments/common/crds/externaldns.nginx.org_dnsendpoints.yamlcustomresourcedefinition.apiextensions.k8s.io/dnsendpoints.externaldns.nginx.org created
Erstellen Sie den externen DNS-Dienst ( external-dns
). Da das Manifest ziemlich lang ist, teilen wir es hier in zwei Teile auf. Der erste Teil konfiguriert Konten, Rollen und Berechtigungen:
„external-dns“,
um alle Schreib- und Aktualisierungsvorgänge für die DNS-Verwaltung zu verwalten.external-dns
genannt), das die erforderlichen Berechtigungen definiert.$ kubectl apply -f - <<EOFapiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: ["externaldns.nginx.org"]
resources: ["dnsendpoints"]
verbs: ["get","watch","list"]
- apiGroups: ["externaldns.nginx.org"]
resources: ["dnsendpoints/status"]
verbs: ["update"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: default
EOF
serviceaccount/external-dns created
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created
Der zweite Teil des Manifests erstellt die ExternalDNS-Bereitstellung:
den Domänenfilter
auf example.com
.CF_API_TOKEN
auf Ihr Cloudflare-API-Token fest. Für <Ihr API-Token>
, ersetzen Sie entweder das eigentliche Token oder ein Geheimnis, das das Token enthält. Im letzteren Fall müssen Sie das Geheimnis auch mithilfe einer Umgebungsvariablen in den Container projizieren .FREE_TIER
auf „true“
(angemessen, sofern Sie nicht über ein kostenpflichtiges Cloudflare-Abonnement verfügen).$ kubectl apply -f - <<EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:v0.12.0
args:
- --source=service
- --source=ingress
- --source=crd
- --crd-source-apiversion=externaldns.nginx.org/v1
- --crd-source-kind=DNSEndpoint
- --domain-filter=example.com
- --provider=Cloudflare
env:
- name: CF_API_TOKEN
value: "<your-API-token>"
- name: FREE_TIER
value: "true"
EOF
serviceaccount/external-dns created
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created
deployment.apps/external-dns created
Verwenden Sie zu Testzwecken die standardmäßige NGINX Ingress Controller-Beispielanwendung namens Cafe .
Stellen Sie die Cafe-Anwendung bereit.
$ kubectl apply -f ./kubernetes-ingress/examples/ingress-resources/complete-example/cafe.yamldeployment.apps/coffee created
service/coffee-svc created
deployment.apps/tea created
service/tea-svc created
Stellen Sie den NGINX Ingress Controller für die Cafe-Anwendung bereit. Beachten Sie folgende Einstellungen:
Art: VirtualServer
– Wir verwenden die NGINX VirtualServer benutzerdefinierte Ressource statt der standardmäßigen Kubernetes Ingress-Ressource.spec.host
– Ersetzen Sie cafe.example.com
durch den Namen des Hosts, den Sie bereitstellen. Der Host muss sich innerhalb der Domäne befinden, die mit ExternalDNS verwaltet wird.spec.tls.cert-manager.cluster-issuer
– Wenn Sie die in diesem Beitrag angegebenen Werte verwendet haben, ist dies example-issuer
. Ersetzen Sie ihn bei Bedarf durch den Namen, den Sie in Schritt 3 von „Cert‑Manager bereitstellen“ gewählt haben.spec.externalDNS.enable
– Der Wert „true“
weist ExternalDNS an, einen DNS- A-
Eintrag zu erstellen.Beachten Sie, dass die für diesen Schritt benötigte Zeit stark vom DNS-Anbieter abhängt, da Kubernetes mit der DNS-API des Anbieters interagiert.
$ kubectl apply -f - <<EOFapiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: cafe
spec:
host: cafe.example.com
tls:
secret: cafe-secret
cert-manager:
cluster-issuer: example-issuer
externalDNS:
enable: true
upstreams:
- name: tea
service: tea-svc
port: 80
- name: coffee
service: coffee-svc
port: 80
routes:
- path: /tea
action:
pass: tea
- path: /coffee
action:
pass: coffee
EOF
virtualserver.k8s.nginx.org/cafe created
Überprüfen Sie den DNS- A-
Eintrag – insbesondere, ob im Block ANSWER
SECTION
der FQDN (hier cafe.example.com
) der richtigen IP-Adresse ( www.xxx.yyy.zzz
) zugeordnet ist.
$ dig cafe.example.com
; <<>> DiG 9.10.6 <<>> cafe.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22633
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;cafe.example.com. IN A
;; ANSWER SECTION:
cafe.example.com. 279 IN A www.xxx.yyy.zzz
;; Query time: 1 msec
;; SERVER: 2607:fb91:119b:4ac4:2e0:xxxx:fe1e:1359#53(2607:fb91:119b:4ac4:2e0:xxxx:fe1e:1359)
;; WHEN: Day Mon DD hh:mm:ss TZ YYYY
;; MSG SIZE rcvd: 67
Überprüfen Sie, ob das Zertifikat gültig ist (der Wert im Feld READY
ist True
).
$ kubectl get certificatesNAME READY SECRET AGE
cafe-secret True cafe-secret 8m51s
Überprüfen Sie, ob Sie die Anwendung erreichen können.
$ curl https://cafe.example.com/coffeeServer address: 10.2.2.4:8080
Server name: coffee-7c86d7d67c-lsfs6
Date: DD/Mon/YYYY:hh:mm:ss +TZ-offset
URI: /coffee
Request ID: 91077575f19e6e735a91b9d06e9684cd
$ curl https://cafe.example.com/tea
Server address: 10.2.2.5:8080
Server name: tea-5c457db9-ztpns
Date: DD/Mon/YYYY:hh:mm:ss +TZ-offset
URI: /tea
Request ID: 2164c245a495d22c11e900aa0103b00f
Hinter den Kulissen läuft viel, sobald Sie die Lösung implementiert haben. Das Diagramm zeigt, was passiert, wenn Sie den NGINX Ingress Controller mit einer benutzerdefinierten NGINX VirtualServer-Ressource bereitstellen. Dabei lassen wir einige betriebliche Details aus.
A
-Eintrag zu erstellenA-
Eintrag im DNSAngesichts der Komplexität von Kubernetes und der von uns verwendeten Komponenten ist es schwierig, eine umfassende Anleitung zur Fehlerbehebung bereitzustellen. Dennoch gibt es einige grundlegende Vorschläge, die Ihnen bei der Ermittlung des Problems helfen können.
„kubectl
get“
und „kubectl
describe“,
um die Konfiguration bereitgestellter Objekte zu validieren.kubectl
Protokolle
<Komponente>
Befehl zum Anzeigen der Protokolldateien für die verschiedenen bereitgestellten Komponenten.Wenn Sie weiterhin Probleme haben, finden Sie uns im NGINXCommunity Slack und bitten Sie um Hilfe! Wir haben eine lebendige Community und arbeiten Probleme immer gerne gemeinsam durch.
Um den auf NGINX Plus basierenden NGINX Ingress Controller auszuprobieren, starten Sie noch heute Ihre 30-tägige kostenlose Testversion oder kontaktieren Sie uns, um Ihre Anwendungsfälle zu besprechen .
„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."