https://github.com/idgenchev/namespace-node-affinity
Kubernetes Mutating Webhook for assigning node affinity and tolerations to all pods in a namespace
https://github.com/idgenchev/namespace-node-affinity
affinity go k8s kubernetes kubernetes-mutating-webhook node-selector tolerations
Last synced: 5 months ago
JSON representation
Kubernetes Mutating Webhook for assigning node affinity and tolerations to all pods in a namespace
- Host: GitHub
- URL: https://github.com/idgenchev/namespace-node-affinity
- Owner: idgenchev
- License: apache-2.0
- Created: 2021-04-05T10:11:47.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2026-01-13T17:24:42.000Z (5 months ago)
- Last Synced: 2026-01-13T19:22:38.668Z (5 months ago)
- Topics: affinity, go, k8s, kubernetes, kubernetes-mutating-webhook, node-selector, tolerations
- Language: Go
- Homepage:
- Size: 209 KB
- Stars: 68
- Watchers: 3
- Forks: 16
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README

[](https://goreportcard.com/report/github.com/idgenchev/namespace-node-affinity)
[](https://codecov.io/gh/idgenchev/namespace-node-affinity)
# Namespace Node Affinity
Namespace Node Affinity is a Kubernetes mutating webhook which provides the ability to define node affinity and/or tolerations for pods on a namespace level.
It is a replacement for the [PodNodeSelector](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podnodeselector) admission controller and it is useful when using a managed k8s control plane such as [GKE](https://cloud.google.com/kubernetes-engine) or [EKS](https://aws.amazon.com/eks) where you do not have the ability to enable additional admission controller plugins and the [PodNodeSelector](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podnodeselector) might not be available. The only admission controller plugin required to run the namespace-node-affinity mutating webhook is the `MutatingAdmissionWebhook` which is already enabled on most managed Kubernetes services such as [EKS](https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html).
It might still be useful on [AKS](https://azure.microsoft.com/en-gb/services/kubernetes-service/) where the [PodNodeSelector](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podnodeselector) admission controller is [readily available](https://docs.microsoft.com/en-us/azure/aks/faq#what-kubernetes-admission-controllers-does-aks-support-can-admission-controllers-be-added-or-removed) as using `namespace-node-affinity` allows a litte bit more flexibility than the node selector by allowing you to set node affinity (only `requiredDuringSchedulingIgnoredDuringExecution` is supported for now) for all pods in the namespace.
# Deployment
The easiest way to deploy the namespace-node-affinity mutating webhook is to apply the kustomizations in the `deployments` directory:
```
kubectl apply -k deployments/base
```
This will create the following:
* namespace-node-affinity ServiceAccount
* namespace-node-affinity Role
* namespace-node-affinity RoleBinding
* namespace-node-affinity ClusterRole
* namespace-node-affinity ClusterRoleBinding
* namespace-node-affinity Service
* namespace-node-affinity Deployment
> Note that this will use the latest images on [Docker Hub](https://hub.docker.com/repository/docker/idgenchev/namespace-node-affinity). If you like to use a specific tag you can use the kustomizations in [deployments](/deployments/) as base and override the images in the Deployment with the desired tag.
The Deployment includes an init container which generates a CA and a certificate and key pair for the webhook server and will create/update the MutatingWebhookConfiguration with the generated CA bundle which will be loaded by the Kubernetes API server and used to verify the serving certificates of the namespace-node-affinity mutating webhook. Using this init container allows for a quick and easy deployment of the namespace-node-affinity webhook, but is not recommended for production. For production use it is recommended to use a tool such as [cert-manager](https://cert-manager.io) to manage the certificates for the namespace-node-affinity mutating webhook.
Docker images for the webhook are available for multiple platforms [here](https://hub.docker.com/repository/docker/idgenchev/namespace-node-affinity). Images for the init container are available [here](https://hub.docker.com/repository/docker/idgenchev/namespace-node-affinity-init-container).
# Required Permissions
The namespace-node-affinity webhook requires `get` permissions for `configmaps` in the namespace where the centralised config is deployed.
The init container (if used) requires `get`, `create` and `update` for `mutatingwebhookconfigurations` in the `admissionregistration.k8s.io` api group to create or update the MutatingWebhookConfiguration.
The `Role` and `ClusterRole` included in [deployments](/deployments/) already include all of the required permissions and the supplied `RoleBinding` and `ClusterRoleBinding` binds the `Role` and `ClusterRole` to the `ServiceAccount` used by the webhook.
# Configuration
To enable the namespace-node-affinity mutating webhook on a namespace you simply have to label the namespace with `namespace-node-affinity=enabled`.
```
kubectl label ns my-namespace namespace-node-affinity=enabled
```
Each namespace with the `namespace-node-affinity=enabled` label will also need an entry in the `ConfigMap` where the configuration for the webhook is stored. The config for each namespace can be in either JSON or YAML format and must have at least one of `nodeSelectorTerms` or `tolerations`. The `nodeSelectorTerms` from the config will be added as `requiredDuringSchedulingIgnoredDuringExecution` node affinity type to each pod that is created in the labeled namespace. An example configuration can be found in [examples/sample_configmap.yaml](/examples/sample_configmap.yaml).
More information on how node affinity works can be found [here](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity).
More information on how taints and tolerations work can be found [here](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/).
# Failure Modes
When using the provided init container to create the mutating webhook configuration, the namespace-node-affinity mutating webhook will fail silently so pods can still be created on the cluster if the webhook has been misconfigured. The affected namespace can be seen in the `AdmissionReview.Namespace`.
* Missing `namespace-node-affinity` `ConfigMap`
```
time="2021-04-10T09:35:06Z" level=info msg="Received AdmissionReview: {...}
time="2021-04-10T09:35:06Z" level=error msg="missing configuration: configmaps \"namespace-node-affinity\" not found"
```
* Missing entry for the namespace in the `ConfigMap`
```
time="2021-09-03T17:32:16Z" level=info msg="Received AdmissionReview: {...}
time="2021-09-03T17:32:16Z" level=error msg="missing configuration: for testing-ns-e"
```
* Both `nodeSelectorTerms` and `tolerations` are missing from the entry for the namespace in the `ConfigMap`
```
time="2021-09-03T17:38:46Z" level=info msg="Received AdmissionReview: {...}
time="2021-09-03T17:38:46Z" level=error msg="invalid configuration: at least one of nodeSelectorTerms or tolerations needs to be specified for testing-ns-d"
```
* Invalid `nodeSelectorTerms` or `tolerations` in the `namespace-node-affinity` `ConfigMap`
```
time="2021-04-10T09:40:59Z" level=info msg="Received AdmissionReview: {...}
time="2021-04-10T09:40:59Z" level=error msg="invalid configuration: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go struct field NamespaceConfig.nodeSelectorTerms of type []v1.NodeSelectorTerm"
```
# Contributing
Want to contribute? Awesome! The easiest way to show your support is to star the project, or to raise issues. If you want to open a pull request, please follow the [contributing guidelines](/.github/CONTRIBUTING.md).
Thanks for your support, it is much appreciated!
# License
Apache-2.0. See LICENSE for more details.