Come posso fornire l'accesso esterno a più servizi Kubernetes nel mio cluster Amazon EKS?

10 minuti di lettura
0

Desidero fornire l'accesso esterno a più servizi Kubernetes nel mio cluster Amazon Elastic Kubernetes Service (Amazon EKS).

Breve descrizione

Usa il controller in ingresso NGINX o AWS Load Balancer Controller per Kubernetes per fornire l'accesso esterno a più servizi Kubernetes nel cluster Amazon EKS. Il controller in ingresso NGINX è gestito principalmente da NGINX. Per verificare la presenza di problemi nel controller in ingresso NGINX, consulta l'elenco dei problemi sul sito web di GitHub. AWS Load Balancer Controller è gestito da Amazon Web Services (AWS). Per verificare la presenza di problemi in AWS Load Balancer Controller, consulta l'elenco dei problemi sul sito web di GitHub.

Importante: Il controller in ingresso e IngressClass (dal sito web di Kubernetes) differiscono da Ingress (dal sito web di Kubernetes). Ingress è una risorsa di Kubernetes che espone i percorsi HTTP e HTTPS dall'esterno del cluster ai servizi all'interno del cluster. In genere, il controller in ingresso soddisfa Ingress con un sistema di bilanciamento del carico. Non è possibile usare Ingress senza un controller in ingresso. IngressClass viene utilizzato per identificare il controller in ingresso da utilizzare per soddisfare la richiesta dell'oggetto Ingress.

Prerequisito: Installa AWS Load Balancer Controller. È consigliabile utilizzare AWS Load Balancer Controller per creare e gestire un Network Load Balancer per gli oggetti assistenza di tipo LoadBalancer in Amazon EKS.

Risoluzione

La risoluzione seguente utilizza il controller in ingresso kubernetes/ingress-nginx sul sito web di Kubernetes GitHub. L'altro controller in ingresso di uso pubblico è nginxinc/kubernetes-ingress sul sito web di GitHub di NGINX.

Implementa il controller in ingresso NGINX per Kubernetes

Puoi implementare il controller in ingresso NGINX per Kubernetes tramite Transmission Control Protocol (TCP) o Transport Layer Security (TLS).

Nota: La seguente risoluzione è stata testata su Amazon EKS versione 1.22, controller in ingresso NGINX versione 1.3.0 e AWS Load Balancer Controller versione 2.4.3.

(Opzione 1) Controller in ingresso NGINX con TCP su Network Load Balancer

1.    Recupera il file YAML per implementare i seguenti oggetti: namespace, serviceaccounts, configmap, clusterroles, clusterrolebindings, roles, rolebindings, services, deployments, ingressclasses e validatingwebhookconfigurations.

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml

2.    Modifica il file. Quindi, nella sezione degli oggetti assistenza ingress-nginx-controller sostituisci tutte le annotazioni service.beta.kubernetes.io con le seguenti:

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.    Applica il manifesto:

kubectl apply -f deploy.yaml

Esempio di output:

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

(Opzione 2) Terminazione TLS del controller in ingresso NGINX su Network Load Balancer

Per impostazione predefinita, la soluzione precedente termina TLS nel controller in ingresso NGINX. È inoltre possibile configurare il servizio NGINX Ingress in modo che termini TLS su Network Load Balancer.

1.    Scarica il modello deploy.yaml:

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml

2.    Modifica il file. Quindi, nella sezione degli oggetti assistenza ingress-nginx-controller, sostituisci tutte le annotazioni service.beta.kubernetes.io con le seguenti:

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"

Nota: Assicurati di includere l’ARN per service.beta.kubernetes.io/aws-load-balancer-ssl-cert.

3.    Modifica il file e cambia il CIDR di Amazon Virtual Private Cloud (Amazon VPC) per il cluster Kubernetes:

proxy-real-ip-cidr: XXX.XXX.XXX/XX

4.    Applica il manifesto:

kubectl apply -f deploy.yaml

Nota: Il manifesto precedente utilizza ExternalTrafficPolicy come locale per preservare l'indirizzo IP di origine (client). L'utilizzo di questa configurazione con un nome DHCP personalizzato in Amazon VPC genera un problema. Per evitare il problema, applica la seguente patch al kube-proxy:

kubectl edit daemonset kube-proxy -n kube-system

5.    Modifica il manifesto in modo che includa il seguente frammento:

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

Verifica le risorse distribuite

AWS Load Balancer Controller

Comando:

