Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for IngressClass resources #1133

Merged
merged 6 commits into from
Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 51 additions & 5 deletions cmd/nginx-ingress/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
api_v1 "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation"
util_version "k8s.io/apimachinery/pkg/util/version"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
Expand Down Expand Up @@ -68,13 +69,23 @@ var (
appProtect = flag.Bool("enable-app-protect", false, "Enable support for NGINX App Protect. Requires -nginx-plus.")

ingressClass = flag.String("ingress-class", "nginx",
`A class of the Ingress controller. The Ingress controller only processes Ingress resources that belong to its class
- i.e. have the annotation "kubernetes.io/ingress.class" or the "ingressClassName" field in VirtualServer/VirtualServerRoute equal to the class. Additionally,
the Ingress controller processes Ingress resources that do not have that annotation,
which can be disabled by setting the "-use-ingress-class-only" flag`)
`A class of the Ingress controller.

For Kubernetes >= 1.18, a corresponding IngressClass resource with the name equal to the class must be deployed. Otherwise,
the Ingress Controller will fail to start.
The Ingress controller only processes resources that belong to its class - i.e. have the "ingressClassName" field resource equal to the class.

For Kubernetes < 1.18, the Ingress Controller only processes resources that belong to its class
- i.e have the annotation "kubernetes.io/ingress.class" equal to the class.
Additionally, the Ingress Controller processes resources that do not have the class set,
which can be disabled by setting the "-use-ingress-class-only" flag

The Ingress Controller processes all the VirtualServer/VirtualServerRoute resources that do not have the "ingressClassName" field for all versions of kubernetes.`)

useIngressClassOnly = flag.Bool("use-ingress-class-only", false,
`Ignore Ingress resources without the "kubernetes.io/ingress.class" annotation or the "ingressClassName" field in VirtualServer/VirtualServerRoute`)
`For kubernetes versions >= 1.18 this flag will be IGNORED.

Ignore Ingress resources without the "kubernetes.io/ingress.class" annotation`)

