El recurso personalizado DatadogPodAutoscaler (DPA) define el comportamiento de escalado automático para una sola carga de trabajo de Kubernetes. La Autoscaling UI con Export Recommendation es un buen lugar para comenzar: configure una carga de trabajo y luego copie el manifiesto generado. Editar el manifiesto directamente le brinda acceso a todos los campos en la definición de recurso personalizado (CRD) y convierte al DPA en una parte normal de su flujo de trabajo GitOps, donde el manifiesto es la fuente revisada y versionada de la verdad.

Esta página cubre las opciones de configuración disponibles en el manifiesto. Los ejemplos en esta página utilizan la versión de API datadoghq.com/v1alpha2.

Para la configuración y los requisitos previos, consulte Kubernetes Autoscaling. Esa página cubre la habilitación del escalado automático de cargas de trabajo y el controlador de admisión en el Datadog Cluster Agent, las versiones requeridas del Agent y la habilitación del escalado vertical in-place.

Anatomía de un manifiesto

El siguiente esqueleto anotado muestra la estructura de un DatadogPodAutoscaler. Todos los campos son opcionales excepto targetRef.

apiVersion: datadoghq.com/v1alpha2
kind: DatadogPodAutoscaler
metadata:
  name: my-app                      # required: conventionally the workload name
  namespace: my-namespace           # required: must match the target workload
  annotations:                      # optional
    ad.datadoghq.com/tags: '{"team": "my-team"}'   # optional: tags on this DPA's telemetry
spec:
  owner: Local                      # optional: Local = this manifest is the source of truth (use for GitOps)
                                    # Remote = created and managed from the Datadog UI

  targetRef:                        # required: the workload being autoscaled - one DPA per workload
    apiVersion: apps/v1
    kind: Deployment
    name: my-app

  applyPolicy:                      # optional
    mode: Apply                     # Apply | Preview (Preview = compute recommendations, change nothing)

    scaleUp:                        # optional: horizontal, upward
      strategy: Max                 # Max | Min | Disabled
      stabilizationWindowSeconds: 600
      rules:
        - type: Percent             # Percent | Pods
          value: 50
          periodSeconds: 120        # 1..3600

    scaleDown:                      # optional: horizontal, downward
      strategy: Max
      stabilizationWindowSeconds: 600
      rules:
        - type: Percent
          value: 10
          periodSeconds: 1800

    update:                         # optional: vertical
      strategy: Auto                # Auto | Disabled | TriggerRollout
      # resizePendingPeriod: 600    # see Vertical rollout timing
      # rolloutFallbackDelay: 900   # see Vertical rollout timing

  constraints:                      # optional
    minReplicas: 3
    maxReplicas: 100
    containers:                     # optional: per-container vertical configuration
      - name: "*"                   # "*" matches all containers
        enabled: true
        controlledResources: [cpu, memory]
        controlledValues: RequestsAndLimits   # RequestsAndLimits | RequestsOnly
        minAllowed:
          cpu: "500m"
          memory: 1Gi
        maxAllowed:
          cpu: "4"
          memory: 8Gi

  objectives:                       # optional: configures horizontal scaling (also used by multidimensional). Exactly one entry.
    - type: ContainerResource       # PodResource | ContainerResource | CustomQuery
      containerResource:
        container: my-app
        name: cpu                   # cpu | memory
        value:
          type: Utilization         # Utilization | AbsoluteValue
          utilization: 65

  fallback:                         # optional: in-cluster horizontal fallback if recommendations go stale
    horizontal:
      enabled: true
      direction: ScaleUp            # ScaleUp | ScaleDown | All (default ScaleUp)
      triggers:
        staleRecommendationThresholdSeconds: 600   # 100..3600, default 600

  options:                          # optional
    burstable: false                # true = remove CPU limits, keep CPU request recommendations
    outOfMemory:
      bumpUpRatio: "1.2"            # +20% memory limit after an OOMKill (default)

