Ce produit n'est pas pris en charge par le site Datadog que vous avez sélectionné. ().

La ressource personnalisée DatadogPodAutoscaler (DPA) définit le comportement de mise à l’échelle automatique pour une seule charge de travail Kubernetes. L’interface utilisateur d’autoscaling avec Export Recommendation est un bon point de départ : configurez une charge de travail, puis copiez le manifeste généré. La modification directe du manifeste vous donne accès à chaque champ de la définition de ressource personnalisée (CRD) et fait du DPA une partie normale de votre workflow GitOps, où le manifeste est la source de vérité révisée et versionnée.

Cette page couvre les options de configuration disponibles dans le manifeste. Les exemples sur cette page utilisent la version d’API datadoghq.com/v1alpha2.

Pour la configuration et les prérequis, consultez Kubernetes Autoscaling. Cette page couvre l’activation de la mise à l’échelle automatique de charge de travail et du contrôleur d’admission sur le Datadog Cluster Agent, les versions d’agent requises, ainsi que l’activation du redimensionnement vertical sur place.

Anatomie d’un manifeste

Le squelette annoté suivant montre la structure d’un DatadogPodAutoscaler. Chaque champ est facultatif, à l’exception de 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)

Charges de travail cibles prises en charge

targetRef.kindapiVersionStatut
Deploymentapps/v1Pris en charge
Rollout (Argo Rollouts)argoproj.io/v1alpha1Pris en charge
StatefulSetapps/v1Pris en charge

Pour un Argo Rollout, pointez targetRef vers le Rollout lui-même plutôt que vers tout déploiement qu’il gère :

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

Choisissez un mode de mise à l’échelle

La combinaison de objectives et applyPolicy.update.strategy détermine si un DPA s’adapte horizontalement, verticalement, ou les deux :

objectives définirapplyPolicy.update.strategyMode résultant
ouiDisabled (ou non défini)Horizontal uniquement
nonAutoVertical uniquement
ouiAutoMultidimensionnel (les deux)

Contraintes de conteneur

La plupart des options verticales sont exprimées via spec.constraints.containers[] :

ChampTypePar défautSignification
namechaîne, requis-Nom du conteneur, ou "*" pour correspondre à chaque conteneur qui n’a pas sa propre entrée (voir Exclure un conteneur)
enabledbooltruefalse désactive la mise à l’échelle automatique des ressources pour ce conteneur
controlledResourcesliste de cpu, memory[cpu, memory]quelles ressources reçoivent des recommandations verticales. Une liste vide équivaut à enabled: false
controlledValuesenumRequestsAndLimitsSi les recommandations écrivent à la fois les requêtes et les limites, ou les requêtes uniquement
minAllowedcarte de ressources-Limite inférieure pour les requêtes du conteneur
maxAllowedcarte de ressources-Limite supérieure pour les requêtes du conteneur

Si constraints.containers est entièrement omis, la mise à l’échelle des ressources est activée pour tous les conteneurs, sans limites.

Dimensionner correctement le CPU et la mémoire

Lorsqu’un DPA combine la mise à l’échelle horizontale (objectives) avec la mise à l’échelle verticale (update.strategy: Auto), le comportement par défaut est de produire des recommandations verticales pour la mémoire uniquement. Les requêtes et limites CPU restent inchangées, et la condition VerticalAbleToRecommend peut apparaître comme Unknown.

Si un DPA ajuste la taille de la mémoire tout en laissant le CPU inchangé, c’est la raison. Cela n’est pas lié à la préservation de la classe de qualité de service (QoS).

Utilisez controlledResources pour déclarer quelles ressources reçoivent des recommandations verticales :

controlledResourcesRecommandations verticales produites
non définimémoire uniquement (par défaut)
[memory]mémoire uniquement, identique à non défini
[cpu, memory]mémoire et CPU
[cpu]CPU uniquement

Exemple complet :

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

Cette fonctionnalité nécessite Datadog Cluster Agent 7.78.0+. Sur les versions antérieures, le champ controlledResources est accepté par le CRD mais n’a aucun effet.

Supprimez les limites de CPU avec le mode burstable

Les recommandations de limite de CPU sont dérivées des percentiles d’utilisation soutenue sur une fenêtre de plusieurs jours. Un court pic de montée en charge (par exemple, lors du démarrage de la JVM) a peu d’effet sur ces percentiles, de sorte que la limite de CPU recommandée peut être trop basse et entraîner la limitation de l’application au mauvais moment. La mémoire n’est pas affectée de la même manière car l’utilisation maximale de la mémoire fournit un plafond fiable.

