BLOG | NGINX

Cómo simplificar la gestión del tráfico de entrada y salida de Kubernetes

Miniatura de Kate Osborn
Kate Osborn
Publicado el 28 de junio de 2021

Una de las formas en que una malla de servicios puede hacer que sea más complicado administrar un entorno de Kubernetes es cuando debe configurarse por separado del controlador de Ingress . Las configuraciones separadas no sólo consumen mucho tiempo. Aumentan la probabilidad de errores de configuración que pueden impedir el enrutamiento adecuado del tráfico e incluso provocar vulnerabilidades de seguridad (como actores maliciosos que obtienen acceso a aplicaciones restringidas) y malas experiencias (como clientes que no pueden acceder a aplicaciones para las que están autorizados). Además del tiempo que lleva realizar configuraciones separadas, terminas gastando más tiempo solucionando errores.

Puede evitar estos problemas y ahorrar tiempo al integrar el controlador de ingreso NGINX basado en NGINX Plus con NGINX Service Mesh para controlar el tráfico mTLS de ingreso y egreso. En esta demostración en video, cubrimos los pasos completos.

La documentación de apoyo se referencia en las siguientes secciones:

Prerrequisitos (0:18)

Antes de comenzar la demostración real, realizamos estos requisitos previos:

  1. Instalé el plano de control de NGINX Server Mesh en el clúster Kubernetes y configuré mTLS y la política estricta para la malla de servicio .

  2. Instalé NGINX Ingress Controller basado en NGINX Plus como una implementación (en lugar de un DaemonSet) en el clúster de Kubernetes, habilité egress y lo expuse como un servicio de tipo LoadBalancer .

    Nota:  La demostración no funciona con el controlador de ingreso NGINX basado en código abierto. Para facilitar la lectura, en el resto de este blog nos referiremos al controlador de ingreso NGINX basado en NGINX Plus simplemente como “Controlador de ingreso NGINX”.

  3. Seguí nuestras instrucciones para descargar la aplicación de muestra bookinfo , inyectar el sidecar NGINX Service Mesh e implementar la aplicación.

Como resultado de la estricta política creada en el Paso 1, las solicitudes a la aplicación bookinfo desde clientes fuera de la malla se rechazan en el sidecar. Lo ilustramos en la demostración ejecutando primero el siguiente comando para configurar el reenvío de puertos:

> kubectl port-forward svc/product-page 9080Forwarding from 127.0.0.1:9080 -> 9080
Forwarding from [::1]:9080 -> 9080
Handling connection for 9080

Cuando intentamos acceder a la aplicación, obtenemos un código de estado503 porque nuestra máquina local no es parte de la malla de servicio:

> curl localhost:9080503

Implementación del controlador de entrada NGINX con NGINX Service Mesh (1:50)

La primera etapa del proceso de exposición de una aplicación es implementar una instancia de controlador de ingreso NGINX. Las instrucciones correspondientes se proporcionan en nuestro tutorial, Implementar con NGINX Plus Ingress Controller para Kubernetes .

NGINX proporciona manifiestos de implementación y DaemonSet para este propósito. En la demostración, usamos el manifiesto de implementación, nginx-plus-ingress.yaml . Incluye anotaciones para enrutar el tráfico de ingreso y egreso a través de la misma instancia del controlador de ingreso NGINX:

El manifiesto permite la integración directa de NGINX Ingress Controller con Spire, la autoridad de certificación (CA) para NGINX Service Mesh, eliminando la necesidad de inyectar el sidecar de NGINX Service Mesh en NGINX Ingress Controller. En su lugar, NGINX Ingress Controller obtiene certificados y claves directamente de la CA de Spire para usarlos para mTLS con los pods en la malla. El manifiesto especifica la dirección del agente Spire:

y monta el socket UNIX del agente Spire en el pod del controlador de ingreso NGINX:

Lo último que hay que tener en cuenta sobre el manifiesto es el argumento CLI -enable-internal-routes , que nos permite enrutar a los servicios de salida:

