{
  "id": "node-selection",
  "title": "Control node selection",
  "url": "https://redis.io/docs/latest/operate/kubernetes/8.0.18/recommendations/node-selection/",
  "summary": "This section provides information about how Redis Enterprise cluster pods can be scheduled to only be placed on specific nodes or node pools.",
  "content": "\nKubernetes clusters often include nodes with different CPU and memory profiles. You control where Redis Enterprise cluster (REC) pods run by setting fields in the REC custom resource (CRD).\n\nA Redis Enterprise cluster (REC) runs as a StatefulSet. The Kubernetes scheduler assigns nodes when you create or resize the cluster, or when a pod restarts.\n\nUse these options to control pod placement:\n\n## Use node selectors\n\nThe [`nodeSelector`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#spec) field matches the Kubernetes [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) syntax.\nLabel the nodes you want to target. For example, if nodes 'n1' and 'n2' are labeled with `memory=high`:\n\n```sh\nkubectl label nodes n1 memory=high\nkubectl label nodes n2 memory=high\n```\n\nThe Redis Enterprise cluster CRD can request to be scheduled on these nodes:\n\n```yaml\napiVersion: app.redislabs.com/v1\nkind: RedisEnterpriseCluster\nmetadata:\n  name: rec\nspec:\n  nodes: 3\n  nodeSelector:\n     memory: high\n```\n\nThe operator copies [`nodeSelector`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#spec) into the pod spec. The scheduler places pods only on nodes that match the selector.\n\n## Use node pools\n\nNode pools group similar nodes. Providers label nodes by pool.\n\nUse [`nodeSelector`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#spec) to target a pool by label. For example, on GKE:\n\n```yaml\napiVersion: app.redislabs.com/v1\nkind: RedisEnterpriseCluster\nmetadata:\n  name: rec\nspec:\n  nodes: 3\n  nodeSelector:\n     cloud.google.com/gke-nodepool: 'high-memory'\n```\n\n### Provider resources\n\nCloud providers label nodes by pool. See links below for specific documentation.\n\n- GKE:\n  - [Create and manage cluster and node pool labels](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-managing-labels)\n  - [Update node labels and taints for existing node pools](https://cloud.google.com/kubernetes-engine/docs/how-to/update-existing-nodepools)\n- AKS:\n  - [Use labels in an AKS cluster](https://learn.microsoft.com/en-us/azure/aks/use-labels)\n  - [Manage node pools in AKS](https://learn.microsoft.com/en-us/azure/aks/manage-node-pools)\n- EKS:\n  - [Create a managed node group with labels (AWS CLI)](https://docs.aws.amazon.com/cli/latest/reference/eks/create-nodegroup.html)\n  - [Update a managed node group to add labels (AWS CLI)](https://docs.aws.amazon.com/cli/latest/reference/eks/update-nodegroup-config.html)\n\n\n## Use node taints\n\nUse node taints and pod tolerations to control REC pod scheduling. Set tolerations with [`spec.podTolerations`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#specpodtolerations) (standard [Kubernetes tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/#concepts)).\n\nExample: on a single node pool, reserve nodes n1–n3 for REC by adding taints:\n\n```sh\nkubectl taint nodes n1 db=rec:NoSchedule\nkubectl taint nodes n2 db=rec:NoSchedule\nkubectl taint nodes n3 db=rec:NoSchedule\n```\n\nThis blocks pods unless they tolerate the `db=rec` taint.\n\nThen add a matching toleration to the REC:\n\n```yaml\napiVersion: app.redislabs.com/v1\nkind: RedisEnterpriseCluster\nmetadata:\n  name: rec\nspec:\n  nodes: 3\n  podTolerations:\n  - key: db\n    operator: Equal\n    value: rec\n    effect: NoSchedule\n```\n\nA set of taints can also handle more complex use cases.\nFor example, a `role=test` or `role=dev` taint can be used to designate a node as dedicated for testing or development workloads via pod tolerations.\n\n## Use pod anti-affinity\n\nBy default, REC node pods are not scheduled on the same node within the same cluster:\n\n```yaml\npodAntiAffinity:\n  requiredDuringSchedulingIgnoredDuringExecution:\n  - labelSelector:\n      matchLabels:\n        app: redis-enterprise\n        redis.io/cluster: rec\n        redis.io/role: node\n    topologyKey: kubernetes.io/hostname\n```\n\nEach pod has these labels. `redis.io/cluster` is your cluster name.\n\nModify this rule to widen or narrow placement. For example, remove the `redis.io/cluster` label to prevent pods from different clusters from sharing a node:\n\n```yaml\napiVersion: app.redislabs.com/v1\nkind: RedisEnterpriseCluster\nmetadata:\n  name: rec\nspec:\n  nodes: 3\n  podAntiAffinity:\n    requiredDuringSchedulingIgnoredDuringExecution:\n    - labelSelector:\n        matchLabels:\n          app: redis-enterprise\n          redis.io/role: node\n      topologyKey: kubernetes.io/hostname\n```\n\nTo avoid co-locating with other database workloads, label those pods `local/role: database` and add anti-affinity to keep one database per node:\n\n```yaml\napiVersion: app.redislabs.com/v1\nkind: RedisEnterpriseCluster\nmetadata:\n  name: rec\nspec:\n  nodes: 3\n  extraLabels:\n     local/role: database\n  podAntiAffinity:\n    requiredDuringSchedulingIgnoredDuringExecution:\n    - labelSelector:\n        matchLabels:\n          local/role: database\n          app: redis-enterprise\n          redis.io/cluster: rec\n          redis.io/role: node\n      topologyKey: kubernetes.io/hostname\n```\n\nKubernetes will not schedule two pods with label `local/role: database` on the same node.\n\n## Enable rack awareness\n\nEnable rack-zone awareness to improve availability during rack or zone failures.\n\nWhen creating your rack-zone ID, there are some constraints to consider; see [rack-zone awareness](https://redis.io/docs/latest/operate/rs/clusters/configure/rack-zone-awareness#rack-zone-id-rules) for more info. \n\nConfigure it with [`spec.rackAwarenessNodeLabel`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#spec) in the REC.\n\n### Choose a node label\n\nThe most common label used for rack-zone awareness is topology.kubernetes.io/zone, a standard Kubernetes label that shows the zone a node runs in. Many Kubernetes platforms add this label to nodes by default, as noted in the [Kubernetes documentation](https://kubernetes.io/docs/setup/best-practices/multiple-zones/#nodes-are-labeled).\n\nIf your platform doesn’t set this label automatically, you can use any custom label that describes the node’s topology (such as rack, zone, or region).\n\n### Label all eligible nodes\n\n\nAll eligible nodes **must** have the label for rack awareness to work. The operator requires every node that might run Redis Enterprise pods to be labeled. If any nodes are missing the label, reconciliation fails.\n\n\nEligible nodes are nodes where REC pods can run. By default, this means all worker nodes. You can limit eligibility with [`spec.nodeSelector`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#spec).\n\nGive each eligible node a label value that reflects its rack, zone, or region.\n\nCheck node label values:\n\n```sh\nkubectl get nodes -o custom-columns=\"name:metadata.name\",\"rack\\\\zone:metadata.labels.topology\\.kubernetes\\.io/zone\"\n\nname                                            rack\\zone\nip-10-0-x-a.eu-central-1.compute.internal    eu-central-1a\nip-10-0-x-b.eu-central-1.compute.internal    eu-central-1a\nip-10-0-x-c.eu-central-1.compute.internal    eu-central-1b\nip-10-0-x-d.eu-central-1.compute.internal    eu-central-1b\n```\n\n### Enable the cluster role\n\nGrant the operator read access to node labels with a ClusterRole and ClusterRoleBinding.\n\nClusterRole:\n\n\n\nBind to the `redis-enterprise-operator` service account:\n\n\n\nApply these files with `kubectl apply`. For example:\n\n```sh\nkubectl apply -f rack-aware-cluster-role.yaml\nkubectl apply -f rack-aware-cluster-role-binding.yaml\n```\n\nAfter you apply the role and binding, you can configure rack awareness.\n\n### Configure rack awareness\n\nSet [`spec.rackAwarenessNodeLabel`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#spec) to the node label to use:\n\n\n\n\nWhen you set [`spec.rackAwarenessNodeLabel`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#spec), the operator sets the anti-affinity `topologyKey` to that label unless you define [`spec.podAntiAffinity`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api#specpodantiaffinity). If you define both, make sure `topologyKey` matches your node label.\n\n\n### Rack awareness limitations\n\n\n**Pod restart distribution maintenance**: When rack awareness is enabled, node pods and shards are initially deployed based on rack constraints to ensure proper distribution across zones. However, Redis Enterprise does not automatically maintain this distribution when node pods are restarted.\n\nAfter pod restarts, the rack awareness policy may be violated, requiring manual intervention to restore proper shard distribution. While Redis Enterprise provides tools to identify shards that need to be moved to restore correct rack distribution, it does not provide automated orchestration to perform these moves.\n\n\n**Important considerations for production deployments:**\n\n- At scale, manual shard redistribution can become operationally challenging\n- This limitation is particularly important for edge deployments where automated recovery is preferred\n- Plan for operational procedures to handle rack awareness policy violations after pod restarts\n- Consider monitoring tools to detect when rack awareness constraints are violated\n",
  "tags": ["docs","operate","kubernetes"],
  "last_updated": "2026-06-04T14:49:57+01:00"
}
