--- myst: html_meta: "description": "Constrain Plone backend, frontend, and Varnish pods to specific Kubernetes nodes using nodeSelector and tolerations." "property=og:description": "Constrain Plone backend, frontend, and Varnish pods to specific Kubernetes nodes using nodeSelector and tolerations." "property=og:title": "Schedule pods to specific nodes" "keywords": "Plone, cdk8s, Kubernetes, nodeSelector, tolerations, scheduling, taints" --- ```{image} ../_static/kup6s-icon-howto.svg :align: center :class: section-icon-large ``` # Schedule pods to specific nodes

Type: How-To (Task-oriented)

Difficulty: Intermediate

Time: 10 minutes

This guide shows you how to control where Plone backend, frontend, and Varnish pods run. Use `nodeSelector` to require specific node labels and tolerations to schedule onto tainted nodes. ## Prerequisites - A working Plone deployment using `cdk8s-plone`. - Cluster labels and taints already configured on the target nodes. ```shell kubectl get nodes --show-labels kubectl describe node | grep Taints ``` ## Constrain pods to labeled nodes Add `nodeSelector` to `backend`, `frontend`, or both. Every label in the selector must match for a node to be considered. ```typescript import { Plone, PloneVariant } from '@bluedynamics/cdk8s-plone'; new Plone(chart, 'plone', { variant: PloneVariant.VOLTO, backend: { image: 'plone/plone-backend:6.1.3', nodeSelector: { 'topology.kubernetes.io/region': 'fsn1', 'workload': 'plone', }, }, frontend: { image: 'plone/plone-frontend:16.0.0', nodeSelector: { 'workload': 'plone', }, }, }); ``` ## Schedule the cache onto the same nodes `PloneVinylCache` exposes the same `nodeSelector` option. ```typescript import { PloneVinylCache } from '@bluedynamics/cdk8s-plone'; new PloneVinylCache(chart, 'cache', { plone: ploneInstance, nodeSelector: { 'workload': 'plone', }, }); ``` `PloneHttpcache` schedules through the underlying mittwald Helm chart and does not expose a `nodeSelector` option directly. Use cluster-level affinity rules or taints when you need to constrain those pods. ## Tolerate tainted nodes When nodes carry a taint, pods must declare a matching toleration before the scheduler places them there. Both cache constructs accept a `tolerations` list. ```typescript new PloneHttpcache(chart, 'cache', { plone: ploneInstance, tolerations: [ { key: 'workload', operator: 'Equal', value: 'plone', effect: 'NoSchedule', }, ], }); ``` ```typescript new PloneVinylCache(chart, 'cache', { plone: ploneInstance, tolerations: [ { key: 'workload', operator: 'Equal', value: 'plone', effect: 'NoSchedule', }, ], }); ``` `operator: 'Exists'` matches any value for that key. Omit `effect` to tolerate every effect for the matching taint. ## Combine selector and toleration Selectors and tolerations work together: the selector narrows the candidate nodes, and the toleration unblocks the scheduler when those nodes are tainted. ```typescript new PloneVinylCache(chart, 'cache', { plone: ploneInstance, nodeSelector: { 'workload': 'plone', }, tolerations: [ { key: 'workload', operator: 'Equal', value: 'plone', effect: 'NoSchedule' }, ], }); ``` ## Verify the rollout ```shell cdk8s synth kubectl apply -f dist/ # Confirm pods landed on the expected nodes kubectl get pods -n -o wide ``` A pod stuck in `Pending` with `0/N nodes are available: ... node(s) had untolerated taint` means a taint is not tolerated. `0/N nodes are available: ... node(s) didn't match Pod's node affinity/selector` means the `nodeSelector` does not match any node. ## See also - {doc}`/reference/configuration-options` — `nodeSelector`, `HttpcacheToleration`, `VinylCacheToleration` reference. - [Kubernetes: Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) — Selectors, affinity, and taints.