Le mode burstable supprime entièrement les limites de CPU tout en appliquant les recommandations de requête 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 n’est pas défini, la valeur par défaut à l’échelle du cluster de l’Agent de cluster s’applique. Définissez-le explicitement sur false pour exclure une seule charge de travail du comportement par défaut.

Effet sur le pod :

AvantAprès
Demande de CPU1400m (recommandation)
Limite de CPU2supprimée
Demande de mémoire500Mi450Mi (recommandation)
Limite de mémoire2Gi2Gi, préservée

Avant de l’activer :

  • Les pods qui étaient en QoS Guaranteed deviennent en QoS Burstable. Cela modifie leur priorité d’éviction en cas de pression sur le nœud.
  • Sans limite de CPU, un conteneur peut consommer le CPU disponible du nœud. Les parts de CPU du noyau s’appliquent toujours.
  • Le mode burstable a priorité sur controlledValues pour les limites de CPU. Si les deux sont définis, le mode burstable l’emporte.

Ajustez l’augmentation de mémoire OOMKill

Après un OOMKill, la limite de mémoire est augmentée de 20 % par rapport à la limite en vigueur à ce moment-là. L’augmentation est appliquée immédiatement et répétée après chaque OOMKill ultérieur jusqu’à ce que la charge de travail se stabilise.

Pour modifier le ratio :

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

Mettez la valeur entre guillemets : il s’agit d’une quantité Kubernetes, pas d’un nombre à virgule flottante.

Quand l’augmenter. Augmentez le ratio pour les charges de travail dont l’utilisation de la mémoire peut atteindre des pics nettement supérieurs aux pics précédents. Une augmentation plus importante permet d’atteindre plus rapidement la limite de mémoire appropriée et évite plusieurs augmentations successives avant que la charge de travail ne se stabilise. Lorsque vous l’augmentez, définissez également un seuil minimal de mémoire minAllowed (voir Définir des limites par conteneur) afin que la limite ne puisse pas retomber en dessous d’une valeur sûre entre les cycles de recommandation.

Dimensionnez uniquement les demandes

Si vous avez délibérément ajusté les limites (pour la marge de manœuvre en rafale, une exigence de plateforme ou une garantie QoS) et que vous souhaitez que Datadog dimensionne uniquement les demandes, utilisez controlledValues: RequestsOnly.

spec:
  constraints:
    containers:
      - name: my-app
        controlledResources: [cpu, memory]
        controlledValues: RequestsOnly     # limits are not right-sized
controlledValuesRequêtesLimites
RequestsAndLimits (par défaut)recommandérecommandé
RequestsOnlyrecommandénon ajusté, sauf lorsqu’une limite doit être déplacée pour maintenir la validité de la spécification du pod (voir ci-dessous)

Interactions à connaître :

  • Sur un conteneur où request == limit, réduire la requête rompt la classe de QoS Garantie. Si vous avez besoin de la classe Garantie, conservez RequestsAndLimits ; le recommender gère explicitement les conteneurs request == limit.
  • Le mode burstable remplace cela pour les limites CPU (voir Supprimer les limites CPU avec le mode burstable).
  • La gestion des OOMKill ajuste toujours la limite de mémoire. RequestsOnly ne supprime pas l’augmentation de la mémoire. Après un OOMKill, la limite de mémoire est augmentée, et la requête est potentiellement augmentée avec elle (Kubernetes rejette tout pod dont la requête dépasse sa limite). Lisez RequestsOnly comme « les limites ne sont pas ajustées », et non « les limites ne sont jamais modifiées ». Voir Ajuster l’augmentation de la mémoire en cas d’OOMKill.

Choisir une combinaison :

ObjectifConfiguration
Ajuster toutcontrolledResources: [cpu, memory] + controlledValues: RequestsAndLimits
Ajuster les requêtes, laisser les limites telles quellescontrolledValues: RequestsOnly
Ajuster la mémoire uniquement, ne pas toucher au CPUcontrolledResources: [memory]
Ajuster les requêtes CPU, aucune limite CPU du toutoptions.burstable: true
Ne pas toucher du tout à un conteneurenabled: false

Définir les limites par conteneur

