Compartir a través de


Implementación de puertas de enlace de salida para el complemento de malla de servicio Istio para Azure Kubernetes Service (versión preliminar)

En este artículo se muestra cómo implementar puertas de enlace de salida para el complemento de malla de servicio Istio para el clúster de Azure Kubernetes Service (AKS).

Información general

La puerta de enlace de salida de Istio puede servir como un punto centralizado para supervisar y restringir el tráfico saliente de las aplicaciones en la malla. Con el complemento Istio, puede implementar varias puertas de enlace de salida en diferentes espacios de nombres, lo que le permite configurar una topología de puerta de enlace de salida de su elección: puertas de enlace de salida por clúster, por espacio de nombres, por carga de trabajo, etc. Aunque AKS administra el aprovisionamiento y el ciclo de vida de las puertas de enlace de salida del complemento Istio, debe crear recursos personalizados de Istio para enrutar el tráfico desde las aplicaciones de la malla a través de la puerta de enlace de salida y aplicar directivas y recopilación de telemetría.

La puerta de enlace de salida del complemento Istio también se basa en la característica y requiere la Puerta de enlace de salida estática, que asigna un prefijo de dirección IP de origen fijo a los pods de salida de Istio. Puede usar este intervalo IP de salida predicable para las reglas de firewall y otros mecanismos de filtrado de tráfico saliente. Mediante el uso de la puerta de enlace de salida de Istio por encima de la Puerta de Enlace de Egreso Estática, puede aplicar políticas de Istio L7, directivas basadas en identidad y restricciones basadas en IP para un control en profundidad del tráfico de salida como defensa. Además, dirigir el tráfico saliente a través de la puerta de enlace de salida de Istio permite que varias cargas de trabajo enruten el tráfico a través de los grupos de nodos de puerta de enlace de salida estática sin modificar esos pods o implementaciones de aplicaciones directamente.

Limitaciones y requisitos

  • Puede habilitar un máximo de 500 puertas de enlace de salida de complemento de Istio por clúster.
  • Los nombres de las pasarelas de salida del complemento Istio deben ser únicos por namespace.
  • Los nombres de puerta de enlace de salida de Istio deben estar entre caracteres 1-53, solo deben constar de caracteres alfanuméricos en minúsculas, "-" y ".", y deben iniciarse y terminar con un carácter alfanumérico. Los nombres también deben ser un nombre válido del sistema de nombres de dominio (DNS). La expresión regular usada para la validación de nombres es ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$.
  • Actualmente, la API de Gateway no es compatible con el egress gateway del complemento Istio.
  • Dado que la puerta de enlace de salida estática no se admite actualmente en clústeres de subredes de pod de Azure CNI, tampoco se admite la puerta de enlace de salida del complemento Istio en clústeres de subred de pod.

Prerrequisitos

Habilitación del complemento Istio

En esta guía, se da por supuesto que ha seguido la documentación para habilitar el complemento de Istio en un clúster de AKS.

Instalación de la extensión de la CLI de Azure aks-preview

Instale la extensión aks-preview si usa la CLI de Azure. Debe usar aks-preview la versión 14.0.0b2 o superior.

  1. Instale la extensión aks-preview mediante el comando az extension add.

    az extension add --name aks-preview
    
  2. Actualiza a la última versión de la extensión mediante el comando az extension update.

    az extension update --name aks-preview
    

Habilitación y configuración de la puerta de enlace de salida estática

Siga las instrucciones de la documentación de la puerta de enlace de salida estática para habilitar la puerta de enlace de salida estática en el clúster, cree un grupo de nodos del modo gateway, y cree un recurso StaticGatewayConfiguration.

Activar una puerta de enlace de salida de Istio

Nota:

Los pods de la puerta de enlace de salida del complemento Istio no se programan en el grupo de nodos gateway. El gateway grupo de nodos solo se utiliza para enrutar el tráfico de salida y no sirve para cargas de trabajo generales. Si necesita que los pods de la puerta de enlace de salida se programen en nodos específicos, puede usar nodos del sistema de AKS o la etiqueta de nodo azureservicemesh/istio.replica.preferred. Los pods tienen afinidades de nodo con una preferencia ponderada de 100 para los nodos del sistema de AKS (etiquetados kubernetes.azure.com/mode: system) y una preferencia ponderada de 50 para los nodos etiquetados azureservicemesh/istio.replica.preferred: true.

