Featured image of post Kubernetes 1.34 - Pod-level resources - simplifier la gestion des ressources quand on a plein de containers

Kubernetes 1.34 - Pod-level resources - simplifier la gestion des ressources quand on a plein de containers

Ecrit par ~ zwindler ~

Introduction

Aujourd’hui, je vais vous parler d’une nouvelle fonctionnalité de Kubernetes 1.34 qui est passée en béta : les Pod-level resources.

Et pour illustrer cette nouvelle fonctionnalité, je vais prendre l’exemple d’un pod pour lequel je souhaite avoir la QoS Guaranteed.

Pendant un temps, j’étais persuadé (mais alors je sais pas pourquoi… parce que la doc est claire 🤔) que pour avoir la QoS Guaranteed, il fallait que tous les containers du pod aient limits=requests, mais les mêmes pour tous les containers (ce qui est faux). Et c’est super pénible parce que des fois on a une grosse app principale et un tout petit sidecar et ça n’a pas de sens de leur mettre les mêmes valeurs.

Si on relit la doc, ce qui compte pour la QoS Guaranteed (doc officielle), c’est que :

  • Chaque container doit avoir cpu.limit = cpu.request
  • Chaque container doit avoir memory.limit = memory.request

Mais les valeurs peuvent être différentes entre les containers !

Pour s’en convaincre, il suffit de tester ce manifest :

apiVersion: v1
kind: Pod
metadata:
  name: ctrlevel-demo1
  namespace: pod-resources-example
spec:
  containers:
  - name: ctrlevel-demo1-ctr-1
    image: nginx
    resources:
      limits:
        cpu: "0.8"
        memory: "100Mi"
      requests:
        cpu: "0.8"
        memory: "100Mi"
  - name: ctrlevel-demo1-ctr-2
    image: fedora
    resources:
      limits:
        cpu: "0.2"
        memory: "200Mi"
      requests:
        cpu: "0.2"
        memory: "200Mi"
    command:
    - sleep
    - inf

Et devinez quoi ? QoS Class: Guaranteed.

Le premier container a 0.8 CPU / 100Mi, le second a 0.2 CPU / 200Mi, et ça ne pose aucun problème tant que chaque container respecte individuellement limit=request pour cpu et ram.

Bon. Maintenant que j’ai admis mon erreur publiquement (shame shame shame), on va quand même parler de Pod-level resources, parce que cette fonctionnalité reste utile.

Alors, à quoi ça sert, les Pod-level resources ?

Dans certains cas, il arrive que les containers (init, sidecar, …) soient très peu consommateurs. Certains sont aussi injectés à la volée (service mesh, auto instrumentation) de manière généralisée. Spécifier explicitement des limits / requests pour ces “petits” containers annexes peut être pénible, chronophage, difficile à tuner s’il y en a beaucoup…

Exemple typique : on injecte un sidecar qui expose juste des métriques Prometheus. Il consomme 10m de CPU et 20Mi de RAM. Vous pourriez écrire :

containers:
- name: mon-app
  resources:
    limits:
      cpu: "1"
      memory: "100Mi"
    requests:
      cpu: "1"
      memory: "100Mi"
- name: metrics-exporter
  resources:
    limits:
      cpu: "10m"
      memory: "20Mi"
    requests:
      cpu: "10m"
      memory: "20Mi"

Mais franchement, c’est chi**t. Et si demain l’exporter a besoin d’un poil plus de mémoire dans certains cas mais pas tous, il faut modifier le manifest pour l’augmenter partout, ou alors gérer l’exception…

Avec Pod-level resources, vous pouvez faire :

#fichier podlevel-demo1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: podlevel-demo1
  namespace: pod-resources-example
spec:
  resources:
    limits:
      cpu: "1"
      memory: 100Mi
    requests:
      cpu: "1"
      memory: 100Mi
  initContainers:
  - name: sidecar-test
    image: busybox:latest
    command: ["sh", "-c", "while true; do sleep 3600; done"]
    restartPolicy: Always
  containers:
  - name: podlevel-demo1-ctr
    image: vish/stress
    args:
    - -cpus
    - "2"

Ici :

  • Les resources sont déclarées au niveau du spec du Pod
  • Les containers eux-mêmes n’ont PAS de déclaration de ressources
  • Le sidecar (déclaré en tant qu’initContainer avec restartPolicy: Always, cf. mon article précédent sur les sidecars) se partage les ressources du Pod avec le container.

Dans cet exemple, c’est un container et un sidecar, mais ça aurait très bien pu être n’importe quel autre mix de containers, d’init containers classiques et de sidecars.

Testons ça !

