Gateways de Entrada

Además del soporte para los recursos Ingress de Kubernetes, Istio también le permite configurar el tráfico de entrada utilizando un Gateway de Istio o un recurso Gateway de Kubernetes. Un Gateway proporciona una personalización y flexibilidad más amplias que Ingress, y permite que las features de Istio, como el monitoreo y las reglas de ruta, se apliquen al tráfico que ingresa al cluster.

Esta tarea describe cómo configurar Istio para exponer un service fuera de la service mesh utilizando un Gateway.

Antes de empezar

  • Configure Istio siguiendo las instrucciones de la guía de instalación.

  • Inicie la muestra httpbin, que servirá como service de destino para el tráfico de entrada:

    Zip
    $ kubectl apply -f @samples/httpbin/httpbin.yaml@

    Tenga en cuenta que, para el propósito de este documento, que muestra cómo usar un gateway para controlar el tráfico de entrada en su “cluster de Kubernetes”, puede iniciar el service httpbin con o sin la inyección de sidecar habilitada (es decir, el service de destino puede estar dentro o fuera de la malla de Istio).

Configuración de la entrada usando un gateway

Un Gateway de entrada describe un balanceador de carga que opera en el borde de la malla y que recibe conexiones HTTP/TCP entrantes. Configura los puertos expuestos, protocolos, etc. pero, a diferencia de los Recursos Ingress de Kubernetes, no incluye ninguna configuración de enrutamiento de tráfico. El enrutamiento de tráfico para el tráfico de entrada se configura utilizando reglas de enrutamiento, exactamente de la misma manera que para las solicitudes de services internos.

Veamos cómo puede configurar un Gateway en el puerto 80 para el tráfico HTTP.

Cree un Gateway de Istio:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  # El selector coincide con las etiquetas del pod del ingress gateway.
  # Si instaló Istio usando Helm siguiendo la documentación estándar, esto sería "istio=ingress"
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"
EOF

Configure las rutas para el tráfico que ingresa a través del Gateway:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

Ahora ha creado una configuración de virtual service para el service httpbin que contiene dos reglas de ruta que permiten el tráfico para las rutas /status y /delay.

La lista de gateways especifica que solo se permiten las solicitudes a través de su httpbin-gateway. Todas las demás solicitudes externas serán rechazadas con una respuesta 404.

Determinación de la IP y los puertos de entrada

Cada Gateway está respaldado por un service de tipo LoadBalancer. La IP y los puertos del balanceador de carga externo para este service se utilizan para acceder al gateway. Los services de Kubernetes de tipo LoadBalancer son compatibles por defecto en clusters que se ejecutan en la mayoría de las plataformas en la nube, pero en algunos entornos (por ejemplo, de prueba) es posible que deba hacer lo siguiente:

  • minikube: inicie un balanceador de carga externo ejecutando el siguiente comando en una terminal diferente:

    $ minikube tunnel
  • kind: siga la guía para que los services de tipo LoadBalancer funcionen.

  • otras plataformas: es posible que pueda usar MetalLB para obtener una EXTERNAL-IP para los services LoadBalancer.

Para mayor comodidad, almacenaremos la IP y los puertos de entrada en variables de entorno que se utilizarán en instrucciones posteriores. Establezca las variables de entorno INGRESS_HOST e INGRESS_PORT de acuerdo con las siguientes instrucciones:

Establezca las siguientes variables de entorno con el nombre y el namespace donde se encuentra el ingress gateway de Istio en su cluster:

$ export INGRESS_NAME=istio-ingressgateway
$ export INGRESS_NS=istio-system

Ejecute el siguiente comando para determinar si su cluster de Kubernetes se encuentra en un entorno que admite balanceadores de carga externos:

$ kubectl get svc "$INGRESS_NAME" -n "$INGRESS_NS"
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)   AGE
istio-ingressgateway   LoadBalancer   172.21.109.129   130.211.10.121   ...       17h

Si el valor EXTERNAL-IP está establecido, su entorno tiene un balanceador de carga externo que puede usar para el ingress gateway. Si el valor EXTERNAL-IP es <none> (o perpetuamente <pending>), su entorno no proporciona un balanceador de carga externo para el ingress gateway.

Si su entorno no admite balanceadores de carga externos, puede intentar acceder al ingress gateway utilizando los puertos de nodo. De lo contrario, establezca la IP y los puertos de entrada utilizando los siguientes comandos:

$ export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
$ export SECURE_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
$ export TCP_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')