Use az aks mesh enable-egress-gateway para habilitar una puerta de enlace de salida de Istio en el clúster de AKS. Debe especificar un nombre para la puerta de enlace de salida de Istio y el nombre del StaticGatewayConfiguration que haya creado en el paso de los requisitos previos. También puede especificar un espacio de nombres en el que implementar la puerta de enlace de salida de Istio, que debe ser el mismo espacio de nombres en el que se creó el StaticGatewayConfiguration. Si no especifica un espacio de nombres, la puerta de enlace de salida se aprovisiona en el espacio de nombres aks-istio-egress.

Como procedimiento recomendado, debe esperar a que se asigne a StaticGatewayConfiguration un egressIpPrefix antes de habilitar la puerta de enlace de salida de Istio mediante esa configuración de puerta de enlace.

az aks mesh enable-egress-gateway --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --istio-egressgateway-name $ISTIO_EGRESS_NAME --istio-egressgateway-namespace $ISTIO_EGRESS_NAMESPACE --gateway-configuration-name $ISTIO_SGC_NAME

Compruebe que el servicio se crea para la puerta de enlace de salida.

kubectl get svc $ISTIO_EGRESS_NAME -n $ISTIO_EGRESS_NAMESPACE

Debería ver un servicio ClusterIP para la puerta de enlace de salida:

NAME              TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                    AGE
asm-egress-test   ClusterIP   10.0.128.17   <none>        15021/TCP,80/TCP,443/TCP   6d4h

También puede comprobar que se crea una implementación para la puerta de enlace de salida de Istio y que los pods de la puerta de enlace de salida tienen la anotación kubernetes.azure.com/static-gateway-configuration establecida en gatewayConfigurationName.

ASM_REVISION=$(az aks show -g $RESOURCE_GROUP -n $CLUSTER_NAME | jq '.serviceMeshProfile.istio.revisions[0]' | sed 's/"//g')

kubectl get deployment $ISTIO_EGRESS_NAME-$ASM_REVISION -n $ISTIO_EGRESS_NAMESPACE -o jsonpath={.spec.template.metadata.annotations."kubernetes\.azure\.com\/static-gateway-configuration"}

Puede volver a ejecutar el az aks mesh enable-egress-gateway comando para crear otra puerta de enlace de salida de Istio.

Nota:

Al realizar una actualización de revisión secundaria del complemento Istio, se crea otra implementación para cada puerta de enlace de salida para la nueva revisión del plano de control.

Enrutar el tráfico a través de la puerta de enlace de salida de Istio

EstablezcaoutboundTrafficPolicy.mode.

De forma predeterminada, Istio outboundTrafficPolicy.mode se establece en ALLOW_ANY, lo que significa que Envoy permite el paso de solicitudes para servicios desconocidos. Como procedimiento recomendado de seguridad, debe establecer Istio outboundTrafficPolicy.mode en REGISTRY_ONLY para que el proxy de Istio bloquee las solicitudes a los servicios que no se agregaron al Registro de servicios de Istio. Puede agregar hosts fuera del clúster al registro de servicio de Istio con un ServiceEntry.

Puede configurar el outboundTrafficPolicy.mode a nivel de malla mediante el complemento Istio MeshConfig compartido o usar el Recurso Personalizado Sidecar para tener como destino espacios de nombres o cargas de trabajo específicos.

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-shared-configmap-asm-1-24
  namespace: aks-istio-system
data:
  mesh: |-
    outboundTrafficPolicy:
      mode: REGISTRY_ONLY

Implementación de una aplicación de ejemplo

En este ejemplo, se implementa la aplicación curl en el mismo espacio de nombres que la puerta de enlace de salida del complemento Istio. Recuerde etiquetar con ISTIO_EGRESS_NAMESPACE la istio.io/rev etiqueta para que el pod de aplicación implementado se inserte con un sidecar:

kubectl label namespace $ISTIO_EGRESS_NAMESPACE istio.io/rev=$ASM_REVISION

A continuación, implemente la aplicación de ejemplo:

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.24/samples/curl/curl.yaml -n $ISTIO_EGRESS_NAMESPACE

Debería ver el pod curl en ejecución con un contenedor sidecar insertado:

NAME                                       READY   STATUS    RESTARTS   AGE
curl-5b549b49b8-bcgts                      2/2     Running   0          13s

Intente enviar una solicitud de curl directamente a edition.cnn.com.

SOURCE_POD=$(kubectl get pod -n $ISTIO_EGRESS_NAMESPACE -l app=curl -o jsonpath={.items..metadata.name})

kubectl exec -n $ISTIO_EGRESS_NAMESPACE "$SOURCE_POD" -c curl -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics

Si establece outboundTrafficPolicy.mode en REGISTRY_ONLY, se producirá un error en la solicitud curl porque no creó un ServiceEntry para edition.cnn.com. Si outboundTrafficPolicy.mode es ALLOW_ANY, la solicitud debería tener éxito.

