Allow any kubernetes ingressClass value
This commit is contained in:
parent
aa6fea7f21
commit
56fe023a12
4 changed files with 61 additions and 18 deletions
|
@ -54,8 +54,6 @@ See also [Kubernetes user guide](/user-guide/kubernetes).
|
||||||
# If the parameter is non-empty, only Ingresses containing an annotation with the same value are processed.
|
# If the parameter is non-empty, only Ingresses containing an annotation with the same value are processed.
|
||||||
# Otherwise, Ingresses missing the annotation, having an empty value, or the value `traefik` are processed.
|
# Otherwise, Ingresses missing the annotation, having an empty value, or the value `traefik` are processed.
|
||||||
#
|
#
|
||||||
# Note : `ingressClass` option must begin with the "traefik" prefix.
|
|
||||||
#
|
|
||||||
# Optional
|
# Optional
|
||||||
# Default: empty
|
# Default: empty
|
||||||
#
|
#
|
||||||
|
|
|
@ -859,12 +859,14 @@ Sometimes Træfik runs along other Ingress controller implementations. One such
|
||||||
The `kubernetes.io/ingress.class` annotation can be attached to any Ingress object in order to control whether Træfik should handle it.
|
The `kubernetes.io/ingress.class` annotation can be attached to any Ingress object in order to control whether Træfik should handle it.
|
||||||
|
|
||||||
If the annotation is missing, contains an empty value, or the value `traefik`, then the Træfik controller will take responsibility and process the associated Ingress object.
|
If the annotation is missing, contains an empty value, or the value `traefik`, then the Træfik controller will take responsibility and process the associated Ingress object.
|
||||||
If the annotation contains any other value (usually the name of a different Ingress controller), Træfik will ignore the object.
|
|
||||||
|
|
||||||
It is also possible to set the `ingressClass` option in Træfik to a particular value.
|
It is also possible to set the `ingressClass` option in Træfik to a particular value. Træfik will only process matching Ingress objects.
|
||||||
If that's the case and the value contains a `traefik` prefix, then only those Ingress objects matching the same value will be processed.
|
|
||||||
For instance, setting the option to `traefik-internal` causes Træfik to process Ingress objects with the same `kubernetes.io/ingress.class` annotation value, ignoring all other objects (including those with a `traefik` value, empty value, and missing annotation).
|
For instance, setting the option to `traefik-internal` causes Træfik to process Ingress objects with the same `kubernetes.io/ingress.class` annotation value, ignoring all other objects (including those with a `traefik` value, empty value, and missing annotation).
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Letting multiple ingress controllers handle the same ingress objects can lead to unintended behavior.
|
||||||
|
It is recommended to prefix all ingressClass values with `traefik` to avoid unintended collisions with other ingress implementations.
|
||||||
|
|
||||||
### Between multiple Træfik Deployments
|
### Between multiple Træfik Deployments
|
||||||
|
|
||||||
Sometimes multiple Træfik Deployments are supposed to run concurrently.
|
Sometimes multiple Træfik Deployments are supposed to run concurrently.
|
||||||
|
|
|
@ -100,12 +100,6 @@ func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *s
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We require that IngressClasses start with `traefik` to reduce chances of
|
|
||||||
// conflict with other Ingress Providers
|
|
||||||
if len(p.IngressClass) > 0 && !strings.HasPrefix(p.IngressClass, traefikDefaultIngressClass) {
|
|
||||||
return fmt.Errorf("value for IngressClass has to be empty or start with the prefix %q, instead found %q", traefikDefaultIngressClass, p.IngressClass)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Using Ingress label selector: %q", p.LabelSelector)
|
log.Debugf("Using Ingress label selector: %q", p.LabelSelector)
|
||||||
k8sClient, err := p.newK8sClient(p.LabelSelector)
|
k8sClient, err := p.newK8sClient(p.LabelSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1165,8 +1165,17 @@ func TestIngressClassAnnotation(t *testing.T) {
|
||||||
iAnnotation(annotationKubernetesIngressClass, traefikDefaultIngressClass+"-other"),
|
iAnnotation(annotationKubernetesIngressClass, traefikDefaultIngressClass+"-other"),
|
||||||
iRules(
|
iRules(
|
||||||
iRule(
|
iRule(
|
||||||
iHost("herp"),
|
iHost("foo"),
|
||||||
iPaths(onePath(iPath("/derp"), iBackend("service1", intstr.FromInt(80))))),
|
iPaths(onePath(iPath("/bar"), iBackend("service1", intstr.FromInt(80))))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
buildIngress(
|
||||||
|
iNamespace("testing"),
|
||||||
|
iAnnotation(annotationKubernetesIngressClass, "custom"),
|
||||||
|
iRules(
|
||||||
|
iRule(
|
||||||
|
iHost("foo"),
|
||||||
|
iPaths(onePath(iPath("/bar"), iBackend("service2", intstr.FromInt(80))))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -1182,12 +1191,32 @@ func TestIngressClassAnnotation(t *testing.T) {
|
||||||
sExternalName("example.com"),
|
sExternalName("example.com"),
|
||||||
sPorts(sPort(80, "http"))),
|
sPorts(sPort(80, "http"))),
|
||||||
),
|
),
|
||||||
|
buildService(
|
||||||
|
sName("service2"),
|
||||||
|
sNamespace("testing"),
|
||||||
|
sUID("2"),
|
||||||
|
sSpec(
|
||||||
|
clusterIP("10.0.0.2"),
|
||||||
|
sPorts(sPort(80, "http"))),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints := []*corev1.Endpoints{
|
||||||
|
buildEndpoint(
|
||||||
|
eName("service2"),
|
||||||
|
eUID("1"),
|
||||||
|
eNamespace("testing"),
|
||||||
|
subset(
|
||||||
|
eAddresses(eAddress("10.10.0.1")),
|
||||||
|
ePorts(ePort(80, "http"))),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
watchChan := make(chan interface{})
|
watchChan := make(chan interface{})
|
||||||
client := clientMock{
|
client := clientMock{
|
||||||
ingresses: ingresses,
|
ingresses: ingresses,
|
||||||
services: services,
|
services: services,
|
||||||
|
endpoints: endpoints,
|
||||||
watchChan: watchChan,
|
watchChan: watchChan,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1247,19 +1276,39 @@ func TestIngressClassAnnotation(t *testing.T) {
|
||||||
provider: Provider{IngressClass: traefikDefaultRealm + "-other"},
|
provider: Provider{IngressClass: traefikDefaultRealm + "-other"},
|
||||||
expected: buildConfiguration(
|
expected: buildConfiguration(
|
||||||
backends(
|
backends(
|
||||||
backend("herp/derp",
|
backend("foo/bar",
|
||||||
servers(
|
servers(
|
||||||
server("http://example.com", weight(1)),
|
|
||||||
server("http://example.com", weight(1))),
|
server("http://example.com", weight(1))),
|
||||||
lbMethod("wrr"),
|
lbMethod("wrr"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
frontends(
|
frontends(
|
||||||
frontend("herp/derp",
|
frontend("foo/bar",
|
||||||
passHostHeader(),
|
passHostHeader(),
|
||||||
routes(
|
routes(
|
||||||
route("/derp", "PathPrefix:/derp"),
|
route("/bar", "PathPrefix:/bar"),
|
||||||
route("herp", "Host:herp")),
|
route("foo", "Host:foo")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Provided IngressClass annotation",
|
||||||
|
provider: Provider{IngressClass: "custom"},
|
||||||
|
expected: buildConfiguration(
|
||||||
|
backends(
|
||||||
|
backend("foo/bar",
|
||||||
|
servers(
|
||||||
|
server("http://10.10.0.1:80", weight(1))),
|
||||||
|
lbMethod("wrr"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
frontends(
|
||||||
|
frontend("foo/bar",
|
||||||
|
passHostHeader(),
|
||||||
|
routes(
|
||||||
|
route("/bar", "PathPrefix:/bar"),
|
||||||
|
route("foo", "Host:foo")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue