Todos los productos
Search
Centro de documentos

Alibaba Cloud Service Mesh:Enrutamiento por subconjuntos dinámicos

Última actualización: Sep 05, 2026

Con el enrutamiento por subconjuntos estáticos, cada DestinationRule debe listar explícitamente cada subconjunto. Cuando se publica una nueva versión o se retira una antigua, es necesario actualizar la regla manualmente. El enrutamiento por subconjuntos dinámicos elimina esta sobrecarga: Service Mesh (ASM) supervisa las etiquetas de las cargas de trabajo y agrupa los endpoints en subconjuntos automáticamente, lo que mantiene las reglas de enrutamiento actualizadas sin cambios manuales.

El siguiente ejemplo integral despliega una aplicación con múltiples versiones, enruta las solicitudes a versiones y entornos específicos mediante encabezados HTTP y configura un comportamiento de respaldo cuando no existe el subconjunto destino.

Funcionamiento de los subconjuntos dinámicos

En el enrutamiento estándar de Istio, una DestinationRule enumera cada subconjunto con un conjunto fijo de etiquetas. Cuando cambian las versiones, se debe actualizar la regla para que coincida.

Los subconjuntos dinámicos adoptan un enfoque diferente. En lugar de listar cada subconjunto, usted especifica una o más claves de agrupación (por ejemplo, version y stage). ASM inspecciona las etiquetas de cada endpoint detrás de un servicio y agrupa automáticamente los endpoints que comparten la misma combinación de clave-valor en el mismo subconjunto.

Luego, una VirtualService asigna los encabezados de las solicitudes entrantes a esas claves de agrupación. Por ejemplo, una solicitud que incluye x-version: v2 y x-stage: prod se enruta al subconjunto donde version=v2 y stage=prod.

Requisitos previos

Antes de empezar, asegúrese de contar con lo siguiente:

Paso 1: Desplegar la aplicación de ejemplo

Este ejemplo utiliza hashicorp/http-echo para simular un despliegue con múltiples entornos y versiones:

  • Entorno dev: versiones v1, v2, v3

  • Entorno prod: versiones v2, v3

Cada pod responde con su entorno, versión y dirección IP. Un Service helloworld en el puerto 8000 actúa como frontend para todos los pods, y un Deployment sleep proporciona un cliente para realizar pruebas.

Deployment topology

Despliegue todos los recursos con kubectl. Para obtener más información, consulte Deploy an application in an ACK cluster that is added to an ASM instance.

dev environment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-dev-v1
  labels:
    app: helloworld
    version: v1
    stage: dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
      version: v1
      stage: dev
  template:
    metadata:
      labels:
        app: helloworld
        version: v1
        stage: dev
    spec:
      containers:
      - name: helloworld
        image: hashicorp/http-echo:0.2.3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5678
        env:
        - name: PODIP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: STAGE
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['stage']
        - name: VERSION
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['version']
        command: ["/http-echo"]
        args:
          - "-text"
          - "Welcome to helloworld stage: $(STAGE), version: $(VERSION), ip: $(PODIP)"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-dev-v2
  labels:
    app: helloworld
    version: v2
    stage: dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
      version: v2
      stage: dev
  template:
    metadata:
      labels:
        app: helloworld
        version: v2
        stage: dev
    spec:
      containers:
      - name: helloworld
        image: hashicorp/http-echo:0.2.3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5678
        env:
        - name: PODIP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: STAGE
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['stage']
        - name: VERSION
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['version']
        command: ["/http-echo"]
        args:
          - "-text"
          - "Welcome to helloworld stage: $(STAGE), version: $(VERSION), ip: $(PODIP)"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-dev-v3
  labels:
    app: helloworld
    version: v3
    stage: dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
      version: v3
      stage: dev
  template:
    metadata:
      labels:
        app: helloworld
        version: v3
        stage: dev
    spec:
      containers:
      - name: helloworld
        image: hashicorp/http-echo:0.2.3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5678
        env:
        - name: PODIP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: STAGE
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['stage']
        - name: VERSION
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['version']
        command: ["/http-echo"]
        args:
          - "-text"
          - "Welcome to helloworld stage: $(STAGE), version: $(VERSION), ip: $(PODIP)"