defaultServerSecret = flag.String("default-server-tls-secret", "",
`A Secret with a TLS certificate and key for TLS termination of the default server. Format: <namespace>/<name>.
Expand Down Expand Up @@ -256,6 +267,32 @@ func main() {
glog.Fatalf("Failed to create client: %v.", err)
}

k8sVersion, err := k8s.GetK8sVersion(kubeClient)
if err != nil {
glog.Fatalf("error retrieving k8s version: %v", err)
}

minK8sVersion := minVersion("1.14.0")
if !k8sVersion.AtLeast(minK8sVersion) {
glog.Fatalf("Versions of Kubernetes < %v are not supported, please refer to the documentation for details on supported versions.", minK8sVersion)
}

// Ingress V1 is only available from k8s > 1.18
ingressV1Version := minVersion("1.18.0")
if k8sVersion.AtLeast(ingressV1Version) {
*useIngressClassOnly = true
glog.Warningln("The '-use-ingress-class-only' flag will be deprecated and has no effect on versions of kubernetes >= 1.18.0. Processing ONLY resources that have the 'ingressClassName' field in Ingress equal to the class.")

ingressClassRes, err := kubeClient.NetworkingV1beta1().IngressClasses().Get(context.TODO(), *ingressClass, meta_v1.GetOptions{})
if err != nil {
glog.Fatalf("Error when getting IngressClass %v: %v", *ingressClass, err)
}

if ingressClassRes != nil && ingressClassRes.Spec.Controller != k8s.IngressControllerName {
lucacome marked this conversation as resolved.
Show resolved Hide resolved
glog.Fatalf("IngressClass with name %v has an invalid Spec.Controller %v", ingressClassRes.Name, ingressClassRes.Spec.Controller)
}
}

var dynClient dynamic.Interface
if *appProtect {
dynClient, err = dynamic.NewForConfig(config)
Expand Down Expand Up @@ -789,3 +826,12 @@ func ready(lbc *k8s.LoadBalancerController) http.HandlerFunc {
fmt.Fprintln(w, "Ready")
}
}

func minVersion(min string) (v *util_version.Version) {
minVer, err := util_version.ParseGeneric(min)
if err != nil {
glog.Fatalf("unexpected error parsing minimum supported version: %v", err)
}

return minVer
}
8 changes: 8 additions & 0 deletions deployments/common/ingress-class.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
name: nginx
# annotations:
# ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: nginx.org/ingress-controller
5 changes: 3 additions & 2 deletions deployments/helm-chart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,9 @@ Parameter | Description | Default
`controller.volumeMounts` | The volumeMounts of the Ingress controller pods. | []
`controller.resources` | The resources of the Ingress controller pods. | {}
`controller.replicaCount` | The number of replicas of the Ingress controller deployment. | 1
`controller.ingressClass` | A class of the Ingress controller. The Ingress controller only processes Ingress resources that belong to its class - i.e. have the annotation `"kubernetes.io/ingress.class"` or the `"ingressClassName"` field in VirtualServer/VirtualServerRoute equal to the class. Additionally, the Ingress controller processes Ingress resources that do not have that annotation which can be disabled by setting the "-use-ingress-class-only" flag. | nginx
`controller.useIngressClassOnly` | Ignore Ingress resources without the `"kubernetes.io/ingress.class"` annotation or the `"ingressClassName"` field in VirtualServer/VirtualServerRoute. | false
`controller.ingressClass` | A class of the Ingress controller. For Kubernetes >= 1.18, the Ingress controller only processes resources that belong to its class - i.e. have the "ingressClassName" field resource equal to the class. Additionally the Ingress Controller processes all the VirtualServer/VirtualServerRoute resources that do not have the "ingressClassName" field. For Kubernetes < 1.18, the Ingress Controller only processes resources that belong to its class - i.e have the annotation "kubernetes.io/ingress.class" (for Ingress resources) or field "ingressClassName" (for VirtualServer/VirtualServerRoute resources) equal to the class. Additionally, the Ingress Controller processes resources that do not have the class set, which can be disabled by setting the "-use-ingress-class-only" flag. | nginx
`controller.useIngressClassOnly` | Ignore Ingress resources without the `"kubernetes.io/ingress.class"` annotation. For kubernetes versions >= 1.18 this flag will be IGNORED. | false
`controller.setAsDefaultIngress` | New Ingresses without an `"ingressClassName"` field specified will be assigned the class specified in `controller.ingressClass`. Only for kubernetes versions >= 1.18. | false
`controller.watchNamespace` | Namespace to watch for Ingress resources. By default the Ingress controller watches all namespaces. | ""
`controller.enableCustomResources` | Enable the custom resources. | true
`controller.enableTLSPassthrough` | Enable TLS Passthrough on port 443. Requires `controller.enableCustomResources`. | false
Expand Down
2 changes: 2 additions & 0 deletions deployments/helm-chart/templates/controller-daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ spec:
- -default-server-tls-secret=$(POD_NAMESPACE)/{{ include "nginx-ingress.defaultTLSName" . }}
{{- end }}
- -ingress-class={{ .Values.controller.ingressClass }}
{{- if semverCompare "<1.18.0" .Capabilities.KubeVersion.GitVersion }}
- -use-ingress-class-only={{ .Values.controller.useIngressClassOnly }}
{{- end }}
{{- if .Values.controller.watchNamespace }}
- -watch-namespace={{ .Values.controller.watchNamespace }}
{{- end }}
Expand Down
2 changes: 2 additions & 0 deletions deployments/helm-chart/templates/controller-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ spec:
- -default-server-tls-secret=$(POD_NAMESPACE)/{{ include "nginx-ingress.defaultTLSName" . }}
{{- end }}
- -ingress-class={{ .Values.controller.ingressClass }}
{{- if semverCompare "<1.18.0" .Capabilities.KubeVersion.GitVersion }}
- -use-ingress-class-only={{ .Values.controller.useIngressClassOnly }}
{{- end }}
{{- if .Values.controller.watchNamespace }}
- -watch-namespace={{ .Values.controller.watchNamespace }}
{{- end }}
Expand Down
12 changes: 12 additions & 0 deletions deployments/helm-chart/templates/controller-ingress-class..yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- if semverCompare ">=1.18.0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
name: {{ .Values.controller.ingressClass }}
{{- if .Values.controller.setAsDefaultIngress }}
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
{{- end }}
spec:
controller: nginx.org/ingress-controller
{{- end }}
6 changes: 6 additions & 0 deletions deployments/helm-chart/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ rules:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
{{- if .Values.controller.reportIngressStatus.enable }}
- apiGroups:
- networking.k8s.io
Expand Down
21 changes: 17 additions & 4 deletions deployments/helm-chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,27 @@ controller:
## The number of replicas of the Ingress controller deployment.
replicaCount: 1

## A class of the Ingress controller. The Ingress controller only processes Ingress resources that belong to its class
## i.e. have the annotation "kubernetes.io/ingress.class" or the "ingressClassName" field in VirtualServer/VirtualServerRoute equal to the class.
## Additionally, the Ingress controller processes Ingress resources that do not have that annotation which can be disabled by setting the "-use-ingress-class-only" flag.
## A class of the Ingress controller.

## For Kubernetes >= 1.18, a corresponding IngressClass resource with the name equal to the class must be deployed. Otherwise,
## the Ingress Controller will fail to start.
## The Ingress controller only processes resources that belong to its class - i.e. have the "ingressClassName" field resource equal to the class.

## For Kubernetes < 1.18, the Ingress Controller only processes resources that belong to its class
## - i.e have the annotation "kubernetes.io/ingress.class" equal to the class.
## Additionally, the Ingress Controller processes resources that do not have the class set, which can be disabled by setting the "-use-ingress-class-only" flag

## The Ingress Controller processes all the VirtualServer/VirtualServerRoute resources that do not have the "ingressClassName" field for all versions of kubernetes.
ingressClass: nginx

## Ignore Ingress resources without the "kubernetes.io/ingress.class" annotation or the "ingressClassName" field in VirtualServer/VirtualServerRoute.
## For kubernetes versions >= 1.18 this flag will be IGNORED.
## Ignore Ingress resources without the "kubernetes.io/ingress.class" annotation
useIngressClassOnly: false

## Only for Kubernetes >= 1.18
## New Ingresses without an ingressClassName field specified will be assigned the class specified in `controller.ingressClass`.
setAsDefaultIngress: false

## Namespace to watch for Ingress resources. By default the Ingress controller watches all namespaces.
watchNamespace: ""

Expand Down
6 changes: 6 additions & 0 deletions deployments/rbac/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ rules:
- virtualserverroutes/status
verbs:
- update
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,15 @@ Below we describe the available command-line arguments:

.. option:: -ingress-class <string>

A class of the Ingress controller. The Ingress controller only processes Ingress resources that belong to its class (i.e. have the annotation "kubernetes.io/ingress.class" or the "ingressClassName" field in VirtualServer/VirtualServerRoute").
Additionally, the Ingress controller processes Ingress resources that do not have that annotation, which can be disabled by setting the :option:`-use-ingress-class-only` flag (default "nginx").
A class of the Ingress controller.

For Kubernetes >= 1.18, a corresponding IngressClass resource with the name equal to the class must be deployed. Otherwise, the Ingress Controller will fail to start.
The Ingress controller only processes resources that belong to its class - i.e. have the "ingressClassName" field resource equal to the class.

For Kubernetes < 1.18, the Ingress Controller only processes resources that belong to its class - i.e have the annotation "kubernetes.io/ingress.class" (for Ingress resources) or field "ingressClassName" (for VirtualServer/VirtualServerRoute resources) equal to the class.
Additionally, the Ingress Controller processes resources that do not have the class set, which can be disabled by setting the "-use-ingress-class-only" flag (default "nginx").
lucacome marked this conversation as resolved.
Show resolved Hide resolved

The Ingress Controller processes all the VirtualServer/VirtualServerRoute resources that do not have the "ingressClassName" field.

.. option:: -ingress-template-path <string>

Expand Down Expand Up @@ -140,7 +147,9 @@ Below we describe the available command-line arguments:

.. option:: -use-ingress-class-only

Ignore Ingress resources without the "kubernetes.io/ingress.class" annotation or the "ingressClassName" field in VirtualServer/VirtualServerRoute.
For kubernetes versions >= 1.18 this flag will be IGNORED.

Ignore Ingress resources without the "kubernetes.io/ingress.class" annotation.

.. option:: -v <value>

Expand Down
10 changes: 10 additions & 0 deletions docs-web/configuration/ingress-resources/basic-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ Starting from Kubernetes 1.18, you can use the following new features:
serviceName: coffee-svc
servicePort: 80
```
* The `ingressClassName` field is now supported. When using this filed you need to create the `IngressClass` resource with the corresponding `name`, for example create the following resource:
lucacome marked this conversation as resolved.
Show resolved Hide resolved
```yaml
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
name: nginx
spec:
controller: nginx.org/ingress-controller
```
and then set `spec.IngressClassName` to `nginx` in the `Ingress` resource.

## Restrictions

Expand Down
15 changes: 13 additions & 2 deletions docs-web/installation/installation-with-helm.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,21 @@ The following tables lists the configurable parameters of the NGINX Ingress cont
- The number of replicas of the Ingress controller deployment.
- 1
* - ``controller.ingressClass``
- A class of the Ingress controller. The Ingress controller only processes Ingress resources that belong to its class - i.e. have the annotation ``"kubernetes.io/ingress.class"`` or the ``"ingressClassName"`` field in VirtualServer/VirtualServerRoute equal to the class. Additionally, the Ingress controller processes Ingress resources that do not have that annotation which can be disabled by setting the "-use-ingress-class-only" flag.
lucacome marked this conversation as resolved.
Show resolved Hide resolved
- A class of the Ingress controller.
For Kubernetes >= 1.18, a corresponding IngressClass resource with the name equal to the class must be deployed. Otherwise,
the Ingress Controller will fail to start.
The Ingress controller only processes resources that belong to its class - i.e. have the "ingressClassName" field resource equal to the class.

For Kubernetes < 1.18, the Ingress Controller only processes resources that belong to its class - i.e have the annotation "kubernetes.io/ingress.class" equal to the class.
Additionally, the Ingress Controller processes resources that do not have the class set, which can be disabled by setting the "-use-ingress-class-only" flag.

The Ingress Controller processes all the VirtualServer/VirtualServerRoute resources that do not have the "ingressClassName" field for all versions of kubernetes.
- nginx
* - ``controller.useIngressClassOnly``
- Ignore Ingress resources without the ``"kubernetes.io/ingress.class"`` annotation or the ``"ingressClassName"`` field in VirtualServer/VirtualServerRoute.
- Ignore Ingress resources without the ``"kubernetes.io/ingress.class"`` annotation. For kubernetes versions >= 1.18 this flag will be IGNORED.
- false
* - ``controller.setAsDefaultIngress``
- New Ingresses without an ingressClassName field specified will be assigned the class specified in `controller.ingressClass`.
- false
* - ``controller.watchNamespace``
- Namespace to watch for Ingress resources. By default the Ingress controller watches all namespaces.
Expand Down
8 changes: 8 additions & 0 deletions docs-web/installation/installation-with-manifests.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ In this section, we create resources common for most of the Ingress Controller i
$ kubectl apply -f common/nginx-config.yaml
```

1. Create an IngressClass resource (for Kubernetes >= 1.18):
```
$ kubectl apply -f common/ingress-class.yaml
lucacome marked this conversation as resolved.
Show resolved Hide resolved
```
If you would like to set the Ingress Controller as the default ingress, uncomment the annotation `ingressclass.kubernetes.io/is-default-class`. With this annotation set to true all the new Ingresses without an ingressClassName field specified will be assigned this IngressClass.
lucacome marked this conversation as resolved.
Show resolved Hide resolved

***Note**: The Ingress Controller will fail to start without an IngressClass resource.
lucacome marked this conversation as resolved.
Show resolved Hide resolved

### Create Custom Resources

**Note**: If you're using Kubernetes 1.14, make sure to add `--validate=false` to the `kubectl apply` commands below. Otherwise, you will get an error validating data:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This document explains the following topics:
The smooth coexistence of multiple Ingress Controllers in one cluster is provided by the Ingress class concept, which mandates the following:
* Every Ingress Controller must only handle Ingress resources for its particular class.
* Ingress resources should be annotated with the `kubernetes.io/ingress.class` annotation set to the value, which corresponds to the class of the Ingress Controller the user wants to use.
* When using versions of Kubernetes >= 1.18, Ingress resources should have the `ingressClassName` field set to the value, which corresponds to the class of the Ingress Controller the user wants to use.
lucacome marked this conversation as resolved.
Show resolved Hide resolved
* VirtualServer and VirtualServerRoute resources should have the `ingressClassName` field set to the value, which corresponds to the class of the Ingress Controller the user wants to use.

### Configuring Ingress Class
lucacome marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
2 changes: 1 addition & 1 deletion examples/complete-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ $ kubectl create -f cafe.yaml
$ kubectl create -f cafe-secret.yaml
```

2. Create an Ingress resource:
2. Create an Ingress resource (for Kubernetes >= 1.18, uncomment the ```ingressClassName``` field in the YAML file):
```
$ kubectl create -f cafe-ingress.yaml
```
Expand Down
1 change: 1 addition & 0 deletions examples/complete-example/cafe-ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ kind: Ingress
metadata:
name: cafe-ingress
spec:
# ingressClassName: nginx # use only with k8s version >= 1.18.0
tls:
- hosts:
- cafe.example.com
Expand Down
Loading