nginx
ingress
deployment
daemonset
kubernetes

update nginx ingress from deployment to daemonset

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Switching an ingress-nginx controller from a Deployment to a DaemonSet changes how the controller is distributed across your cluster. The main reason to do it is usually operational: a DaemonSet gives you one ingress pod per eligible node, which can make sense for bare-metal clusters, host networking, or node-local traffic handling.

Know What Changes Operationally

A Deployment manages a chosen replica count. A DaemonSet runs one pod on every eligible node. That means the change affects:

  • how many controller pods exist
  • how pods are scheduled onto nodes
  • how you size resources per node
  • how services and external traffic reach the controller

For ingress-nginx, this is not just a cosmetic manifest change. It changes the traffic topology.

When a DaemonSet Makes Sense

A DaemonSet is commonly used when:

  • you want one ingress controller per node
  • you rely on host ports or host networking
  • you are on bare metal and want node-local exposure
  • you want newly added nodes to receive a controller automatically

A Deployment is still perfectly valid when a smaller shared replica pool behind a Service is enough. So migrate only when the node-per-pod model actually fits your environment.

Helm-Based Migration Is Usually the Safest Route

If ingress-nginx was installed with Helm, the cleanest migration is usually to update the controller kind through chart values and run helm upgrade.

A minimal values file can look like this:

yaml
1controller:
2  kind: DaemonSet
3  service:
4    externalTrafficPolicy: Local

Then upgrade:

bash
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  -f values.yaml

Before doing this in production, inspect the rendered manifests and chart notes carefully because Service type, host ports, tolerations, and node selectors may need to change at the same time.

Raw Manifest Migration

If you manage manifests directly, you normally cannot "convert" a Deployment object into a DaemonSet with a trivial in-place edit. The safe pattern is:

  1. export or preserve your current controller settings
  2. create a DaemonSet manifest with matching labels and container args
  3. apply the new controller resource
  4. remove the old Deployment once traffic is stable

A simplified controller skeleton looks like this:

yaml
1apiVersion: apps/v1
2kind: DaemonSet
3metadata:
4  name: ingress-nginx-controller
5  namespace: ingress-nginx
6spec:
7  selector:
8    matchLabels:
9      app.kubernetes.io/name: ingress-nginx
10      app.kubernetes.io/component: controller
11  template:
12    metadata:
13      labels:
14        app.kubernetes.io/name: ingress-nginx
15        app.kubernetes.io/component: controller
16    spec:
17      serviceAccountName: ingress-nginx
18      containers:
19        - name: controller
20          image: registry.k8s.io/ingress-nginx/controller:v1.11.0
21          args:
22            - /nginx-ingress-controller
23            - --ingress-class=nginx

In a real cluster, you must carry over the full controller arguments, volumes, admission settings, probes, and security context from your current installation.

Service and Networking Matter

The controller kind is only half the migration. You also need to confirm how traffic reaches the pods.

Questions to answer before the change:

  • will the Service still point at the controller pods correctly
  • do you need externalTrafficPolicy: Local
  • are you using hostNetwork or hostPort
  • should the DaemonSet run on control-plane nodes or only worker nodes

For example, if the controller should only run on labeled ingress nodes, add a node selector.

yaml
1spec:
2  template:
3    spec:
4      nodeSelector:
5        ingress-ready: "true"

That prevents the DaemonSet from spreading onto nodes where it does not belong.

Plan the Rollout Carefully

Ingress is a cluster entry point, so a bad migration is user-visible immediately. A cautious rollout usually includes:

  1. render and review the new manifests
  2. check resource requests on every target node
  3. stage the change in a non-production cluster
  4. verify controller pod count and readiness
  5. test a real ingress route end to end

If possible, keep rollback simple by preserving the previous manifest or Helm values so you can revert quickly.

Common Pitfalls

A common mistake is focusing only on kind: DaemonSet and forgetting the Service exposure model. Traffic problems after migration often come from Service or networking assumptions, not from the controller pod itself.

Another issue is running the controller on every node unintentionally. Without node selectors or tolerations tuned correctly, the DaemonSet can land in places you did not expect.

Teams also sometimes overlook resource cost. One pod per node can be substantially more expensive than a small Deployment replica set.

Finally, do not treat the change as risk-free because the image stays the same. Changing the workload controller changes rollout behavior and cluster footprint in meaningful ways.

Summary

  • Moving ingress-nginx from Deployment to DaemonSet changes traffic topology, not just YAML shape.
  • Use a DaemonSet when one controller pod per node is actually desirable.
  • Helm upgrade is usually the safest migration path when Helm manages the install.
  • Review Service exposure, host networking, and node placement at the same time.
  • Validate the rollout in staging before changing a production entry point.

Course illustration
Course illustration

All Rights Reserved.