¿Cómo proporciono acceso externo a varios servicios de Kubernetes en mi clúster de Amazon EKS?

11 minutos de lectura
0

Quiero proporcionar acceso externo a varios servicios de Kubernetes en mi clúster de Amazon Elastic Kubernetes Service (Amazon EKS).

Descripción corta

Utilice el controlador de entrada NGINX o el controlador AWS Load Balancer para Kubernetes para proporcionar acceso externo a varios servicios de Kubernetes en su clúster de Amazon EKS. El controlador de ingreso de NGINX es mantenido principalmente por NGINX. Para comprobar si hay problemas con el controlador de ingreso de NGINX, consulte la lista de problemas en el sitio web de GitHub. Amazon Web Services (AWS) es mantenido por el AWS Load Balancer Controller. Para comprobar si hay problemas con AWS Load Balancer Controller, consulte la lista de problemas en el sitio web de GitHub.

**Importante:**El controlador de ingreso e IngressClass (del sitio web de Kubernetes) no son lo mismo que el Ingress (del sitio web de Kubernetes). El Ingress es un recurso de Kubernetes que expone las rutas HTTP y HTTPS desde fuera del clúster a los servicios del clúster. El controlador de ingreso normalmente completa el Ingress con un balanceador de carga. No puede usar Ingress sin un controlador de ingreso. La IngressClass se usa para identificar qué controlador de ingreso usar para cumplir con la solicitud de objetos Ingress.

Requisito previo:Instale el AWS Load Balancer Controller. Se recomienda utilizar el AWS Load Balancer Controller para crear y administrar un balanceador de carga de red para los objetos de servicio de tipo LoadBalancer en Amazon EKS.

Resolución

La siguiente resolución usa el controlador de ingreso kubernetes/ingress-nginx del sitio web GitHub de Kubernetes. El otro controlador de ingreso que está disponible para uso público es el nginxinc/kubernetes-ingress del sitio web de GitHub de NGINX.

Implemente el controlador de ingreso NGINX para Kubernetes

Puede implementar el controlador de ingreso NGINX para Kubernetes mediante el protocolo de control de transmisión (TCP) o la seguridad de la capa de transporte (TLS).

**Nota:**La siguiente resolución se probó en la versión 1.22 de Amazon EKS, la versión 1.3.0 del controlador de ingreso de NGINX y la versión 2.4.3 del controlador de carga de AWS.

(Opción 1) Controlador de ingreso NGINX con TCP en el balanceador de carga de red

  1. Obtenga el archivo YAML para implementar los siguientes objetos de Kubernetes: espacio de nombres, cuentas de servicio**,mapa de configuración**,roles de clúster, enlaces de roles, roles, role bindings,** servicios**, implementaciones, clases de ingreso, yvalidatingwebhookconfigurations.
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml
  1. Edite el archivo. A continuación, en la sección de objetos de servicio ingress-nginx-controller, sustituya todas las anotaciones de service.beta.kubernetes.io por las siguientes:
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"
  1. Aplique el manifiesto:
kubectl apply -f deploy.yaml

Ejemplo de salida:

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

(Opción 2) Terminación TLS del controlador de ingreso NGINX** en el balanceador de carga de red**

De forma predeterminada, la solución anterior termina TLS en el controlador de ingreso NGINX. También puede configurar el servicio NGINX Ingress para que termine TLS en el balanceador de carga de red.

  1. Descargue la plantilla deploy.yaml:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml
  1. Edite el archivo. A continuación, en la sección de objetos de servicio ingress-nginx-controller reemplace todas las anotaciones de service.beta.kubernetes.io por las siguientes:
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:**Asegúrese de incluir su ARN para service.beta.kubernetes.io/aws-load-balancer-ssl-cert.

  1. Edite el archivo y cambie el CIDR de Amazon Virtual Private Cloud (Amazon VPC) para el clúster de Kubernetes:
proxy-real-ip-cidr: XXX.XXX.XXX/XX
  1. Aplique el manifiesto:
kubectl apply -f deploy.yaml