Cargas de trabajo de destino admitidas

targetRef.kindapiVersionEstado
Deploymentapps/v1Admitido
Rollout (Argo Rollouts)argoproj.io/v1alpha1Admitido
StatefulSetapps/v1Admitido

Para un Argo Rollout, apunte targetRef al Rollout en sí en lugar de a cualquier Deployment que gestione:

  targetRef:
    apiVersion: argoproj.io/v1alpha1
    kind: Rollout
    name: my-app

Elija un modo de escalado

La combinación de objectives y applyPolicy.update.strategy determina si un DPA escala horizontalmente, verticalmente o ambos:

objectives establecerapplyPolicy.update.strategyModo resultante
síDisabled (o sin establecer)Solo horizontal
noAutoSolo vertical
síAutoMultidimensional (ambos)

Restricciones del contenedor

La mayoría de las opciones verticales se expresan a través de spec.constraints.containers[]:

CampoTipoPredeterminadoSignificado
namecadena, obligatorio-Nombre del contenedor, o "*" para coincidir con cada contenedor que no tenga su propia entrada (consulte Excluir un contenedor)
enabledbooltruefalse deshabilita el escalado automático de recursos para este contenedor
controlledResourceslista de cpu, memory[cpu, memory]qué recursos reciben recomendaciones verticales. Una lista vacía es equivalente a enabled: false
controlledValuesenumRequestsAndLimitsSi las recomendaciones escriben tanto solicitudes como límites, o solo solicitudes
minAllowedmapa de recursos-Límite inferior para las solicitudes del contenedor
maxAllowedmapa de recursos-Límite superior para las solicitudes del contenedor

Si constraints.containers se omite por completo, el escalado de recursos se habilita para todos los contenedores, sin límites.

Ajustar el tamaño de CPU y memoria

Cuando un DPA combina escalado horizontal (objectives) con escalado vertical (update.strategy: Auto), el comportamiento predeterminado es producir recomendaciones verticales solo para memoria. Las solicitudes y límites de CPU se dejan intactos, y la condición VerticalAbleToRecommend puede mostrarse como Unknown.

Si un DPA ajusta el tamaño de la memoria mientras deja la CPU sin cambios, esta es la razón. No está relacionado con la preservación de la clase de Calidad de Servicio (QoS).

Use controlledResources para declarar qué recursos reciben recomendaciones verticales:

controlledResourcesRecomendaciones verticales producidas
sin configurarsolo memoria (predeterminado)
[memory]solo memoria, igual que sin configurar
[cpu, memory]memoria y CPU
[cpu]solo CPU

Ejemplo completo:

apiVersion: datadoghq.com/v1alpha2
kind: DatadogPodAutoscaler
metadata:
  name: my-app
  namespace: my-namespace
spec:
  owner: Local
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  applyPolicy:
    mode: Apply
    update:
      strategy: Auto              # required - without it, nothing vertical is applied
  constraints:
    minReplicas: 3
    maxReplicas: 60
    containers:
      - name: "*"
        controlledResources:
          - cpu                   # opts CPU into vertical rightsizing
          - memory
        controlledValues: RequestsAndLimits
  objectives:
    - type: ContainerResource
      containerResource:
        container: my-app
        name: cpu
        value:
          type: Utilization
          utilization: 65

Esta función requiere Datadog Cluster Agent 7.78.0+. En versiones anteriores, el campo controlledResources es aceptado por el CRD pero no tiene efecto.

Eliminar límites de CPU con modo Burstable

Las recomendaciones de límite de CPU se derivan de los percentiles de uso sostenido durante un periodo de varios días. Un pico breve de calentamiento (por ejemplo, durante el inicio de la JVM) tiene poco efecto en esos percentiles, por lo que el límite de CPU recomendado puede ser demasiado bajo y causar que la aplicación sea limitada en el momento equivocado. La memoria no se ve afectada de la misma manera porque el uso máximo de memoria proporciona un techo confiable.

