</code></pre></div><h2id=what-has-caused-this-change-in-behavior>What has caused this change in behavior?<aclass=headerlinkhref=#what-has-caused-this-change-in-behaviortitle="Permanent link"> ¶</a></h2><p>There are 2 primary reasons.</p><h3id=reason-1>Reason 1<aclass=headerlinkhref=#reason-1title="Permanent link"> ¶</a></h3><p>Until K8s version 1.21, it was possible to create an Ingress resource using deprecated versions of the Ingress API, such as:</p><ul><li><code>extensions/v1beta1</code></li><li><code>networking.k8s.io/v1beta1</code> You would get a message about deprecation, but the Ingress resource would get created.</li></ul><p>From K8s version 1.22 onwards, you can <strong>only</strong> access the Ingress API via the stable, <code>networking.k8s.io/v1</code> API. The reason is explained in the <ahref=https://kubernetes.io/blog/2021/07/26/update-with-ingress-nginx/>official blog on deprecated ingress API versions</a>.</p><h3id=reason-2>Reason #2<aclass=headerlinkhref=#reason-2title="Permanent link"> ¶</a></h3><p>If you are already using the ingress-nginx controller and then upgrade to Kubernetes 1.22, there are several scenarios where your existing Ingress objects will not work how you expect.</p><p>Read this FAQ to check which scenario matches your use case.</p><h2id=what-is-the-ingressclassname-field>What is the <code>ingressClassName</code> field?<aclass=headerlinkhref=#what-is-the-ingressclassname-fieldtitle="Permanent link"> ¶</a></h2><p><code>ingressClassName</code> is a field in the spec of an Ingress object.</p><divclass=highlight><pre><span></span><code>kubectl<spanclass=w></span>explain<spanclass=w></span>ingress.spec.ingressClassName
<spanclass=go> IngressClassName is the name of the IngressClass cluster resource. The</span>
<spanclass=go> associated IngressClass defines which controller will implement the</span>
<spanclass=go> resource. This replaces the deprecated `kubernetes.io/ingress.class`</span>
<spanclass=go> annotation. For backwards compatibility, when that annotation is set, it</span>
<spanclass=go> must be given precedence over this field. The controller may emit a warning</span>
<spanclass=go> if the field and annotation have different values. Implementations of this</span>
<spanclass=go> API should ignore Ingresses without a class specified. An IngressClass</span>
<spanclass=go> resource may be marked as default, which can be used to set a default value</span>
<spanclass=go> for this field. For more information, refer to the IngressClass</span>
<spanclass=go> documentation.</span>
</code></pre></div><p>The <code>.spec.ingressClassName</code> behavior has precedence over the deprecated <code>kubernetes.io/ingress.class</code> annotation.</p><h2id=i-have-only-one-ingress-controller-in-my-cluster-what-should-i-do>I have only one ingress controller in my cluster. What should I do?<aclass=headerlinkhref=#i-have-only-one-ingress-controller-in-my-cluster-what-should-i-dotitle="Permanent link"> ¶</a></h2><p>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.</p><p>When using Helm, you can enable this annotation by setting <code>.controller.ingressClassResource.default: true</code> in your Helm chart installation's values file.</p><p>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:</p><ul><li>You can manually set the <ahref=https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec><code>.spec.ingressClassName</code></a> field in the manifest of your own Ingress resources.</li><li>You can re-create them after setting the <code>ingressclass.kubernetes.io/is-default-class</code> annotation to <code>true</code> on the IngressClass</li><li>Alternatively you can make the ingress-nginx controller watch Ingress objects without the ingressClassName field set by starting your ingress-nginx with the flag <ahref=#what-is-the-flag-watch-ingress-without-class>--watch-ingress-without-class=true</a>. When using Helm, you can configure your Helm chart installation's values file with <code>.controller.watchIngressWithoutClass: true</code>.</li></ul><p>We recommend that you create the IngressClass as shown below:</p><divclass=highlight><pre><span></span><code>---
</code></pre></div><p>and add the value <code>spec.ingressClassName=nginx</code> in your Ingress objects.</p><h2id=i-have-many-ingress-objects-in-my-cluster-what-should-i-do>I have many ingress objects in my cluster. What should I do?<aclass=headerlinkhref=#i-have-many-ingress-objects-in-my-cluster-what-should-i-dotitle="Permanent link"> ¶</a></h2><p>If you have a lot of ingress objects without ingressClass configuration, you can run the ingress controller with the flag <code>--watch-ingress-without-class=true</code>.</p><h3id=what-is-the-flag-watch-ingress-without-class>What is the flag <code>--watch-ingress-without-class</code>?<aclass=headerlinkhref=#what-is-the-flag-watch-ingress-without-classtitle="Permanent link"> ¶</a></h3><p>It's a flag that is passed, as an argument, to the <code>nginx-ingress-controller</code> executable. In the configuration, it looks like this:</p><divclass=highlight><pre><span></span><code><spanclass=c1># ...</span>
</code></pre></div><h2id=i-have-more-than-one-controller-in-my-cluster-and-im-already-using-the-annotation>I have more than one controller in my cluster, and I'm already using the annotation<aclass=headerlinkhref=#i-have-more-than-one-controller-in-my-cluster-and-im-already-using-the-annotationtitle="Permanent link"> ¶</a></h2><p>No problem. This should still keep working, but we highly recommend you to test! Even though <code>kubernetes.io/ingress.class</code> 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 <code>.spec.ingressClassName</code>.</p><h2id=i-have-more-than-one-controller-running-in-my-cluster-and-i-want-to-use-the-new-api>I have more than one controller running in my cluster, and I want to use the new API<aclass=headerlinkhref=#i-have-more-than-one-controller-running-in-my-cluster-and-i-want-to-use-the-new-apititle="Permanent link"> ¶</a></h2><p>In this scenario, you need to create multiple IngressClasses (see the example above).</p><p>Be aware that IngressClass works in a very specific way: you will need to change the <code>.spec.controller</code> value in your IngressClass and configure the controller to expect the exact same value.</p><p>Let's see an example, supposing that you have three IngressClasses:</p><ul><li>IngressClass <code>ingress-nginx-one</code>, with <code>.spec.controller</code> equal to <code>example.com/ingress-nginx1</code></li><li>IngressClass <code>ingress-nginx-two</code>, with <code>.spec.controller</code> equal to <code>example.com/ingress-nginx2</code></li><li>IngressClass <code>ingress-nginx-three</code>, with <code>.spec.controller</code> equal to <code>example.com/ingress-nginx1</code></li></ul><p>For private use, you can also use a controller name that doesn't contain a <code>/</code>, e.g. <code>ingress-nginx1</code>.</p><p>When deploying your ingress controllers, you will have to change the <code>--controller-class</code> field as follows:</p><ul><li>Ingress-Nginx A, configured to use controller class name <code>example.com/ingress-nginx1</code></li><li>Ingress-Nginx B, configured to use controller class name <code>example.com/ingress-nginx2</code></li></ul><p>When you create an Ingress object with its <code>ingressClassName</code> set to <code>ingress-nginx-two</code>, only controllers looking for the <code>example.com/ingress-nginx2</code> controller class pay attention to the new object.</p><p>Given that Ingress-Nginx B is set up that way, it will serve that object, whereas Ingress-Nginx A ignores the new Ingress.</p><p>Bear in mind that if you start Ingress-Nginx B with the command line argument <code>--watch-ingress-without-class=true</code>, it will serve:</p><ol><li>Ingresses without any <code>ingressClassName</code> set</li><li>Ingresses where the deprecated annotation (<code>kubernetes.io/ingress.class</code>) matches the value set in the command line argument <code>--ingress-class</code></li><li>Ingresses that refer to any IngressClass that has the same <code>spec.controller</code> as configured in <code>--controller-class</code></li><li>If you start Ingress-Nginx B with the command line argument <code>--watch-ingress-without-class=true</code> and you run Ingress-Nginx A with the command line argument <code>--watch-ingress-without-class=false</code> then this is a supported configuration. If you have two ingress-nginx controllers for the same cluster, both running with <code>--watch-ingress-without-class=true</code> then there is likely to be a conflict.</li></ol><h2id=why-am-i-seeing-ingress-class-annotation-is-not-equal-to-the-expected-by-ingress-controller-in-my-controller-logs>Why am I seeing "ingress class annotation is not equal to the expected by Ingress Controller" in my controller logs?<aclass=headerlinkhref=#why-am-i-seeing-ingress-class-annotation-is-not-equal-to-the-expected-by-ingress-controller-in-my-controller-logstitle="Permanent link"> ¶</a></h2><p>It is highly likely that you will als