**Nota:**El manifiesto anterior usa ExternalTrafficPolicy como local para conservar la dirección IP de origen (cliente). El uso de esta configuración con un nombre DHCP personalizado en Amazon VPC provoca un problema. Para evitar que se produzca el problema, aplique el siguiente parche al kube-proxy:

kubectl edit daemonset kube-proxy -n kube-system
  1. Edite el manifiesto para incluir el siguiente fragmento:
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

Verificar los recursos desplegados

Controlador AWS Load Balancer

Comando:

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

Ejemplo de salida:

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

Controlador de ingreso NGINX

Comando:

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

Ejemplo de salida:

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

Clase de ingreso

Comando:

kubectl get ingressclass

Ejemplo de salida:

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

Probar la configuración de despliegue

**Nota:El siguiente paso consiste en ejecutar dos micro servicios. Los micro servicios se exponen internamente con ** Kubernetes como tipo predeterminado.

  1. Configure sus implementaciones o micro servicios. Por ejemplo, hostname-app y apache-app.

Ejemplo de un hostname-app-svc.yaml archivo para** 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

Ejemplo de un apache-app-svc.yamlarchivo para 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
  1. Aplique sus configuraciones.

aplicación de nombre de host:

kubectl apply -f hostname-app-svc.yaml

aplicación apache:

kubectl apply -f apache-app-svc.yaml
  1. Compruebe que se hayan creado los recursos.

**Despliegues **

Comando:

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

Ejemplo de salida:

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

Servicios

Comando:

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

Ejemplo de salida:

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

Pruebe el controlador de ingreso NGINX

  1. Acceda a la URL DNS del balanceador de carga que has recuperado de la línea de comandos:
curl -I ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com

Ejemplo de salida:

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:**El servidor predeterminado devuelve una página 404 No encontrada para todas las solicitudes de dominio que no tienen reglas de ingreso definidas. Según las reglas definidas, el controlador de ingreso no desvía el tráfico al servicio de backend especificado a menos que la solicitud coincida con la configuración. Como el campo host está configurado para el objeto Ingress, debe proporcionar el encabezado Host de la solicitud con el mismo nombre de host. En un entorno de prueba, utilice un indicador curl para proporcionar el encabezado Host. En un entorno de producción, asigne el nombre DNS del balanceador de carga al nombre de host de cualquier proveedor de DNS, como Amazon Route 53.

  1. Implemente la entrada para que interactúe con sus servicios mediante un único balanceador de carga proporcionado por el controlador de ingreso NGINX.

Ejemplo de 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:**Para obtener más información, consulte Alojamiento virtual basado en nombres (del sitio web de Kubernetes).

  1. Compruebe que se haya creado el recurso.

Ingreso

Comando:

kubectl get ingress -n default

Ejemplo de salida:

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
  1. Añada el encabezado Host a la solicitud.

Primer dominio configurado:

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

Ejemplo de salida:

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

Segundo dominio configurado:

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

Ejemplo de salida:

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

Tras añadir el encabezado Host, el controlador de entrada redirige el tráfico al servicio configurado en el backend, ya que coincide con la configuración definida en el Ingress.

Para mantener el mismo nombre de dominio pero desviar el tráfico en función de la ruta a la que se accede, debe añadir el enrutamiento basado en rutas con el Ingress.

Por ejemplo:

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:**Si las solicitudes tienen mydomain.com como encabezado de Hostheader, el ejemplo anterior solo devuelve la respuesta 200. Se accede a las solicitudes a través de las rutas /hostname o /apache paths. Para todas las demás solicitudes, se devuelven respuestas 404.

  1. Verifique que se haya agregado el enrutamiento basado en rutas:

Comando:

kubectl get ingress -n default

Salida:

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

-o-

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

Pruebe la entrada con el controlador AWS Load Balancer

  1. Inicie el balanceador de carga de aplicaciones mediante el siguiente ejemplo de manifiesto de ingreso:
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
  1. Compruebe que se inicie el balanceador de carga de aplicaciones.

Comando:

kubectl get ingress -n default

Salida:

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

Solicitud basada en el primer dominio configurado:

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

Ejemplo de salida:

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

Solicitud basada en el segundo dominio configurado:

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

Ejemplo de salida:

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

OFICIAL DE AWS
OFICIAL DE AWSActualizada hace 2 años