El modo Burstable elimina los límites de CPU por completo mientras sigue aplicando recomendaciones de _ solicitud_ de CPU:

apiVersion: datadoghq.com/v1alpha2
kind: DatadogPodAutoscaler
metadata:
  name: my-java-app
  namespace: my-namespace
spec:
  owner: Local
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-java-app
  applyPolicy:
    mode: Apply
    update:
      strategy: Auto
  options:
    burstable: true

Si options.burstable se deja sin configurar, se aplica el valor predeterminado de clúster del Cluster Agent. Establézcalo explícitamente en false para excluir una sola carga de trabajo del comportamiento predeterminado.

Efecto en el pod:

AntesDespués
Solicitud de CPU1400m (recomendación)
Límite de CPU2eliminado
Solicitud de memoria500Mi450Mi (recomendación)
Límite de memoria2Gi2Gi, preservado

Antes de habilitarlo:

  • Los pods que tenían QoS Garantizada pasan a tener QoS Burstable. Esto cambia su prioridad de desalojo bajo presión del nodo.
  • Sin un límite de CPU, un contenedor puede consumir la CPU disponible del nodo. Las cuotas de CPU del kernel siguen aplicándose.
  • El modo Burstable tiene prioridad sobre controlledValues para los límites de CPU. Si ambos están configurados, gana el modo Burstable.

Ajuste el incremento de memoria de OOMKill

Después de un OOMKill, el límite de memoria aumenta un 20 % en relación con el límite vigente en ese momento. El aumento se aplica de inmediato y se repite después de cada OOMKill posterior hasta que la carga de trabajo se estabiliza.

Para cambiar la proporción:

spec:
  options:
    outOfMemory:
      bumpUpRatio: "1.5"      # 1.2 = +20% (default), 1.5 = +50%

Escriba el valor entre comillas: es una cantidad de Kubernetes, no un número de punto flotante.

Cuándo aumentarlo. Aumente la proporción para cargas de trabajo cuyo uso de memoria pueda alcanzar picos drásticamente superiores a los picos anteriores. Un aumento mayor alcanza el límite de memoria correcto más rápido y evita varios aumentos sucesivos antes de que la carga de trabajo se estabilice. Cuando lo aumente, establezca también un minAllowed límite mínimo de memoria (consulte Establecer límites por contenedor) para que el límite no pueda caer por debajo de un valor seguro entre ciclos de recomendación.

Ajustar solo las solicitudes al tamaño correcto

Si ha ajustado deliberadamente los límites (para el margen de maniobra de ráfagas, un requisito de la plataforma o una garantía de QoS) y desea que Datadog ajuste solo las solicitudes al tamaño correcto, use controlledValues: RequestsOnly.

spec:
  constraints:
    containers:
      - name: my-app
        controlledResources: [cpu, memory]
        controlledValues: RequestsOnly     # limits are not right-sized
controlledValuesSolicitudesLímites
RequestsAndLimits (predeterminado)recomendadorecomendado
RequestsOnlyrecomendadono ajustado al tamaño correcto, excepto donde un límite debe moverse para mantener válida la especificación del pod (consulte a continuación)

Interacciones que debe tener en cuenta:

  • En un contenedor donde request == limit, reducir la solicitud rompe la clase de QoS garantizada. Si necesita la clase garantizada, mantenga RequestsAndLimits; el recomendador maneja los contenedores request == limit explícitamente.
  • Modo Burstable anula esto para los límites de CPU (consulte Eliminar límites de CPU con Modo Burstable).
  • El manejo de OOMKill aún ajusta el límite de memoria. RequestsOnly no suprime el aumento de memoria. Después de un OOMKill, el límite de memoria se aumenta y la solicitud potencialmente también se incrementa (Kubernetes rechaza cualquier pod cuya solicitud exceda su límite). Lea RequestsOnly como “los límites no se ajustan al tamaño correcto”, no como “los límites nunca se modifican”. Consulte Ajustar el aumento de memoria de OOMKill.