prod environment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-prod-v2
  labels:
    app: helloworld
    version: v2
    stage: prod
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
      version: v2
      stage: prod
  template:
    metadata:
      labels:
        app: helloworld
        version: v2
        stage: prod
    spec:
      containers:
      - name: helloworld
        image: hashicorp/http-echo:0.2.3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5678
        env:
        - name: PODIP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: STAGE
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['stage']
        - name: VERSION
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['version']
        command: ["/http-echo"]
        args:
          - "-text"
          - "Welcome to helloworld stage: $(STAGE), version: $(VERSION), ip: $(PODIP)"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-prod-v3
  labels:
    app: helloworld
    version: v3
    stage: prod
spec:
  replicas: 2
  selector:
    matchLabels:
      app: helloworld
      version: v3
      stage: prod
  template:
    metadata:
      labels:
        app: helloworld
        version: v3
        stage: prod
    spec:
      containers:
      - name: helloworld
        image: hashicorp/http-echo:0.2.3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5678
        env:
        - name: PODIP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: STAGE
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['stage']
        - name: VERSION
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['version']
        command: ["/http-echo"]
        args:
          - "-text"
          - "Welcome to helloworld stage: $(STAGE), version: $(VERSION), ip: $(PODIP)"

helloworld Service

apiVersion: v1
kind: Service
metadata:
  name: helloworld
  labels:
    app: helloworld
    service: helloworld
spec:
  ports:
  - port: 8000
    name: http
    targetPort: 5678
  selector:
    app: helloworld

sleep client

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sleep
  template:
    metadata:
      labels:
        app: sleep
    spec:
      terminationGracePeriodSeconds: 0
      serviceAccountName: sleep
      containers:
      - name: sleep
        image: curlimages/curl
        command: ["/bin/sleep", "infinity"]
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /etc/sleep/tls
          name: secret-volume
      volumes:
      - name: secret-volume
        secret:
          secretName: sleep-secret
          optional: true

Paso 2: Enrutar solicitudes a una versión y entorno específicos

Tras el despliegue, Kubernetes distribuye las solicitudes entre todos los pods de helloworld sin importar la versión ni el entorno. Para dirigirse a una combinación específica, cree una DestinationRule que defina las claves de agrupación y una VirtualService que asigne los encabezados de las solicitudes a dichas claves.

Crear la DestinationRule

Aplique la siguiente DestinationRule para agrupar los endpoints por stage y version. Para obtener más información, consulte Manage destination rules.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
  namespace: default
spec:
  host: helloworld.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      dynamicSubset:
        subsetSelectors:
          - keys:
              - stage
              - version

ASM lee las etiquetas stage y version de cada endpoint y genera los siguientes subconjuntos:

Subconjunto

Pod

Dirección IP

stage=dev, version=v1

helloworld-dev-v1-67b6876778-nf7pz

192.168.0.5

stage=dev, version=v2

helloworld-dev-v2-68f65bbc99-v957l

192.168.0.1

stage=dev, version=v3

helloworld-dev-v3-7f6978bc56-hqzgg

192.168.0.252

stage=prod, version=v2

helloworld-prod-v2-b5745b949-p8rc4

192.168.0.103

stage=prod, version=v3

helloworld-prod-v3-6768bf56f8-6bd6h

192.168.0.104, 192.168.0.6

Crear la VirtualService

Aplique la siguiente VirtualService para asignar los encabezados HTTP a las claves de subconjuntos dinámicos. Para obtener más información, consulte Manage virtual services.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: helloworld
  namespace: default
spec:
  hosts:
    - helloworld.default.svc.cluster.local
  http:
    - headerToDynamicSubsetKey:
        - header: x-version        # Map the x-version header to the "version" grouping key
          key: version
          defaultValue: v3          # Fall back to v3 if the header is absent
        - header: x-stage           # Map the x-stage header to the "stage" grouping key
          key: stage
          defaultValue: prod        # Fall back to prod if the header is absent
      name: default
      route:
        - destination:
            host: helloworld.default.svc.cluster.local
            port:
              number: 8000

Esta VirtualService establece dos asignaciones:

  • Encabezado x-version a la clave de agrupación version. Valor predeterminado: v3 cuando el encabezado está ausente.

  • Encabezado x-stage a la clave de agrupación stage. Valor predeterminado: prod cuando el encabezado está ausente.