Para enrutar realmente las solicitudes a edition.cnn.com desde el pod curl a la puerta de enlace de salida del complemento Istio, debe crear y ServiceEntry configurar otros recursos personalizados de Istio. Siga las instrucciones de una de las secciones siguientes para configurar una puerta de enlace de salida HTTP, una puerta de enlace de salida HTTPS o una puerta de enlace de salida que origine una conexión de seguridad de la capa de transporte (TLS).

Antes de iniciar cualquiera de los escenarios siguientes, establezca estas variables de entorno:

ISTIO_EGRESS_DEPLOYMENT=$ISTIO_EGRESS_NAME-$ASM_REVISION
EGRESS_GTW_SELECTOR=$(kubectl get deployment $ISTIO_EGRESS_DEPLOYMENT -n $ISTIO_EGRESS_NAMESPACE -o jsonpath={.metadata.labels.istio})

También puede habilitar el registro de acceso de Envoy mediante MeshConfig o la API de Telemetría. Una vez que tenga habilitado el registro de acceso, puede comprobar que el tráfico fluye a través de la puerta de enlace de salida inspeccionando los registros de contenedor istio-proxy:

kubectl logs -l istio=$EGRESS_GTW_SELECTOR -n $ISTIO_EGRESS_NAMESPACE

Configuración de una puerta de enlace de salida HTTP Istio

  1. Cree un ServiceEntry para edition.cnn.com:
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: cnn
spec:
  hosts:
  - edition.cnn.com
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
EOF
  1. Cree Gateway, VirtualService y DestinationRule para enrutar el tráfico HTTP de la aplicación curl a edition.cnn.com a través de la puerta de enlace de salida. Asegúrese de establecer el selector de puerta de enlace y el nombre de dominio completo del servicio (FQDN) según corresponda en función del selector de etiquetas istio de la implementación de la puerta de enlace de salida.
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: istio-egressgateway
spec:
  selector:
    istio: $EGRESS_GTW_SELECTOR
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - edition.cnn.com
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: egressgateway-for-cnn
spec:
  host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
  subsets:
  - name: cnn
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: direct-cnn-through-egress-gateway
spec:
  hosts:
  - edition.cnn.com
  gateways:
  - istio-egressgateway
  - mesh
  http:
  - match:
    - gateways:
      - mesh
      port: 80
    route:
    - destination:
        host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
        subset: cnn
        port:
          number: 80
      weight: 100
  - match:
    - gateways:
      - istio-egressgateway
      port: 80
    route:
    - destination:
        host: edition.cnn.com
        port:
          number: 80
      weight: 100
EOF
  1. Intente enviar una solicitud HTTP desde el curl pod a edition.cnn.com:
kubectl exec -n $ISTIO_EGRESS_NAMESPACE "$SOURCE_POD" -c curl -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics

Debería ver una respuesta HTTP/2 200.

  1. Limpieza de recursos
kubectl delete serviceentry cnn -n $ISTIO_EGRESS_NAMESPACE
kubectl delete gateway istio-egressgateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete virtualservice direct-cnn-through-egress-gateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule egressgateway-for-cnn -n $ISTIO_EGRESS_NAMESPACE

Configuración de una puerta de enlace de salida de HTTPS Istio

  1. Cree un HTTPS ServiceEntry para edition.cnn.com:
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: cnn
spec:
  hosts:
  - edition.cnn.com
  ports:
  - number: 443
    name: tls
    protocol: TLS
  resolution: DNS
EOF
  1. Cree Gateway, VirtualService y DestinationRule para enrutar el tráfico HTTP de la aplicación curl a edition.cnn.com a través de la puerta de enlace de salida. Asegúrese de establecer el selector de puerta de enlace y el FQDN del servicio según corresponda en función del selector de etiquetas istio en la implementación de la puerta de enlace de salida.
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: istio-egressgateway
spec:
  selector:
    istio: $EGRESS_GTW_SELECTOR
  servers:
  - port:
      number: 443
      name: tls
      protocol: TLS
    hosts:
    - edition.cnn.com
    tls:
      mode: PASSTHROUGH
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: egressgateway-for-cnn
spec:
  host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
  subsets:
  - name: cnn
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: direct-cnn-through-egress-gateway
spec:
  hosts:
  - edition.cnn.com
  gateways:
  - mesh
  - istio-egressgateway
  tls:
  - match:
    - gateways:
      - mesh
      port: 443
      sniHosts:
      - edition.cnn.com
    route:
    - destination:
        host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
        subset: cnn
        port:
          number: 443
  - match:
    - gateways:
      - istio-egressgateway
      port: 443
      sniHosts:
      - edition.cnn.com
    route:
    - destination:
        host: edition.cnn.com
        port:
          number: 443
      weight: 100