Elegir una combinación:

ObjetivoConfiguración
Ajustar el tamaño de todocontrolledResources: [cpu, memory] + controlledValues: RequestsAndLimits
Ajustar el tamaño de las solicitudes, dejar los límites tal como están escritoscontrolledValues: RequestsOnly
Ajustar el tamaño solo de la memoria, dejar la CPU intactacontrolledResources: [memory]
Ajustar el tamaño de las solicitudes de CPU, sin límite de CPU en absolutooptions.burstable: true
Dejar un contenedor completamente intactoenabled: false

Establecer límites por contenedor

minAllowed y maxAllowed restringen las solicitudes de recursos que el recomendador puede producir. Se recomiendan para cargas de trabajo sensibles a la latencia. También se recomiendan cuando cambia la relación de aumento de OOM (consulte Ajustar el aumento de memoria de OOMKill) para evitar que las solicitudes de memoria caigan por debajo de un mínimo seguro entre ciclos de recomendación.

spec:
  constraints:
    minReplicas: 2
    maxReplicas: 100
    containers:
      - name: api
        enabled: true
        minAllowed:
          cpu: "1"
          memory: 1Gi
        maxAllowed:
          cpu: "4"
          memory: 5Gi
      - name: worker
        enabled: true          # no bounds - recommendations are unconstrained

Excluir un contenedor

Puede excluir un contenedor de las recomendaciones verticales, de la señal horizontal o de ambas.

Excluir un contenedor de las recomendaciones verticales

spec:
  constraints:
    containers:
      - name: my-app
        enabled: true
      - name: istio-proxy
        enabled: false          # resources for this container are never modified

También puede especificar la configuración equivalente de forma explícita:

      - name: istio-proxy
        controlledResources: []   # empty list is equivalent to enabled: false

Un patrón común es escalar automáticamente todo excepto un sidecar conocido:

spec:
  constraints:
    containers:
      - name: "*"
        enabled: true
        controlledResources: [cpu, memory]
      - name: istio-proxy
        enabled: false

Cómo se combinan "*" y las entradas con nombre: la entrada "*" se aplica a cada contenedor que no tiene una entrada con nombre. Un contenedor con su propia entrada con nombre toma solo la configuración declarada bajo ese nombre. Ambas no se combinan, por lo que el comodín no aporta nada a ella.

En el ejemplo anterior, istio-proxy se rige únicamente por enabled: false y no hereda controlledResources del comodín. Cualquier otro contenedor en el pod utiliza la entrada comodín.

Nota: Si agrega una entrada con nombre solo para establecer un límite, repita cualquier configuración de comodín que aún desee. En el ejemplo siguiente, my-app recurre al RequestsAndLimits predeterminado en lugar del RequestsOnly establecido en el comodín:

      - name: "*"
        controlledValues: RequestsOnly
      - name: my-app
        maxAllowed:
          memory: 8Gi          # controlledValues is NOT inherited - repeat it if you want it

Excluir un contenedor de la señal horizontal

enabled: false rige solo el comportamiento vertical. El objetivo horizontal se elige por separado, y aquí es donde los sidecars suelen distorsionar las decisiones de escalado:

  objectives:
    # Recommended: scale on the application container's CPU
    - type: ContainerResource
      containerResource:
        container: my-app
        name: cpu
        value:
          type: Utilization
          utilization: 65

La siguiente configuración a nivel de pod puede producir resultados engañosos cuando hay sidecars presentes:

  objectives:
    # Risky when sidecars are present: pod-level utilization is diluted by
    # sidecar requests, so a busy application container can appear idle.
    - type: PodResource
      podResource:
        name: cpu
        value:
          type: Utilization
          utilization: 65

Recomendación: Si el pod tiene algún sidecar, use ContainerResource con alcance al contenedor principal. Reserve PodResource para pods de un solo contenedor.

