This is the documentation for the Ingress NGINX Controller.
Getting Started ¶
See Deployment for a whirlwind tour that will get you started.
FAQ - Migration to apiVersion
If you are using Ingress objects in your cluster (running Kubernetes older than v1.22), and you plan to upgrade to Kubernetes v1.22, this section is relevant to you.
Please read this official blog on deprecated Ingress API versions
Please read this official documentation on the IngressClass object
What is an IngressClass and why is it important for users of Ingress-NGINX controller now ? ¶
IngressClass is a Kubernetes resource. See the description below. It's important because until now, a default install of the Ingress-NGINX controller did not require any IngressClass object. From version 1.0.0 of the Ingress-NGINX Controller, an IngressClass object is required.
On clusters with more than one instance of the Ingress-NGINX controller, all instances of the controllers must be aware of which Ingress objects they serve. The
ingressClassName field of an Ingress is the way to let the controller know about that.
kubectl explain ingressclass
KIND: IngressClass VERSION: networking.k8s.io/v1 DESCRIPTION: IngressClass represents the class of the Ingress, referenced by the Ingress Spec. The `ingressclass.kubernetes.io/is-default-class` annotation can be used to indicate that an IngressClass should be considered default. When a single IngressClass resource has this annotation set to true, new Ingress resources without a class specified will be assigned this default class. FIELDS: apiVersion <string> APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources kind <string> Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds metadata <Object> Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata spec <Object> Spec is the desired state of the IngressClass. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status`
What has caused this change in behavior? ¶
There are 2 reasons primarily.
Reason #1 ¶
Until K8s version 1.21, it was possible to create an Ingress resource using deprecated versions of the Ingress API, such as:
You would get a message about deprecation, but the Ingress resource would get created.
From K8s version 1.22 onwards, you can only access the Ingress API via the stable,
networking.k8s.io/v1 API. The reason is explained in the official blog on deprecated ingress API versions.
Reason #2 ¶
If you are already using the Ingress-NGINX controller and then upgrade to K8s version v1.22 , there are several scenarios where your existing Ingress objects will not work how you expect. Read this FAQ to check which scenario matches your use case.
What is ingressClassName field ? ¶
ingressClassName is a field in the specs of an Ingress object.
kubectl explain ingress.spec.ingressClassName
KIND: Ingress VERSION: networking.k8s.io/v1 FIELD: ingressClassName <string> DESCRIPTION: IngressClassName is the name of the IngressClass cluster resource. The associated IngressClass defines which controller will implement the resource. This replaces the deprecated `kubernetes.io/ingress.class` annotation. For backwards compatibility, when that annotation is set, it must be given precedence over this field. The controller may emit a warning if the field and annotation have different values. Implementations of this API should ignore Ingresses without a class specified. An IngressClass resource may be marked as default, which can be used to set a default value for this field. For more information, refer to the IngressClass documentation.
.spec.ingressClassName behavior has precedence over the deprecated
I have only one ingress controller in my cluster. What should I do? ¶
If a single instance of the Ingress-NGINX controller is the sole Ingress controller running in your cluster, you should add the annotation "ingressclass.kubernetes.io/is-default-class" in your IngressClass, so any new Ingress objects will have this one as default IngressClass.
When using Helm, you can enable this annotation by setting
.controller.ingressClassResource.default: true in your Helm chart installation's values file.
If you have any old Ingress objects remaining without an IngressClass set, you can do one or more of the following to make the Ingress-NGINX controller aware of the old objects:
- You can manually set the
.spec.ingressClassNamefield in the manifest of your own Ingress resources.
- You can re-create them after setting the
trueon the IngressClass
- Alternatively you can make the Ingress-NGINX controller watch Ingress objects without the ingressClassName field set by starting your Ingress-NGINX with the flag --watch-ingress-without-class=true . When using Helm, you can configure your Helm chart installation's values file with
You can configure your Helm chart installation's values file with
We recommend that you create the IngressClass as shown below:
--- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: app.kubernetes.io/component: controller name: nginx annotations: ingressclass.kubernetes.io/is-default-class: "true" spec: controller: k8s.io/ingress-nginx
And add the value
spec.ingressClassName=nginx in your Ingress objects.
I have multiple ingress objects in my cluster. What should I do ? ¶
- If you have lot of ingress objects without ingressClass configuration, you can run the ingress-controller with the flag
What is the flag '--watch-ingress-without-class' ? ¶
- Its a flag that is passed,as an argument, to the
nginx-ingress-controllerexecutable. In the configuration, it looks like this:
... ... args: - /nginx-ingress-controller - --watch-ingress-without-class=true - --publish-service=$(POD_NAMESPACE)/ingress-nginx-dev-v1-test-controller - --election-id=ingress-controller-leader - --controller-class=k8s.io/ingress-nginx - --configmap=$(POD_NAMESPACE)/ingress-nginx-dev-v1-test-controller - --validating-webhook=:8443 - --validating-webhook-certificate=/usr/local/certificates/cert - --validating-webhook-key=/usr/local/certificates/key ... ...
I have more than one controller in my cluster and already use the annotation ? ¶
No problem. This should still keep working, but we highly recommend you to test!
kubernetes.io/ingress.class is deprecated, the Ingress-NGINX controller still understands that annotation. If you want to follow good practice, you should consider migrating to use IngressClass and
I have more than one controller running in my cluster, and I want to use the new API ? ¶
In this scenario, you need to create multiple IngressClasses (see example one). But be aware that IngressClass works in a very specific way: you will need to change the
.spec.controller value in your IngressClass and configure the controller to expect the exact same value.
Let's see some example, supposing that you have three IngressClasses:
(for private use, you can also use a controller name that doesn't contain a
/; for example:
When deploying your ingress controllers, you will have to change the
--controller-class field as follows:
- Ingress-Nginx A, configured to use controller class name
- Ingress-Nginx B, configured to use controller class name
Then, when you create an Ingress object with its
ingressClassName set to
ingress-nginx-two, only controllers looking for the
example.com/ingress-nginx2 controller class pay attention to the new object. Given that Ingress-Nginx B is set up that way, it will serve that object, whereas Ingress-Nginx A ignores the new Ingress.
Bear in mind that, if you start Ingress-Nginx B with the command line argument
--watch-ingress-without-class=true, then it will serve:
- Ingresses without any
- Ingresses where the deprecated annotation (
kubernetes.io/ingress.class) matches the value set in the command line argument
- Ingresses that refer to any IngressClass that has the same
spec.controlleras configured in
If you start Ingress-Nginx B with the command line argument
--watch-ingress-without-class=true and you run Ingress-Nginx A with the command line argument
--watch-ingress-without-class=false then this is a supported configuration. If you have two Ingress-NGINX controllers for the same cluster, both running with
--watch-ingress-without-class=true then there is likely to be a conflict.
I am seeing this error message in the logs of the Ingress-NGINX controller: "ingress class annotation is not equal to the expected by Ingress Controller". Why ? ¶
- It is highly likely that you will also see the name of the ingress resource in the same error message. This error message has been observed on use the deprecated annotation (
kubernetes.io/ingress.class) in a Ingress resource manifest. It is recommended to use the
.spec.ingressClassNamefield of the Ingress resource, to specify the name of the IngressClass of the Ingress you are defining.
How to easily install multiple instances of the ingress-NGINX controller in the same cluster ? ¶
- Create a new namespace
kubectl create namespace ingress-nginx-2
- Use Helm to install the additional instance of the ingress controller
- Ensure you have Helm working (refer to the Helm documentation)
- We have to assume that you have the helm repo for the ingress-NGINX controller already added to your Helm config. But, if you have not added the helm repo then you can do this to add the repo to your helm config;
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
- Make sure you have updated the helm repo data;
helm repo update
- Now, install an additional instance of the ingress-NGINX controller like this:
helm install ingress-nginx-2 ingress-nginx/ingress-nginx \ --namespace ingress-nginx-2 \ --set controller.ingressClassResource.name=nginx-two \ --set controller.ingressClass=nginx-two \ --set controller.ingressClassResource.controllerValue="example.com/ingress-nginx-2" \ --set controller.ingressClassResource.enabled=true \ --set controller.ingressClassByName=true
- If you need to install yet another instance, then repeat the procedure to create a new namespace, change the values such as names & namespaces (for example from "-2" to "-3"), or anything else that meets your needs.
- If you need to install all instances in the same namespace, then you need to specify a different election id, like this:
helm install ingress-nginx-2 ingress-nginx/ingress-nginx \ --namespace kube-system \ --set controller.electionID=nginx-two-leader \ --set controller.ingressClassResource.name=nginx-two \ --set controller.ingressClass=nginx-two \ --set controller.ingressClassResource.controllerValue="example.com/ingress-nginx-2" \ --set controller.ingressClassResource.enabled=true \ --set controller.ingressClassByName=true
- Note, controller.ingressClassResource.name and controller.ingressClass have to be set with the value of the new class as the first is to create the IngressClass object and the other is to modify the deployment of the actuall ingress controller pod.