Antes de comenzar la demostración, ejecutamos el comando kubectl apply -f nginx-plus-ingress.yaml para instalar NGINX Ingress Controller y, en este punto, inspeccionamos la implementación en el espacio de nombres nginx-ingress . Como se muestra en la columna LISTO de la siguiente salida, solo hay un contenedor para el pod NGINX Ingress Controller, porque no lo hemos inyectado con un sidecar NGINX Service Mesh.

También hemos implementado un servicio de tipo LoadBalancer para exponer la dirección IP externa del controlador de ingreso NGINX (aquí, 35.233.133.188) fuera del clúster. Accederemos a la aplicación de muestra bookinfo en esa dirección IP.

> kubectl get pods --namespace=nginx-ingressNAME                                 READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-867f954b8f0fzdrm   1/1     Running   0          3d3h

NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP      ...
service-nginx-ingress   LoadBalancer   10.31.245.207   35.233.133.188   ...

      ... PORT(S)                      AGE
      ... 80:31469/TCP,443:32481/TCP   4d2h
...

Uso de un recurso de ingreso estándar de Kubernetes para exponer la aplicación (3:55)

Ahora exponemos la aplicación bookinfo en la malla, utilizando un recurso Ingress de Kubernetes estándar como se define en bookinfo-ingress.yaml . Las instrucciones correspondientes se proporcionan en nuestro tutorial, Exponer una aplicación con el controlador de ingreso NGINX Plus .

El recurso hace referencia a un secreto de Kubernetes para la aplicación bookinfo en la línea 10 e incluye una regla de enrutamiento que especifica que las solicitudes para bookinfo.example.com se envían al servicio productpage ( líneas 11 a 18 ). El secreto se define en bookinfo-secret.yaml :

Ejecutamos este comando para cargar la clave y el certificado, que en la demo está autofirmado:

> kubectl apply -f bookinfo-secret.yamlsecret/bookinfo-secret unchanged

Activamos el recurso Ingress:

> kubectl apply -f bookinfo-ingress.yamlingress.networking.k8s.io/bookinfo-ingress deleted

y verificar que Ingress Controller agregó la ruta definida en el recurso, como lo confirma el evento al final de la salida:

> kubectl describe ingress bookinfo-ingress...
Events:
  Type    Reason          Age   From                      Message
  ----    ------          ----  ----                      -------
  Normal  AddedOrUpdated  5s    nginx-ingress-controller  Configuration for ...
        ...default/bookinfo-ingress was added or updated

En la demostración ahora usamos un navegador para acceder a la aplicación bookinfo en https://bookinfo.example.com/ . (Anteriormente hemos agregado una asignación en el archivo /etc/hosts local entre la dirección IP del servicio Ingress Controller – 35.233.133.188 en la demostración, como se indicó anteriormente – y bookinfo.example.com . Para obtener instrucciones, consulte la documentación .) La información en la sección Reseñas de libros de la página cambia periódicamente a medida que las solicitudes rotan entre las tres versiones del servicio de reseñas definido en bookinfo.yaml ( descargar ).

A continuación inspeccionamos el tráfico de entrada a los clústeres. Ejecutamos el script generate-traffic.sh para realizar solicitudes al servicio productpage a través de la dirección IP pública del controlador de ingreso NGINX y luego ejecutamos el comando nginx-meshctl top para monitorear el tráfico:

> nginxmesh-ctl top deploy/productpage-v1Deployment       Direction  Resource       Success Rate  P99    P90    P50   ...
productpage-v1  
                 To         details-v1     100.00%       3ms    3ms    2ms   
                 To         reviews-v2     100.00%       99ms   90ms   20ms
                 To         reviews-v3     100.00%       99ms   85ms   18ms
                 To         reviews-v1     100.00%       20ms   17ms   9ms
                 From       nginx-ingress  100.00%       192ms  120ms  38ms

      ... NumRequests 
      ... 14
      ... 5
      ... 5
      ... 12