Configurar sidecars

Sidecars ordinarios (spec.containers)

No se requiere nada especial. Pueden limitarse, excluirse o seleccionarse como cualquier otro contenedor; consulte Excluir un contenedor.

Sidecars nativos (spec.initContainers con restartPolicy: Always)

Kubernetes 1.29+ admite sidecars de larga duración declarados en initContainers con restartPolicy: Always, conocidos como el patrón sidecar nativo. Un sidecar nativo se ejecuta durante toda la vida útil del pod.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      initContainers:
        - name: log-shipper
          image: log-shipper:1.2
          restartPolicy: Always      # this is what makes it a native sidecar
          resources:
            requests: {cpu: 100m, memory: 128Mi}
            limits:   {memory: 256Mi}
      containers:
        - name: my-app
          image: my-app:4.5
          resources:
            requests: {cpu: "1", memory: 2Gi}
            limits:   {cpu: "2", memory: 4Gi}

Los sidecars nativos son totalmente compatibles. Se tratan como contenedores ordinarios: se producen y aplican recomendaciones para ellos, y aparecen en la lista de contenedores de la carga de trabajo donde pueden configurarse o excluirse. Haga referencia a ellos en constraints.containers[] por nombre, exactamente igual que cualquier otro contenedor. No hay un bloque initContainers separado en la especificación de DPA, y una entrada "*" también los cubre.

spec:
  constraints:
    containers:
      - name: my-app
        controlledResources: [cpu, memory]
        controlledValues: RequestsAndLimits
      - name: log-shipper        # native sidecar, referenced by name
        enabled: false

Puntos a tener en cuenta:

  • restartPolicy: Always es lo que los distingue. Los contenedores de inicialización ordinarios (aquellos que se ejecutan hasta completarse antes de que inicie la aplicación) no son sidecars nativos y no son administrados por un DPA.
  • Las cifras de costos y ahorros pueden subestimar los sidecars nativos. Sus solicitudes de recursos se informan bajo una agregación separada, por lo que las cifras de costos mostradas para una carga de trabajo con sidecars nativos pueden parecer inconsistentes con su uso observado. Esta es una limitación conocida que afecta solo a la visualización de costos; las recomendaciones no se ven afectadas.
  • Los sidecars inyectados (como los de Istio) son agregados por un webhook de admisión mutante a nivel de pod y nunca aparecen en el manifiesto de Deployment. Aun así son detectados, porque la lista de contenedores se reconcilia a partir de los pods en ejecución en lugar de solo a partir del manifiesto de la carga de trabajo.
  • No excluya los contenedores con escalado automático de la recolección del Agent. Un DatadogPodAutoscaler depende de las métricas que el Agent recolecta para los contenedores que administra. Si un contenedor en una carga de trabajo con escalado automático se filtra a través de la configuración de descubrimiento de contenedores del Agent, no existen métricas para él y no se puede ajustar su tamaño correctamente. Confirme que ningún contenedor en una carga de trabajo con escalado automático esté excluido de la recolección. Para saber cómo funcionan las reglas de inclusión y exclusión, consulte Gestión del Descubrimiento de Contenedorest.

Opciones de manifiesto adicionales

Modo de vista previa (simulación)

spec:
  applyPolicy:
    mode: Preview     # recommendations are computed and visible in .status, but nothing is applied

Útil como interruptor de parada temporal. Si una configuración horizontal no es válida, el ajuste de tamaño vertical continúa ejecutándose; establecer mode: Preview congela ambas mientras usted la corrige.

Deshabilitar una dirección de escalado

spec:
  applyPolicy:
    scaleUp:
      strategy: Max
    scaleDown:
      strategy: Disabled     # never scale down
    update:
      strategy: Auto

Para el escalado solo vertical, omita objectives y establezca update.strategy: Auto, como en la tabla Elegir un modo de escalado. Sin objectives, el escalado horizontal no tiene un objetivo sobre el cual actuar, por lo que tampoco necesita establecer scaleUp y scaleDown en Disabled.