Acceso a services de entrada

  1. Acceda al service httpbin usando curl:

    $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/status/200"
    ...
    HTTP/1.1 200 OK
    ...
    server: istio-envoy
    ...

    Tenga en cuenta que utiliza el flag -H para establecer la cabecera HTTP Host en “httpbin.example.com”. Esto es necesario porque su Gateway de entrada está configurado para manejar “httpbin.example.com”, pero en su entorno de prueba no tiene ninguna vinculación DNS para ese host y simplemente está enviando su solicitud a la IP de entrada.

  2. Acceda a cualquier otra URL que no haya sido expuesta explícitamente. Debería ver un error HTTP 404:

    $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/headers"
    HTTP/1.1 404 Not Found
    ...

Acceso a services de entrada usando un navegador

Introducir la URL del service httpbin en un navegador no funcionará porque no puede pasar la cabecera Host a un navegador como lo hizo con curl. En una situación real, esto no es un problema porque configura el host solicitado correctamente y es resoluble por DNS. Por lo tanto, utiliza el nombre de dominio del host en la URL, por ejemplo, https://httpbin.example.com/status/200.

Puede solucionar este problema para pruebas y demostraciones simples de la siguiente manera:

Use un valor comodín * para el host en las configuraciones de Gateway y VirtualService. Por ejemplo, cambie su configuración de entrada a lo siguiente:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  # El selector coincide con las etiquetas del pod del ingress gateway.
  # Si instaló Istio usando Helm siguiendo la documentación estándar, esto sería "istio=ingress"
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /headers
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

Luego puede usar $INGRESS_HOST:$INGRESS_PORT en la URL del navegador. Por ejemplo, http://$INGRESS_HOST:$INGRESS_PORT/headers mostrará todas las cabeceras que envía su navegador.

Comprender lo que sucedió

Los recursos de configuración de Gateway permiten que el tráfico externo ingrese a la service mesh de Istio y ponen a disposición las features de gestión de tráfico y políticas de Istio para los services de borde.

En los pasos anteriores, creó un service dentro de la service mesh y expuso un endpoint HTTP del service al tráfico externo.

Uso de puertos de nodo del service de ingress gateway

Si su entorno no admite balanceadores de carga externos, aún puede experimentar con algunas de las features de Istio utilizando los puertos de nodo del service istio-ingressgateway.

Establezca los puertos de entrada:

$ export INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
$ export SECURE_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
$ export TCP_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')

La configuración de la IP de entrada depende del proveedor del cluster:

  1. GKE:

    $ export INGRESS_HOST=worker-node-address

    Debe crear reglas de firewall para permitir el tráfico TCP a los puertos del service ingressgateway. Ejecute los siguientes comandos para permitir el tráfico para el puerto HTTP, el puerto seguro (HTTPS) o ambos:

    $ gcloud compute firewall-rules create allow-gateway-http --allow "tcp:$INGRESS_PORT"
    $ gcloud compute firewall-rules create allow-gateway-https --allow "tcp:$SECURE_INGRESS_PORT"
  2. IBM Cloud Kubernetes Service:

    $ ibmcloud ks workers --cluster cluster-name-or-id
    $ export INGRESS_HOST=public-IP-of-one-of-the-worker-nodes
  3. Docker For Desktop:

    $ export INGRESS_HOST=127.0.0.1
  4. Otros entornos:

    $ export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n "${INGRESS_NS}" -o jsonpath='{.items[0].status.hostIP}')

Solución de problemas

  1. Inspeccione los valores de las variables de entorno INGRESS_HOST e INGRESS_PORT. Asegúrese de que tienen valores válidos, de acuerdo con la salida de los siguientes comandos:

    $ kubectl get svc -n istio-system
    $ echo "INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT"
  2. Verifique que no tiene otros ingress gateways de Istio definidos en el mismo puerto:

    $ kubectl get gateway --all-namespaces
  3. Verifique que no tiene recursos Ingress de Kubernetes definidos en la misma IP y puerto:

    $ kubectl get ingress --all-namespaces
  4. Si tiene un balanceador de carga externo y no le funciona, intente acceder al gateway utilizando su puerto de nodo.

Limpieza

Elimine la configuración de Gateway y VirtualService, y apague el service httpbin:

Zip
$ kubectl delete gateway httpbin-gateway
$ kubectl delete virtualservice httpbin
$ kubectl delete --ignore-not-found=true -f @samples/httpbin/httpbin.yaml@
¿Fue útil esta información?
¿Tienes alguna sugerencia para mejorar?

¡Gracias por tus comentarios!