minAllowed et maxAllowed contraignent les demandes de ressources que le recommender peut produire. Ils sont recommandés pour les charges de travail sensibles à la latence. Ils sont également recommandés lorsque vous modifiez le taux d’augmentation OOM (voir Ajuster l’augmentation de la mémoire OOMKill) pour éviter que les demandes de mémoire ne tombent en dessous d’un minimum sûr entre les cycles de recommandation.

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

Exclure un conteneur

Vous pouvez exclure un conteneur des recommandations verticales, du signal horizontal, ou les deux.

Exclure un conteneur des recommandations verticales

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

Vous pouvez spécifier explicitement la configuration équivalente :

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

Un modèle courant consiste à mettre à l’échelle automatique tout, sauf un sidecar connu :

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

Comment "*" et les entrées nommées se combinent : l’entrée "*" s’applique à chaque conteneur qui **n’**a pas d’entrée nommée. Un conteneur avec sa propre entrée nommée utilise uniquement les paramètres déclarés sous ce nom. Les deux ne sont pas fusionnés, donc le caractère générique ne lui apporte rien.

Dans l’exemple ci-dessus, istio-proxy est régi uniquement par enabled: false et n’hérite pas de controlledResources du caractère générique. Tous les autres conteneurs du pod utilisent l’entrée générique.

Remarque : Si vous ajoutez une entrée nommée uniquement pour définir une limite, répétez tous les paramètres génériques que vous souhaitez conserver. Dans l’exemple ci-dessous, my-app revient à la valeur par défaut RequestsAndLimits plutôt qu’à RequestsOnly définie sur le caractère générique :

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

Exclure un conteneur du signal horizontal

enabled: false régit uniquement le comportement vertical. L’objectif horizontal est choisi séparément, et c’est là que les sidecars faussent le plus souvent les décisions de mise à l’échelle :

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

La configuration au niveau du pod suivante peut produire des résultats trompeurs lorsque des sidecars sont présents :

  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

Recommandation : Si le pod possède un sidecar, utilisez ContainerResource ciblé sur le conteneur principal. Réservez PodResource aux pods à conteneur unique.

Configurer les sidecars

Sidecars ordinaires (spec.containers)

Rien de spécial n’est requis. Ils peuvent être limités, exclus ou ciblés comme n’importe quel autre conteneur ; voir Exclure un conteneur.

Sidecars natifs (spec.initContainers avec restartPolicy: Always)

Kubernetes 1.29+ prend en charge les sidecars à exécution longue déclarés dans initContainers avec restartPolicy: Always, connus sous le nom de modèle sidecar natif. Un sidecar natif s’exécute pendant toute la durée de vie du 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}

Les sidecars natifs sont entièrement pris en charge. Ils sont traités comme des conteneurs ordinaires : des recommandations sont générées et appliquées pour eux, et ils apparaissent dans la liste des conteneurs de la charge de travail où ils peuvent être configurés ou exclus. Référencez-les dans constraints.containers[] par nom, exactement comme n’importe quel autre conteneur. Il n’y a pas de bloc initContainers distinct dans la spécification DPA, et une entrée "*" les couvre également.

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

Points à noter :

  • restartPolicy: Always est ce qui les distingue. Les conteneurs d’initialisation ordinaires (ceux qui s’exécutent jusqu’à leur terme avant le démarrage de l’application) ne sont pas des sidecars natifs et ne sont pas gérés par un DPA.
  • Les chiffres relatifs aux coûts et aux économies peuvent sous-estimer les sidecars natifs. Leurs demandes de ressources sont rapportées sous une agrégation distincte, de sorte que les chiffres de coût affichés pour une charge de travail avec des sidecars natifs peuvent sembler incohérents avec son utilisation observée. Il s’agit d’une limitation connue qui affecte uniquement l’affichage des coûts ; les recommandations ne sont pas affectées.
  • Les sidecars injectés (tels que ceux d’Istio) sont ajoutés par un webhook d’admission mutant au niveau du pod et n’apparaissent jamais dans le manifeste du déploiement. Ils sont toujours récupérés, car la liste des conteneurs est réconciliée à partir des pods en cours d’exécution plutôt que du seul manifeste de charge de travail.
  • Ne pas exclure les conteneurs mis à l’échelle automatiquement de la collecte par l’Agent. Un DatadogPodAutoscaler s’appuie sur les métriques que l’Agent collecte pour les conteneurs qu’il gère. Si un conteneur dans une charge de travail mise à l’échelle automatiquement est filtré par la configuration de découverte de conteneurs de l’Agent, aucune métrique n’existe pour lui et il ne peut pas être redimensionné correctement. Confirmez qu’aucun conteneur dans une charge de travail mise à l’échelle automatiquement n’est exclu de la collecte. Pour savoir comment fonctionnent les règles d’inclusion et d’exclusion, consultez Gestion de la découverte de conteneurs.