Uso de un recurso de servidor virtual NGINX para exponer la aplicación (6:45)

A continuación mostramos una forma alternativa de exponer una aplicación, utilizando un recurso NGINX VirtualServer . Es un recurso de controlador de ingreso NGINX personalizado que admite un manejo de tráfico más complejo, como división de tráfico y enrutamiento basado en contenido.

Primero eliminamos el recurso Ingress estándar:

> kubectl delete -f bookinfo-ingress.yamlingress.networking.k8s.io "bookinfo-ingress" deleted

Nuestro archivo bookinfo-vs.yaml configura mTLS con el mismo secreto que en bookinfo-ingress.yaml ( líneas 7-8 ). Las líneas 9 a 12 definen el servicio productpage como el upstream, y las líneas 13 a 24 una ruta que envía todas las solicitudes GET realizadas en bookinfo.example.com a ese upstream. Para los métodos HTTP distintos de GET , devuelve el código de estado405 .

Aplicamos el recurso:

> kubectl apply -f bookinfo-vs.yamlvirtualserver.kubernetes.nginx.org/bookinfo-vs created

Luego realizamos los mismos pasos que con el recurso Ingress: ejecutamos el comando kubectl describe para confirmar la implementación correcta y acceder a la aplicación en un navegador. Otra confirmación de que la aplicación funciona correctamente es que rechaza el método POST :

> curl -k -X POST https://bookinfo.example.com/Method not allowed

Configuración de una ruta de salida segura con el controlador de entrada NGINX (8:44)

Ahora mostramos cómo enrutar el tráfico de salida a través del controlador de ingreso NGINX. Nuestro tutorial Configurar una ruta de salida segura con NGINX Plus Ingress Controller cubre el proceso mediante el uso de diferentes aplicaciones de muestra.

Ya hemos definido un pod bash simple en bash.yaml y lo hemos implementado en el espacio de nombres predeterminado desde donde enviamos solicitudes. Como se muestra en la columna LISTO de esta salida, se ha inyectado con el sidecar NGINX Service Mesh.

> kubectl get allNAME                        READY  STATUS    RESTARTS   AGE
pod/bash-6ccb678958-zsgm7   2/2    Running   0          77s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.31.240.1   <none>        443/TCP   4d2h
...

Hay varios casos de uso en los que es posible que desee habilitar solicitudes desde dentro del pod a un servicio de salida , que es cualquier entidad que no sea parte de NGINX Service Mesh. Algunos ejemplos son los servicios implementados:

  • Fuera del cluster
  • En otro cluster
  • En el mismo clúster, pero no inyectado con el sidecar NGINX Service Mesh

En la demostración, consideramos el caso de uso final. Tenemos una aplicación implementada en el espacio de nombres heredado , que no está controlado por NGINX Service Mesh y donde la inyección automática del sidecar de NGINX Service Mesh está deshabilitada. Solo hay un pod ejecutándose para la aplicación.

> kubectl get all --namespaces=legacyNAME                          READY  STATUS    RESTARTS   AGE
pod/target-5f7bcb96c6-km9lz   1/1    Running   0          27m

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/target-svc   ClusterIP   10.31.245.213   <none>        80/TCP,443/TCP   27m
...

Recuerde que hemos configurado una política mTLS estricta para NGINX Service Mesh; como resultado, no podemos enviar solicitudes directamente desde el pod bash al servicio de destino, porque ambos no pueden autenticarse entre sí. Cuando lo intentamos, obtenemos un código de estado.503 como se ilustra aquí:

> kubectl exec -it bash-6ccb678958-zsgm7 -c bash -- curl target-svc.legacycurl: (56) Recv failure: connection reset by peer
503command terminated with exit code 56

La solución es permitir que el pod bash envíe tráfico de salida a través del controlador de ingreso NGINX. Descomentamos la anotación en las líneas 14-15 de bash.yaml :

Luego aplicamos la nueva configuración:

> kubectl apply -f bash.yamldeployment.apps/bash configured

y verificar que se haya creado un nuevo pod bash :

> kubectl get podsNAME                    READY  STATUS        RESTARTS   AGE
bash-678c8b4579-7sfml   2/2    Running       0          6s
bash-6ccb678958-zsgm7   2/2    Terminating   0          3m28s

Ahora, cuando ejecutamos el mismo comando kubectl exec que antes, para enviar una solicitud desde el pod bash al servicio de destino, obtenemos el código de estado404 en lugar de503 . Esto indica que el pod bash ha enviado con éxito la solicitud al controlador de ingreso NGINX, pero este último no sabe dónde reenviarla porque no hay ninguna ruta definida.

Creamos la ruta requerida con la siguiente definición de recurso de Ingress en legacy-route.yaml . La anotación de ruta interna en la línea 7 significa que el servicio de destino no está expuesto a Internet, sino solo a las cargas de trabajo dentro de NGINX Service Mesh.

Activamos el nuevo recurso y confirmamos que NGINX Ingress Controller agregó la ruta definida en el recurso:

> kubectl apply -f legacy-route.yamlingress.networking.k8s.io/target-internal-route created
> kubectl describe ingress target-internal-route -n legacy
...
Events:
  Type    Reason          Age   From                      Message
  ----    ------          ----  ----                      -------
  Normal  AddedOrUpdated  6s    nginx-ingress-controller  Configuration for ...
        ...legacy/target-internal-route was added or updated

Ahora, cuando ejecutamos el comando kubectl exec , llegamos al servicio de destino:

{"req": {"method": "GET"                "url": "/",
                "host": "target-svc.legacy",
                "remoteAddr": "10.28.2.76:56086"}}

Una ventaja de enrutar el tráfico de salida a través del controlador de ingreso NGINX es que puede controlar exactamente a qué servicios externos se puede acceder desde dentro del clúster: solo aquellos para los que define una ruta.

Una última cosa que mostramos en la demostración es cómo monitorear el tráfico de salida. Ejecutamos el comando kubectl exec para enviar varias solicitudes y luego ejecutamos este comando:

> nginxmesh-ctl top deploy/nginx-ingress -n nginx-ingressDeployment      Direction  Resource  Success Rate  P99  P90  P50  NumRequests
nginx-ingress  
                To         target    100.00%       1ms  1ms  1ms  9
                From       bash      100.00%       0ms  0ms  0ms  9

Diga “no” a la latencia: pruebe NGINX Service Mesh con NGINX Ingress Controller

Muchas mallas de servicios ofrecen opciones de puerta de enlace de entrada y salida, pero creemos que apreciará un beneficio adicional de la integración con NGINX: menor latencia. La mayoría de las mallas requieren que se inyecte un sidecar en el controlador de Ingress, lo que requiere que el tráfico haga un salto adicional en su camino hacia sus aplicaciones. Los segundos importan, y ese salto adicional que ralentiza sus experiencias digitales puede provocar que los clientes busquen en otra parte. NGINX Service Mesh no agrega latencia innecesaria porque no inyecta un sidecar en NGINX Ingress Controller. En cambio, al integrarse directamente con Spire, la CA de la malla, NGINX Ingress Controller se convierte en parte de NGINX Service Mesh. El controlador de ingreso NGINX simplemente obtiene certificados y claves del agente Spire y los usa para participar en el intercambio de certificados mTLS con pods en malla.

Hay dos versiones de NGINX Ingress Controller para Kubernetes: NGINX de código abierto y NGINX Plus. Para implementar NGINX Ingress Controller con NGINX Service Mesh como se describe en este blog, debe usar la versión NGINX Plus, que está disponible para una prueba gratuita de 30 días .

¡NGINX Service Mesh es completamente gratuito y está disponible para descarga inmediata y se puede implementar en menos de 10 minutos! Para comenzar, consulte la documentación y cuéntenos cómo va a través de GitHub .


"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.