EOF
  1. Pruebe a enviar una solicitud HTTPS desde curl a edition.cnn.com:
kubectl exec "$SOURCE_POD" -n $ISTIO_EGRESS_NAMESPACE -c curl -- curl -sSL -o /dev/null -D - https://edition.cnn.com/politics

Debería ver una respuesta HTTP/2 200.

  1. Limpieza de recursos
kubectl delete serviceentry cnn -n $ISTIO_EGRESS_NAMESPACE
kubectl delete gateway istio-egressgateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete virtualservice direct-cnn-through-egress-gateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule egressgateway-for-cnn -n $ISTIO_EGRESS_NAMESPACE

Configura una puerta de enlace de egreso de Istio para realizar la originación de TLS

  1. Cree un ServiceEntry para edition.cnn.com:
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: cnn
spec:
  hosts:
  - edition.cnn.com
  ports:
  - number: 80
    name: http
    protocol: HTTP
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
EOF
  1. Cree Gateway, VirtualService y DestinationRule para enrutar el tráfico HTTP desde la aplicación curl hacia edition.cnn.com a través de la puerta de enlace de salida y para realizar el establecimiento de TLS en la puerta de enlace de salida. Asegúrese de establecer el selector de puerta de enlace y el FQDN del servicio según corresponda en función del selector de etiquetas istio en la implementación de la puerta de enlace de salida.
kubectl apply -n $ISTIO_EGRESS_NAMESPACE -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: istio-egressgateway
spec:
  selector:
    istio: $EGRESS_GTW_SELECTOR
  servers:
  - port:
      number: 80
      name: https-port-for-tls-origination
      protocol: HTTPS
    hosts:
    - edition.cnn.com
    tls:
      mode: ISTIO_MUTUAL
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: egressgateway-for-cnn
spec:
  host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
  subsets:
  - name: cnn
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
      portLevelSettings:
      - port:
          number: 80
        tls:
          mode: ISTIO_MUTUAL
          sni: edition.cnn.com
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: direct-cnn-through-egress-gateway
spec:
  hosts:
  - edition.cnn.com
  gateways:
  - istio-egressgateway
  - mesh
  http:
  - match:
    - gateways:
      - mesh
      port: 80
    route:
    - destination:
        host: $ISTIO_EGRESS_NAME.$ISTIO_EGRESS_NAMESPACE.svc.cluster.local
        subset: cnn
        port:
          number: 80
      weight: 100
  - match:
    - gateways:
      - istio-egressgateway
      port: 80
    route:
    - destination:
        host: edition.cnn.com
        port:
          number: 443
      weight: 100
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: originate-tls-for-edition-cnn-com
spec:
  host: edition.cnn.com
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
    portLevelSettings:
    - port:
        number: 443
      tls:
        mode: SIMPLE # initiates HTTPS for connections to edition.cnn.com
EOF
  1. Intente enviar un formulario de solicitud curl a edition.cnn.com con la puerta de enlace de salida que realiza la originación TLS;
kubectl exec "${SOURCE_POD}" -n $ISTIO_EGRESS_NAMESPACE -c curl -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics

Debería ver una respuesta de estado 200.

  1. Limpieza de recursos
kubectl delete serviceentry cnn -n $ISTIO_EGRESS_NAMESPACE
kubectl delete gateway istio-egressgateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete virtualservice direct-cnn-through-egress-gateway -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule originate-tls-for-edition-cnn-com -n $ISTIO_EGRESS_NAMESPACE
kubectl delete destinationrule egressgateway-for-cnn -n $ISTIO_EGRESS_NAMESPACE

Deshabilitación de la puerta de enlace de salida de Istio

Ejecute el az aks mesh disable-egress-gateway comando para deshabilitar la puerta de enlace de salida del complemento Istio que creó:

az aks mesh disable-egress-gateway --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --istio-egressgateway-name $ISTIO_EGRESS_NAME --istio-egressgateway-namespace $ISTIO_EGRESS_NAMESPACE

Una vez que deshabilite la puerta de enlace de salida de Istio, debería poder eliminar el StaticGatewayConfiguration espacio de nombres y el gateway grupo de nodos que la puerta de enlace de salida de Istio estaba utilizando si ninguna otra puerta de enlace de salida de Istio los está utilizando.

Pasos siguientes

Nota:

Si hay algún problema con la implementación de la puerta de enlace de salida de Istio o la configuración del enrutamiento del tráfico de salida, consulte el artículo sobre la solución de problemas de puertas de enlace de salida de complemento de Istio.