Options de manifeste supplémentaires

Mode aperçu (simulation)

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

Utile comme interrupteur d’arrêt temporaire. Si une configuration horizontale est invalide, le redimensionnement vertical continue de s’exécuter ; définir mode: Preview gèle les deux pendant que vous la corrigez.

Désactiver une direction de mise à l’échelle

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

Pour une mise à l’échelle uniquement verticale, omettez objectives et définissez update.strategy: Auto, comme dans le tableau Choisir un mode de mise à l’échelle. Sans objectives, la mise à l’échelle horizontale n’a aucune cible sur laquelle agir, vous n’avez donc pas non plus besoin de définir scaleUp et scaleDown sur Disabled.

Calendrier de déploiement vertical

Le contrôleur applique un changement vertical par la voie la moins perturbatrice disponible et escalade si cette voie est bloquée. Deux champs contrôlent la durée d’attente à chaque étape :

spec:
  applyPolicy:
    update:
      strategy: Auto
      resizePendingPeriod: 600      # 1..3600 seconds
      rolloutFallbackDelay: 900     # 1..3600 seconds
ChampContrôle
resizePendingPeriodDurée d’attente avant d’évincer un pod lorsque le kubelet signale le redimensionnement comme étant en attente (accepté mais ne progressant pas, souvent parce que le nœud manque de marge de manœuvre)
rolloutFallbackDelayDurée d’attente avant de revenir à un déploiement complet lorsque les évictions sont bloquées, généralement par un PodDisruptionBudget

Les deux sont facultatifs et acceptent de 1 à 3600 secondes. Les laisser non définis utilise les valeurs par défaut intégrées du contrôleur.

  • Augmentez resizePendingPeriod lorsque l’éviction est coûteuse (préchauffage long, caches volumineux, vidage lent). Vous échangez une période plus longue à l’ancienne taille contre moins de redémarrages.
  • Augmentez rolloutFallbackDelay sur les charges de travail avec un PodDisruptionBudget serré, afin qu’une contrainte budgétaire temporaire ne se transforme pas immédiatement en un déploiement complet.
  • Réduisez l’un ou l’autre lorsque les redémarrages sont peu coûteux et que vous souhaitez que les recommandations prennent effet plus rapidement.

Ceux-ci contrôlent comment un changement est effectué, et non si il se produit. Pour arrêter complètement les changements, utilisez update.strategy: Disabled ou applyPolicy.mode: Preview. Ces champs s’appliquent à la mise à l’échelle verticale sur place ; consultez la vue d’ensemble pour l’activation au niveau du cluster et les exigences Kubernetes.

Réglage de secours local

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

Les recommandations de secours sont calculées au sein du cluster à partir des métriques collectées par l’Agent, de sorte que la mise à l’échelle se poursuit si Datadog ne peut pas fournir de recommandation dans le délai imparti.

Cette fonctionnalité nécessite également une configuration côté cluster sur le Cluster Agent et sur les Agents de nœud. Consultez Kubernetes Autoscaling ou contactez le support Datadog.

Objectifs en valeur absolue

Au lieu d’un pourcentage d’utilisation, ciblez une valeur absolue :

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

Objectifs de requête personnalisée

Mettez à l’échelle sur n’importe quelle métrique Datadog plutôt que sur le CPU ou la mémoire :

  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 peut également être ApmMetrics, avec des champs tels que service, resourceName, operationName et stat.

Les requêtes personnalisées sont prises en charge pour la mise à l’échelle horizontale uniquement. La combinaison d’une requête personnalisée avec une mise à l’échelle verticale n’est pas prise en charge, car l’autoscaler ne peut pas déduire sur quelle dimension une requête arbitraire doit agir.

Taguez la télémétrie d’un DPA

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

Ceci ajoute les tags à la télémétrie d’autoscaling émise pour ce DPA. Pour la liste des métriques émises par le Cluster Agent, consultez l’intégration Datadog Cluster Agent.

Pour aller plus loin