docs/user-guide/k8s-122-migration.md
networking.k8s.io/v1If you are using Ingress objects in your cluster (running Kubernetes older than v1.22), and you plan to upgrade to Kubernetes v1.22, this page is relevant to you.
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 a 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`
There are 2 primary reasons.
Until K8s version 1.21, it was possible to create an Ingress resource using deprecated versions of the Ingress API, such as:
extensions/v1beta1networking.k8s.io/v1beta1
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.
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.
Read this FAQ to check which scenario matches your use case.
ingressClassName field?ingressClassName is a field in the spec 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.
The .spec.ingressClassName behavior has precedence over the deprecated kubernetes.io/ingress.class annotation.
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:
.spec.ingressClassName field in the manifest of your own Ingress resources.ingressclass.kubernetes.io/is-default-class annotation to true on the IngressClass.controller.watchIngressWithoutClass: true.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.
If you have a lot of ingress objects without ingressClass configuration,
you can run the ingress controller with the flag --watch-ingress-without-class=true.
--watch-ingress-without-class?It's a flag that is passed, as an argument, to the nginx-ingress-controller executable.
In the configuration, it looks like this:
# ...
args:
- /nginx-ingress-controller
- --watch-ingress-without-class=true
- --controller-class=k8s.io/ingress-nginx
# ...
# ...
No problem. This should still keep working, but we highly recommend you to test!
Even though 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 .spec.ingressClassName.
In this scenario, you need to create multiple IngressClasses (see the example above).
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 an example, supposing that you have three IngressClasses:
ingress-nginx-one, with .spec.controller equal to example.com/ingress-nginx1ingress-nginx-two, with .spec.controller equal to example.com/ingress-nginx2ingress-nginx-three, with .spec.controller equal to example.com/ingress-nginx1For private use, you can also use a controller name that doesn't contain a /, e.g. ingress-nginx1.
When deploying your ingress controllers, you will have to change the --controller-class field as follows:
example.com/ingress-nginx1example.com/ingress-nginx2When 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, it will serve:
ingressClassName setkubernetes.io/ingress.class) matches the value set in the command line argument --ingress-classspec.controller as configured in --controller-class--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.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 an Ingress resource manifest.
It is recommended to use the .spec.ingressClassName field of the Ingress resource, to specify the name of the IngressClass of the Ingress you are defining.