kubectl create namespace pod-resources-example
kubectl apply -f podlevel-demo1.yaml

Maintenant, vérifions que nous avons bien obtenu la QoS Guaranteed avec ce oneliner des enfers 😈 :

kubectl get pod podlevel-demo1 -n pod-resources-example -o jsonpath=$'Pod-level resources:\n  Requests: {.spec.resources.requests}\n  Limits: {.spec.resources.limits}\n\nContainer podlevel-demo1-ctr:\n  Requests: {.spec.containers[0].resources.requests}\n  Limits: {.spec.containers[0].resources.limits}\n\nSidecar sidecar-test:\n  Requests: {.spec.initContainers[0].resources.requests}\n  Limits: {.spec.initContainers[0].resources.limits}\n\nQoS Class: {.status.qosClass}\n'

Résultat :

Pod-level resources:
  Requests: {"cpu":"1","memory":"100Mi"}
  Limits: {"cpu":"1","memory":"100Mi"}

Container podlevel-demo1-ctr:
  Requests: 
  Limits: 

Sidecar sidecar-test:
  Requests: 
  Limits: 

QoS Class: Guaranteed

Les containers individuels n’ont PAS de ressources déclarées, mais le Pod dans son ensemble a des ressources. Et on obtient quand même la QoS Guaranteed !

Tout fonctionne comme prévu.

On peut aussi mixer pod level et container level

Au-delà de cet exemple, sachez qu’il est possible de mixer du container level (classique) avec du pod level.

Voici un exemple inspiré par la doc officielle :

#fichier podlevel-demo2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: podlevel-demo2
  namespace: pod-resources-example
spec:
  resources:
    limits:
      cpu: "1"
      memory: "200Mi"
    requests:
      cpu: "1"
      memory: "200Mi"
  containers:
  - name: podlevel-demo2-ctr-1
    image: nginx
    resources:
      limits:
        cpu: "0.5"
        memory: "100Mi"
      requests:
        cpu: "0.5"
        memory: "100Mi"
  - name: podlevel-demo2-ctr-2
    image: fedora
    command:
    - sleep
    - inf 

Ici, le container podlevel-demo2-ctr-1 spécifie ses ressources, mais on spécifie aussi des ressources pour tout le pod, et pas du tout dans podlevel-demo2-ctr-2.

Pour info, l’exemple de ce pod est aussi Guaranteed, malgré l’absence de limits/requests sur podlevel-demo2-ctr-2

kubectl get pod podlevel-demo2 -n pod-resources-example -o jsonpath=$'Pod-level resources:\n  Requests: {.spec.resources.requests}\n  Limits: {.spec.resources.limits}\n\nContainer podlevel-demo2-ctr-1:\n  Requests: {.spec.containers[0].resources.requests}\n  Limits: {.spec.containers[0].resources.limits}\n\nContainer podlevel-demo2-ctr-2:\n  Requests: {.spec.containers[1].resources.requests}\n  Limits: {.spec.containers[1].resources.limits}\n\nQoS Class: {.status.qosClass}\n'

Résultat :

Pod-level resources:
  Requests: {"cpu":"1","memory":"200Mi"}
  Limits: {"cpu":"1","memory":"200Mi"}

Container podlevel-demo2-ctr-1:
  Requests: {"cpu":"500m","memory":"100Mi"}
  Limits: {"cpu":"500m","memory":"100Mi"}

Container podlevel-demo2-ctr-2:
  Requests: 
  Limits: 

QoS Class: Guaranteed

Conclusion

Les Pod-level resources sont une fonctionnalité qui simplifie la vie dans certains cas d’usage, notamment quand on utilise des sidecars légers ou des containers injectés à la volée.

Est-ce révolutionnaire ? Non. Est-ce que ça va changer votre vie ? Probablement pas. Mais ça peut toujours servir.

On en apprend tous les jours. Même (surtout ?) quand on se plante. 😌

Références

Licensed under CC BY-SA 4.0

Vous aimez ce blog ou cet article ? Partagez-le avec vos amis !   Twitter Linkedin email Facebook

Vous pouvez également vous abonner à la mailing list des articles ici

L'intégralité du contenu appartenant à Denis Germain (alias zwindler) présent sur ce blog, incluant les textes, le code, les images, les schémas et les supports de talks de conf, sont distribués sous la licence CC BY-SA 4.0.

Les autres contenus (thème du blog, police de caractères, logos d'entreprises, articles invités...) restent soumis à leur propre licence ou à défaut, au droit d'auteur. Plus d'informations dans les Mentions Légales

Généré avec Hugo
Thème Stack conçu par Jimmy