Comprobar el enrutamiento

Envíe una solicitud dirigida al entorno dev, versión v1:

kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: dev' -H 'x-version: v1' helloworld:8000

Salida esperada:

Welcome to helloworld stage: dev, version: v1, ip: 192.168.0.5

La solicitud llega al pod donde stage=dev y version=v1, lo que confirma que el enrutamiento por subconjuntos dinámicos funciona correctamente.

Paso 3: Configurar directivas de respaldo

La versión v1 no existe en el entorno prod. Una solicitud dirigida a stage=prod, version=v1 no coincide con ningún subconjunto:

kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000
# Output: no healthy upstream

Para gestionar los subconjuntos sin coincidencias, establezca una fallbackPolicy en la DestinationRule. ASM admite tres directivas:

Directiva

Comportamiento

Recomendada para

NO_FALLBACK

Devuelve un error no healthy upstream. Este es el valor predeterminado.

Enrutamiento estricto donde las solicitudes mal enrutadas deben fallar rápidamente

ANY_ENDPOINT

Enruta a cualquier endpoint disponible en todos los subconjuntos

Desarrollo o pruebas donde la disponibilidad es más importante que la precisión

DEFAULT_SUBSET (recomendada para producción)

Enruta a un subconjunto predeterminado preconfigurado

Cargas de trabajo de producción, donde las solicitudes sin coincidencia deben dirigirse a una versión estable conocida

NO_FALLBACK

NO_FALLBACK es el comportamiento predeterminado. Las solicitudes que no coinciden con ningún subconjunto devuelven un error. Establézcala explícitamente para dejar clara la intención de fallo rápido.

Aplique la siguiente DestinationRule. Para obtener más información, consulte Manage destination rules.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
  namespace: default
spec:
  host: helloworld.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      dynamicSubset:
        subsetSelectors:
          - fallbackPolicy: NO_FALLBACK
            keys:
              - stage
              - version

Compruebe el resultado:

kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000

Salida esperada:

no healthy upstream

ANY_ENDPOINT

Cuando ningún subconjunto coincide, las solicitudes se enrutan a cualquier endpoint disponible sin importar las etiquetas.

Aplique la siguiente DestinationRule. Para obtener más información, consulte Manage destination rules.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
  namespace: default
spec:
  host: helloworld.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      dynamicSubset:
        subsetSelectors:
          - fallbackPolicy: ANY_ENDPOINT
            keys:
              - stage
              - version

Compruébelo mediante el envío de dos solicitudes. Cada una puede llegar a un pod diferente:

# First request
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' helloworld:8000

Ejemplo de salida:

Welcome to helloworld stage: prod, version: v2, ip: 192.168.0.103
# Second request -- targets a non-existent subset
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000

Ejemplo de salida:

Welcome to helloworld stage: dev, version: v2, ip: 192.168.0.1

Dado que no existe el subconjunto prod/v1, la solicitud recurre a un endpoint aleatorio.

DEFAULT_SUBSET

Cuando ningún subconjunto coincide, las solicitudes se enrutan al subconjunto definido en defaultSubset. Esta es la directiva recomendada para cargas de trabajo de producción, ya que las solicitudes sin coincidencia se dirigen a una versión estable conocida en lugar de fallar o dispersarse aleatoriamente.

Aplique la siguiente DestinationRule. En este ejemplo, defaultSubset apunta a stage=prod, version=v3. Para obtener más información, consulte Manage destination rules.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
  namespace: default
spec:
  host: helloworld.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      dynamicSubset:
        defaultSubset:
          stage: prod
          version: v3
        subsetSelectors:
          - fallbackPolicy: DEFAULT_SUBSET
            keys:
              - stage
              - version

Compruébelo mediante el envío de dos solicitudes al subconjunto inexistente prod/v1:

kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000

Salida esperada:

Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.6
kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-stage: prod' -H 'x-version: v1' helloworld:8000

Salida esperada:

Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.104

Ambas solicitudes llegan al subconjunto predeterminado prod/v3. Las dos direcciones IP diferentes (192.168.0.6 y 192.168.0.104) reflejan el balanceo de carga entre las dos réplicas prod-v3.

Paso 4: Enrutar a un pod específico por dirección IP

