Wie stelle ich externen Zugriff auf mehrere Kubernetes-Services in meinem Amazon EKS-Cluster bereit?
Ich möchte externen Zugriff auf mehrere Kubernetes-Services in meinem Amazon Elastic Kubernetes Service (Amazon EKS)-Cluster bereitstellen.
Kurzbeschreibung
Verwenden Sie den NGINX-Eingangscontroller oder den AWS Load Balancer-Controller für Kubernetes, um externen Zugriff auf mehrere Kubernetes-Services im Amazon EKS-Cluster bereitzustellen. Der NGINX-Eingangscontroller wird hauptsächlich von NGINX verwaltet. Um nach Problemen mit dem NGINX-Eingangscontroller zu suchen, sehen Sie sich die Liste der Probleme auf der GitHub-Website an. Der AWS Load Balancer-Controller wird von Amazon Web Services (AWS) verwaltet. Informationen zur Überprüfung auf Probleme mit dem AWS Load Balancer-Controller finden Sie in der Liste der Probleme auf der GitHub-Website.
Wichtig: Der Eingangscontroller und IngressClass (von der Kubernetes-Website) sind nicht identisch mit Ingress (von der Kubernetes-Website). Der Ingress ist eine Kubernetes-Ressource, die HTTP- und HTTPS-Routen von außerhalb des Clusters für die Services innerhalb des Clusters verfügbar macht. Der Eingangscontroller erfüllt den Ingress normalerweise mit einem Load Balancer. Sie können Ingress nicht ohne einen Eingangscontroller verwenden. Die IngressClass wird verwendet, um zu ermitteln, welcher Ingress-Controller für die Erfüllung der Ingress-Objektanforderung verwendet werden soll.
Voraussetzung: Installieren Sie den AWS Load Balancer-Controller. Es ist eine bewährte Methode, den AWS Load Balancer-Controller zu verwenden, um einen Network Load Balancer für Serviceobjekte vom Typ LoadBalancer in Amazon EKS zu erstellen und zu verwalten.
Lösung
Bei der folgenden Lösung wird der kubernetes/ingress-nginx-Eingangscontroller auf der Kubernetes-GitHub-Website verwendet. Der andere Eingangscontroller, der für die öffentliche Nutzung verfügbar ist, ist der nginxinc/kubernetes-ingress auf der NGINX-GitHub-Website.
NGINX-Eingangscontroller für Kubernetes bereitstellen
Sie können den NGINX-Eingangscontroller für Kubernetes entweder über das Transmission Control Protocol (TCP) oder Transport Layer Security (TLS) bereitstellen.
Hinweis: Die folgende Lösung wurde auf Amazon EKS Version 1.22, NGINX-Eingangscontroller Version 1.3.0 und AWS Load Balancer-Controller Version 2.4.3 getestet.
**(Option 1) NGINX-Eingangscontroller mit TCP auf Network Load Balancer **
1. Rufen Sie die YAML-Datei ab, um die folgenden Kubernetes-Objekte bereitzustellen: namespace, serviceaccounts, configmap, clusterroles, clusterrolebindings, roles, rolebindings, services, deployments, ingressclasses und validatingwebhookconfigurations.
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml
2. Bearbeiten Sie die Datei. Ersetzen Sie dann im Abschnitt mit den Serviceobjekten ingress-nginx-controller alle service.beta.kubernetes.io-Anmerkungen durch die folgenden:
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance" service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
3. Wenden Sie das Manifest an:
kubectl apply -f deploy.yaml
Beispiel für eine Ausgabe:
namespace/ingress-nginx created serviceaccount/ingress-nginx created configmap/ingress-nginx-controller created clusterrole.rbac.authorization.k8s.io/ingress-nginx created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created role.rbac.authorization.k8s.io/ingress-nginx created rolebinding.rbac.authorization.k8s.io/ingress-nginx created service/ingress-nginx-controller-admission created service/ingress-nginx-controller created deployment.apps/ingress-nginx-controller created ingressclass.networking.k8s.io/nginx created validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created serviceaccount/ingress-nginx-admission created clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
(Option 2) TLS-Terminierung des NGINX**-Eingangscontrollers auf dem Network Load Balancer**
Standardmäßig beendet die vorherige Lösung TLS im NGINX-Eingangscontroller. Sie können den NGINX Ingress-Dienst auch so konfigurieren, dass TLS am Network Load Balancer beendet wird.
1. Laden Sie die deploy.yaml-Vorlage herunter:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml
2. Bearbeiten Sie die Datei. Ersetzen Sie dann im Abschnitt mit den Serviceobjekten von ingress-nginx-controller alle service.beta.kubernetes.io-Anmerkungen durch die folgenden:
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443" service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance" service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
Hinweis: Stellen Sie sicher, dass Sie Ihren ARN für service.beta.kubernetes.io/aws-load-balancer-ssl-cert angeben.
3. Bearbeiten Sie die Datei und ändern Sie den CIDR von Amazon Virtual Private Cloud (Amazon VPC) für den Kubernetes-Cluster:
proxy-real-ip-cidr: XXX.XXX.XXX/XX
4. Wenden Sie das Manifest an:
kubectl apply -f deploy.yaml
Hinweis: Das vorherige Manifest verwendet ExternalTrafficPolicy als lokal, um die Quell-IP-Adresse (Client) beizubehalten. Die Verwendung dieser Konfiguration mit einem benutzerdefinierten DHCP-Namen in der Amazon VPC verursacht ein Problem. Um das Auftreten des Problems zu verhindern, wenden Sie den folgenden Patch auf den Kube-Proxy an:
kubectl edit daemonset kube-proxy -n kube-system
5. Bearbeiten Sie das Manifest so, dass es den folgenden Codeausschnitt enthält:
spec: template: spec: containers: - name: kube-proxy command: - kube-proxy - --hostname-override=$(NODE_NAME) - --v=2 - --config=/var/lib/kube-proxy-config/config env: - name: NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName
Überprüfen der bereitgestellten Ressourcen
AWS Load Balancer-Controller
Befehl:
kubectl get all -n kube-system --selector app.kubernetes.io/instance=aws-load-balancer-controller
Beispiel für eine Ausgabe:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/aws-load-balancer-controller-85cd8965dc-ctkjt 1/1 Running 0 48m 192.168.37.36 ip-192-168-59-225.us-east-2.compute.internal none none pod/aws-load-balancer-controller-85cd8965dc-wpwx9 1/1 Running 0 48m 192.168.53.110 ip-192-168-59-225.us-east-2.compute.internal none> none NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/aws-load-balancer-webhook-service ClusterIP 10.100.154.44 none 443/TCP 19h app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR deployment.apps/aws-load-balancer-controller 2/2 2 2 19h aws-load-balancer-controller 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0 app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR replicaset.apps/aws-load-balancer-controller-85cd8965dc 2 2 2 19h aws-load-balancer-controller 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0 app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller,pod-template-hash=85cd8965dc
NGINX-Eingangscontroller
Befehl:
kubectl get all -n ingress-nginx --selector app.kubernetes.io/instance=ingress-nginx
Beispiel für eine Ausgabe:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/ingress-nginx-controller-54d8b558d4-k4pdf 1/1 Running 0 56m 192.168.46.241 ip-192-168-59-225.us-east-2.compute.internal none none NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/ingress-nginx-controller LoadBalancer 10.100.99.129 ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80:32578/TCP,443:30724/TCP 15h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx service/ingress-nginx-controller-admission ClusterIP 10.100.190.61 none 443/TCP 15h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR deployment.apps/ingress-nginx-controller 1/1 1 1 15h controller k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR replicaset.apps/ingress-nginx-controller-54d8b558d4 1 1 1 15h controller k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx,pod-template-hash=54d8b558d4 NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR job.batch/ingress-nginx-admission-create 1/1 2s 15h create k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660 controller-uid=242bdf56-de16-471d-a691-1ca1dbc10a41 job.batch/ingress-nginx-admission-patch 1/1 2s 15h patch k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660 controller-uid=a9e710d2-5001-4d40-a435-ddc8993bfe42
IngressClass
Befehl:
kubectl get ingressclass
Beispiel für eine Ausgabe:
NAME CONTROLLER PARAMETERS AGE alb ingress.k8s.aws/alb IngressClassParams.elbv2.k8s.aws/alb 19h nginx k8s.io/ingress-nginx none 15h
Testen des Setup der Bereitstellung
Hinweis: Im folgenden Schritt werden zwei Microservices ausgeführt. Die Microservices werden intern mit Kubernetes als Standardtyp bereitgestellt.
1. Richten Sie Ihre Bereitstellungen oder Microservices ein. Zum Beispiel hostname-app und apache-app.
Beispiel einer hostname-app-svc.yaml-Datei für hostname-app:
apiVersion: apps/v1 kind: Deployment metadata: name: hostname-app namespace: default spec: replicas: 2 selector: matchLabels: app: hostname-app template: metadata: labels: app: hostname-app spec: containers: - name: hostname-app image: k8s.gcr.io/serve_hostname:1.1 --- apiVersion: v1 kind: Service metadata: name: hostname-svc namespace: default spec: ports: - port: 80 targetPort: 9376 protocol: TCP selector: app: hostname-app
Beispiel einer apache-app-svc.yaml-Datei für apache-app:
apiVersion: apps/v1 kind: Deployment metadata: name: apache-app namespace: default spec: replicas: 2 selector: matchLabels: app: apache-app template: metadata: labels: app: apache-app spec: containers: - name: apache-app image: httpd:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: apache-svc namespace: default labels: spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: app: apache-app
2. Wenden Sie Ihre Konfigurationen an.
hostname-app:
kubectl apply -f hostname-app-svc.yaml
apache-app:
kubectl apply -f apache-app-svc.yaml
3. Stellen Sie sicher, dass die Ressourcen erstellt werden.
Bereitstellungen
Befehl:
kubectl get deployment hostname-app apache-app -n default
Beispiel für eine Ausgabe:
NAME READY UP-TO-DATE AVAILABLE AGE hostname-app 2/2 2 2 29m apache-app 2/2 2 2 29m
Services
Befehl:
kubectl get svc apache-svc hostname-svc -n default
Beispiel für eine Ausgabe:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE apache-svc ClusterIP 10.100.73.51 none 80/TCP 29m hostname-svc ClusterIP 10.100.100.44 none 80/TCP 29m
Testen des NGINX-Eingangscontrollers
1. Greifen Sie über die Befehlszeile auf die DNS-URL des Load Balancers zu, den Sie abgerufen haben:
curl -I ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com
Beispiel für eine Ausgabe:
HTTP/1.1 404 Not Found Date: Thu, 03 Mar 2022 14:03:11 GMT Content-Type: text/html Content-Length: 146 Connection: keep-alive
Hinweis: Der Standardserver gibt für alle Domainanfragen, für die keine definierten Eingangsregeln gelten, eine 404 Nicht gefunden-Seite zurück. Basierend auf den definierten Regeln leitet der Eingangscontroller keinen Datenverkehr an den angegebenen Backend-Dienst um, es sei denn, die Anfrage entspricht der Konfiguration. Da das Host-Feld für das Eingangsobjekt konfiguriert ist, müssen Sie den Host-Header der Anfrage mit demselben Hostnamen angeben. Verwenden Sie in einer Testumgebung eine Curl-Flag, um den Host-Header bereitzustellen. Ordnen Sie in einer Produktionsumgebung den DNS-Namen des Load Balancers dem Hostnamen eines beliebigen DNS-Anbieters zu, z. B. Amazon Route 53.
2. Implementieren Sie den Eingang so, dass er mit Ihren Services verbunden ist, indem Sie einen einzigen Load Balancer verwenden, der vom NGINX-Eingangscontroller bereitgestellt wird.
Beispiel micro-ingress.yaml:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: micro-ingress namespace: default annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: hostname.mydomain.com http: paths: - backend: service: name: hostname-svc port: number: 80 path: / pathType: Prefix - host: apache.mydomain.com http: paths: - backend: service: name: apache-svc port: number: 80 path: / pathType: Prefix
Hinweis: Weitere Informationen finden Sie unter Namensbasiertes virtuelles Hosting (auf der Kubernetes-Website).
3. Stellen Sie sicher, dass die Ressource erstellt wird.
Eingang
Befehl:
kubectl get ingress -n default
Beispiel für eine Ausgabe:
NAME CLASS HOSTS ADDRESS PORTS AGE micro-ingress none hostname.mydomain.com,apache.mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 29m
4. Fügen Sie der Anfrage den Host-Header hinzu.
Erste konfigurierte Domain:
curl -i -H "Host: hostname.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/
Beispiel für eine Ausgabe:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 18:50:38 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive
Zweite konfigurierte Domain:
curl -i -H "Host: apache.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/
Beispiel für eine Ausgabe:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 18:51:00 GMT Content-Type: text/html Content-Length: 45 Connection: keep-alive Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT ETag: "2d-432a5e4a73a80" Accept-Ranges: bytes
Nach dem Hinzufügen des Host-Headers leitet der Eingangscontroller den Datenverkehr an den im Backend konfigurierten Dienst weiter, sofern er der Konfiguration entspricht, die im Eingang definiert ist.
Um den gleichen Domainnamen beizubehalten, den Datenverkehr jedoch auf der Grundlage des Pfads umzuleiten, auf den zugegriffen wird, müssen Sie dem Eingang pfadbasiertes Routing hinzufügen.
Zum Beispiel:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: path-ingress namespace: default annotations: kubernetes.io/ingress.class: nginxd nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: mydomain.com http: paths: - backend: service: name: hostname-svc port: number: 80 path: /hostname pathType: Prefix - host: mydomain.com http: paths: - backend: service: name: apache-svc port: number: 80 path: /apache pathType: Prefix
Hinweis: Wenn in Anfragen mydomain.com als Host-Header steht, gibt das vorherige Beispiel nur den Antwortcode 200 zurück. Auf die Anfragen wird entweder über die Pfade /hostname oder /apache zugegriffen. Für alle anderen Anfragen wird der Antwortcode 404 zurückgegeben.
5. Stellen Sie sicher, dass das pfadbasierte Routing hinzugefügt wird:
Befehl:
kubectl get ingress -n default
Ausgabe:
NAME CLASS HOSTS ADDRESS PORTS AGE micro-ingress none hostname.mydomain.com,apache.mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 164m path-ingress none mydomain.com,mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 120m
Befehl:
curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/hostname
– oder –
curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/apache
Eingang mit dem AWS Load Balancer-Controller testen
1. Starten Sie den Application Load Balancer mithilfe des folgenden Beispiel-Ingress-Manifests:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: micro-ingress-alb namespace: default annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: rules: - host: alb.hostname.mydomain.com http: paths: - backend: service: name: hostname-svc port: number: 80 path: / pathType: Prefix - host: alb.apache.mydomain.com http: - backend: service: name: apache-svc port: number: 80 path: / pathType: Prefix
2. Stellen Sie sicher, dass der Application Load Balancer gestartet wird.
Befehl:
kubectl get ingress -n default
Ausgabe:
NAME CLASS HOSTS ADDRESS PORTS AGE micro-ingress none hostname.mydomain.com,apache.mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 164m micro-ingress-alb none alb.hostname.mydomain.com,alb.apache.mydomain.com k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com 80 18m path-ingress none mydomain.com,mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 120m
Anfrage basierend auf der ersten konfigurierten Domain:
curl -i -H "Host: alb.hostname.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com
Beispiel für eine Ausgabe:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 20:46:02 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive
Anfrage basierend auf der zweiten konfigurierten Domain:
curl -i -H "Host: alb.apache.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com
Beispiel für eine Ausgabe:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 20:46:14 GMT Content-Type: text/html Content-Length: 45 Connection: keep-alive Server: Apache/2.4.53 (Unix) Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT ETag: "2d-432a5e4a73a80" Accept-Ranges: bytes
Relevanter Inhalt
- AWS OFFICIALAktualisiert vor 2 Jahren
- AWS OFFICIALAktualisiert vor 2 Jahren
- AWS OFFICIALAktualisiert vor 3 Jahren
- AWS OFFICIALAktualisiert vor 2 Jahren