Tiempo de implementación vertical

El controlador aplica un cambio vertical mediante la ruta menos disruptiva disponible y escala si esa ruta se detiene. Dos campos controlan cuánto tiempo espera en cada paso:

spec:
  applyPolicy:
    update:
      strategy: Auto
      resizePendingPeriod: 600      # 1..3600 seconds
      rolloutFallbackDelay: 900     # 1..3600 seconds
CampoControles
resizePendingPeriodCuánto tiempo esperar antes de desalojar un pod cuando el kubelet informa que el cambio de tamaño está pendiente (aceptado pero sin progreso, a menudo porque el nodo carece de capacidad suficiente)
rolloutFallbackDelayCuánto tiempo esperar antes de recurrir a un despliegue completo cuando los desalojos están bloqueados, generalmente por un PodDisruptionBudget

Ambos son opcionales y aceptan de 1 a 3600 segundos. Dejarlos sin configurar utiliza los valores predeterminados integrados del controlador.

  • Aumente resizePendingPeriod donde el desalojo sea costoso (calentamiento prolongado, cachés grandes, drenaje lento). Usted cambia un período más largo en el tamaño anterior por menos reinicios.
  • Aumente rolloutFallbackDelay en cargas de trabajo con un PodDisruptionBudget ajustado, para que una restricción de presupuesto temporal no escale inmediatamente a un despliegue completo.
  • Reduzca cualquiera de los dos donde los reinicios sean económicos y desee que las recomendaciones surtan efecto más rápido.

Estos controlan cómo se entrega un cambio, no si ocurre uno. Para detener los cambios por completo, use update.strategy: Disabled o applyPolicy.mode: Preview. Estos campos se aplican al escalado vertical in-place; consulte la descripción general para conocer la habilitación a nivel de clúster y los requisitos de Kubernetes.

Ajuste de respaldo local

spec:
  fallback:
    horizontal:
      enabled: true
      direction: ScaleUp          # default; use All to allow fallback scale-in as well
      triggers:
        staleRecommendationThresholdSeconds: 600    # 100..3600

Las recomendaciones de respaldo se calculan dentro del clúster a partir de las métricas recopiladas por el Agent, por lo que el escalado continúa si Datadog no puede entregar una recomendación dentro del umbral.

Esta función también requiere configuración del lado del clúster tanto en el Cluster Agent como en los node Agents. Consulte Kubernetes Autoscaling o comuníquese con Soporte de Datadog.

Objetivos de valor absoluto

En lugar de un porcentaje de utilización, establezca como objetivo un valor absoluto:

  objectives:
    - type: ContainerResource
      containerResource:
        container: my-app
        name: cpu
        value:
          type: AbsoluteValue
          absoluteValue: "1.5"     # target cores per pod

Objetivos de consulta personalizados

Escala según cualquier métrica de Datadog en lugar de CPU o memoria:

  objectives:
    - type: CustomQuery
      customQuery:
        window: 5m
        request:
          queries:
            - name: a
              source: Metrics
              metrics:
                query: "avg:my.queue.depth{service:my-app}"
        value:
          type: AbsoluteValue
          absoluteValue: "100"

source también puede ser ApmMetrics, con campos como service, resourceName, operationName y stat.

Las consultas personalizadas son compatibles solo para el escalado horizontal. Combinar una consulta personalizada con el escalado vertical no es compatible, porque el escalador automático no puede inferir sobre qué dimensión debe actuar una consulta arbitraria.

Etiquete la telemetría de un DPA

metadata:
  annotations:
    ad.datadoghq.com/tags: '{"team": "my-team", "tier": "critical"}'

Esto agrega las etiquetas a la telemetría de escalado automático emitida para este DPA. Para obtener la lista de métricas que emite el Cluster Agent, consulte la integración del Cluster Agent de Datadog.

Lecturas adicionales