Para fijar las solicitudes a un pod individual, utilice el atributo integrado %ip% como clave de agrupación. Cada pod se convierte en su propio subconjunto de un solo miembro.

Crear la DestinationRule

Aplique la siguiente DestinationRule para agrupar los pods por dirección IP. Para obtener más información, consulte Manage destination rules.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
  namespace: default
spec:
  host: helloworld.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      dynamicSubset:
        defaultSubset:
          stage: prod
          version: v3
        subsetSelectors:
          - keys:
              - '%ip%'

Crear la VirtualService

Asigne el encabezado x-ip a la clave %ip% para que el valor del encabezado especifique la IP del pod destino. Para obtener más información, consulte Manage virtual services.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: helloworld
  namespace: default
spec:
  hosts:
    - helloworld.default.svc.cluster.local
  http:
    - headerToDynamicSubsetKey:
        - header: x-ip
          key: '%ip%'
      name: default
      route:
        - destination:
            host: helloworld.default.svc.cluster.local
            port:
              number: 8000

Comprobar el enrutamiento

Envíe varias solicitudes dirigidas a la IP del pod 192.168.0.6:

kubectl exec -it deploy/sleep -c sleep -- curl -H 'x-ip: 192.168.0.6' helloworld:8000

Salida esperada (consistente en llamadas repetidas):

Welcome to helloworld stage: prod, version: v3, ip: 192.168.0.6

Cada solicitud llega al mismo pod, lo que confirma la fijación basada en IP.

Referencia de campos CRD

VirtualService

HTTPRoute

ASM extiende el recurso HTTPRoute con el campo headerToDynamicSubsetKey.

Campo

Tipo

Descripción

headerToDynamicSubsetKey

HeaderToMetadataSubsetKey[]

Asigna encabezados de solicitud a claves de agrupación de subconjuntos dinámicos. Cada elemento define una asignación de encabezado a clave.

HeaderToMetadataSubsetKey

Campo

Tipo

Descripción

header

string

Nombre del encabezado de la solicitud.

key

string

Nombre de la clave de agrupación del subconjunto dinámico. Un valor encerrado entre signos de porcentaje (por ejemplo, %ip%) hace referencia a un atributo integrado de la carga de trabajo.

defaultValue

string

Valor utilizado cuando la solicitud no incluye el encabezado especificado. Si se omite y el encabezado está ausente, la clave queda sin establecer y se excluye de la coincidencia de subconjuntos.

DestinationRule

ASM extiende la estructura trafficPolicy con el campo dynamicSubset.

TrafficPolicy

Campo

Tipo

Descripción

dynamicSubset

DynamicSubsetLB

Configura las reglas de agrupación de subconjuntos dinámicos.

DynamicSubsetLB

Campo

Tipo

Descripción

defaultSubset

map[string]string

Subconjunto predeterminado que se utiliza cuando fallbackPolicy es DEFAULT_SUBSET y ningún subconjunto coincide con la solicitud.

subsetSelectors

SubsetSelector[]

Lista de reglas de agrupación. Cada elemento define una dimensión de agrupación independiente.

fallbackPolicy

DynamicSubsetLB_FallbackPolicy

Directiva de respaldo global cuando ningún subconjunto coincide. El valor predeterminado es NO_FALLBACK.

SubsetSelector

Campo

Tipo

Descripción

keys

string[]

Dimensiones de agrupación asignadas a etiquetas de carga de trabajo. Por ejemplo, version agrupa los endpoints por la etiqueta version. También se admiten atributos integrados de carga de trabajo como %ip%.

fallbackPolicy

DynamicSubsetLB_FallbackPolicy

Directiva de respaldo para esta regla de agrupación específica. Anula la directiva establecida en DynamicSubsetLB.

DynamicSubsetLB_FallbackPolicy

Valor

Descripción

NO_FALLBACK

Devuelve un error cuando ningún subconjunto coincide. Este es el valor predeterminado.

ANY_ENDPOINT

Enruta a cualquier endpoint del servicio cuando ningún subconjunto coincide.

DEFAULT_SUBSET

Enruta al subconjunto definido en defaultSubset cuando ningún subconjunto coincide.

Atributos integrados de carga de trabajo

Atributo

Tipo

Descripción

%ip%

string

Dirección IP del pod donde se ejecuta la carga de trabajo.

Véase también