kubectl get all -n kube-system --selector app.kubernetes.io/instance=aws-load-balancer-controller

Esempio di output:

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

Controller in ingresso NGINX

Comando:

kubectl get all -n ingress-nginx --selector app.kubernetes.io/instance=ingress-nginx

Esempio di output:

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

Comando:

kubectl get ingressclass

Esempio di output:

NAME    CONTROLLER             PARAMETERS                             AGE
alb     ingress.k8s.aws/alb    IngressClassParams.elbv2.k8s.aws/alb   19h
nginx   k8s.io/ingress-nginx   none                                   15h

Testa la configurazione della distribuzione

Nota: Il passaggio successivo prevede l'esecuzione di due microservizi. I microservizi sono esposti internamente con Kubernetes come tipo predefinito.

1.    Configura le distribuzioni o i microservizi. Ad esempio, hostname-app e apache-app.

Esempio di file hostname-app-svc.yaml per 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

Esempio di file apache-app-svc.yaml per 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.    Applica le configurazioni.

hostname-app:

kubectl apply -f hostname-app-svc.yaml

apache-app:

kubectl apply -f apache-app-svc.yaml

3.    Verifica che le risorse siano state create.

Distribuzioni

Comando:

kubectl get deployment hostname-app apache-app -n default

Esempio di output:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hostname-app   2/2     2            2           29m
apache-app     2/2     2            2           29m

Servizi

Comando:

kubectl get svc apache-svc hostname-svc -n default

Esempio di output:

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

Testa il controller in ingresso NGINX

1.    Accedi all'URL DNS del sistema di bilanciamento del carico recuperato dalla riga di comando:

curl -I ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com

Esempio di output:

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

**Nota:**Il server predefinito restituisce una pagina 404 Non trovato per tutte le richieste di dominio che non hanno regole di ingresso definite. In base alle regole definite, il controller in ingresso non devia il traffico verso il servizio backend specificato a meno che la richiesta non corrisponda alla configurazione. Poiché il campo host è configurato per l'oggetto Ingress, è necessario fornire l'intestazione Host della richiesta con lo stesso nome host. In un ambiente di test, usa un flag curl per fornire l'intestazione Host. In un ambiente di produzione, esegui il mapping del nome DNS del sistema di bilanciamento del carico al nome host di un provider DNS, ad esempio Amazon Route 53.

2.    Implementa l'ingresso in modo che si interfacci con i servizi utilizzando un sistema di bilanciamento del carico unico fornito dal controller in ingresso NGINX.

Esempio 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

Nota: Per ulteriori informazioni, consulta Hosting virtuale basato su nome (dal sito web di Kubernetes).

3.    Verifica che la risorsa sia stata creata.

Ingress

Comando:

kubectl get ingress -n default

Esempio di output:

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.    Aggiungi l’intestazione Host alla richiesta.

Primo dominio configurato:

curl -i -H "Host: hostname.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/

Esempio di output:

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

Secondo dominio configurato:

curl -i -H "Host: apache.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/

Esempio di output:

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

Dopo aver aggiunto l'intestazione Host, il controller in ingresso reindirizza il traffico al servizio configurato di backend in quanto corrisponde alla configurazione definita in Ingress.

Per mantenere lo stesso nome di dominio ma deviare il traffico in base al percorso a cui si accede, è necessario aggiungere un routing basato su percorso con Ingress.

Ad esempio:

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

Nota: Se le richieste hanno mydomain.com come intestazione Host, l'esempio precedente restituisce soltanto la risposta 200. È possibile accedere alle richieste tramite i percorsi /hostname e /apache. Per tutte le altre richieste, viene restituita la risposta 404.

5.    Verifica che sia stato aggiunto il routing basato su percorso:

Comando:

kubectl get ingress -n default

Uscita:

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

Comando:

curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/hostname

-oppure-

curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/apache

Verifica l'ingresso utilizzando AWS Load Balancer Controller

1.    Avvia Application Load Balancer utilizzando il seguente esempio di manifesto Ingress:

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.    Verifica che Application Load Balancer venga avviato.

Comando:

kubectl get ingress -n default

Uscita:

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

Richiesta basata sul primo dominio configurato:

curl -i -H "Host: alb.hostname.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com

Esempio di output:

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

Richiesta basata sul secondo dominio configurato:

curl -i -H "Host: alb.apache.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com

Esempio di output:

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

AWS UFFICIALE
AWS UFFICIALEAggiornata 2 anni fa