Cloud Native 10 min read

Mastering Multi‑Instance NGINX‑Ingress: Deployment, Configuration, and Best Practices

This guide explains how NGINX‑Ingress works, outlines key considerations for running multiple instances, and provides step‑by‑step instructions—including helm installation, custom controller parameters, admission webhook scoping, and verification screenshots—to reliably deploy and manage several NGINX‑Ingress controllers in a Kubernetes cluster.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Mastering Multi‑Instance NGINX‑Ingress: Deployment, Configuration, and Best Practices

1. How NGINX‑Ingress Works

In an NGINX‑Ingress pod there are two core components: the nginx‑ingress‑controller and NGINX itself. The controller watches the Kubernetes API server for changes to Ingress, Service, Endpoint, and ConfigMap resources, generates NGINX configuration, and reloads the NGINX process to provide external routing.

When the controller runs, it list‑watches the API server for relevant resources.

If a user creates an Ingress and the controller’s webhook is enabled, the API server calls the controller’s 8443 port to validate the Ingress before storing it in etcd.

The controller detects the new Ingress, fetches the associated Service, Endpoint, and ConfigMap (e.g., certificates), and rewrites nginx.conf.

When a request reaches NGINX on port 80 or 443, NGINX processes it; if the rule matches, a Lua script queries the API server to obtain the backend pod IP.

Key considerations for deploying multiple NGINX‑Ingress instances

How to uniquely identify each NGINX‑Ingress instance?

When several controllers watch Ingress resources, which one should handle a given Ingress?

If some instances have webhook enabled, which controller’s webhook will the API server invoke for validation?

2. Installation Tips for Multiple NGINX‑Ingress Controllers

2.1 Different --controller-class for each instance

Example startup parameters for two instances (nginx‑ingress‑a and nginx‑ingress‑b) are shown in the images below.

2.2 Specify the associated controller with spec.ingressClassName

For Kubernetes versions ≤1.23 the API version is networking.k8s.io/v1beta1:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-a
  namespace: nginx-a
  annotations:
    kubernetes.io/ingress.class: custom-nginx-a
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
        property:
          ingress.beta.kubernetes.io/url-match-mode: STARTS_WITHSTARTS_WITH

For Kubernetes ≥1.23 the API version changes to networking.k8s.io/v1 and the class is set via ingressClassName:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-a
  namespace: nginx-a
spec:
  ingressClassName: custom-nginx-a
  rules:
  - http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
        property:
          ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH

2.3 Scope admission webhooks to a single controller

By default, admission webhooks are global; with multiple controllers they can block all Ingress writes if one controller fails. Use namespaceSelector to limit each webhook to a specific namespace.

admissionwebhook:
  namespaceSelector:
    matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: In
      values: ["${namespace}"]
  rules:
  - operations: ["CREATE","UPDATE"]
    apiGroups: ["*"]
    apiVersions: ["*"]
    resources: ["ingresses"]
    scope: "*"
  objectSelector: {}

For clusters ≥1.28 you can also use matchConditions to filter by ingressClassName.

3. Deploying Multiple NGINX‑Ingress Controllers

Download the Helm chart:

wget https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-4.3.0/ingress-nginx-4.3.0.tgz

Create a custom myvalue.yaml with unique fields for each controller (controller name, ingressClass, service annotations, resources, admission webhook settings, etc.). Example excerpt:

imagePullSecrets: {}
controller:
  name: controller
  image:
    repository: swr.cn-north-4.myhuaweicloud.com/hwofficial/nginx-ingress
    tag: "v1.2.1"
  ingressClass: custom-nginx
  ingressClassResource:
    name: custom-nginx
    controllerValue: k8s.io/custom-nginx
  service:
    annotations:
      kubernetes.io/elb.id: 3660aa3c-xxxx-xxxx-xxxx-xxxxff97xxxx
  resources:
    requests:
      cpu: 200m
      memory: 200Mi
  extraVolumeMounts:
  - name: localtime
    mountPath: /etc/localtime
    readOnly: true
  extraVolumes:
  - name: localtime
    hostPath:
      path: /etc/localtime
  admissionWebhooks:
    enabled: true
    failurePolicy: Fail
    port: 8443
    certificate: "/usr/local/certificates/cert"
    key: "/usr/local/certificates/key"
    namespaceSelector:
      matchExpressions:
      - key: kubernetes.io/metadata.name
        operator: In
        values: ["${namespace}"]
    rules:
    - operations: ["CREATE","UPDATE"]
      apiGroups: ["*"]
      apiVersions: ["*"]
      resources: ["ingresses"]
      scope: "*"
    networkPolicyEnabled: false
    service:
      servicePort: 443
      type: ClusterIP
    createSecretJob:
      resources:
        limits:
          cpu: 20m
          memory: 40Mi
        requests:
          cpu: 10m
          memory: 20Mi
    patch:
      enabled: true
      image:
        registry: registry.k8s.io
        image: ingress-nginx/kube-webhook-certgen
        tag: v1.1.1
        pullPolicy: IfNotPresent
      nodeSelector:
        kubernetes.io/os: linux
      securityContext:
        runAsNonRoot: true
        runAsUser: 2000
        fsGroup: 2000
defaultBackend:
  enabled: false

Deploy the controller to a specific namespace:

helm install ingress-nginx-controller -f myvalue.yaml ./ingress-nginx -a -n ${namespace}

Repeat the above steps for each additional controller.

Result Showcase

Verify controller pods are running, view IngressClass resources, and check the ELB address. Then create test workloads, Services, and Ingress resources to confirm traffic routing.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

cloud-nativeadmission-webhookMulti-Instancenginx-ingress
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.