Skip to content

Commit

Permalink
Merge pull request kubernetes-sigs#3589 from alefray/ingress-class-fi…
Browse files Browse the repository at this point in the history
…ltering

(V2) Support filtering ingresses on ingressClassName as well as deprecated kubernetes.io/ingress.class annotation
  • Loading branch information
k8s-ci-robot authored May 9, 2023
2 parents 9877b8f + 7b94002 commit c4dcbf7
Show file tree
Hide file tree
Showing 16 changed files with 256 additions and 64 deletions.
37 changes: 23 additions & 14 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,24 +257,33 @@ spec:
### Running an internal and external dns service
Sometimes you need to run an internal and an external dns service.
The internal one should provision hostnames used on the internal network (perhaps inside a VPC), and the external
one to expose DNS to the internet.
The internal one should provision hostnames used on the internal network (perhaps inside a VPC), and the external one to expose DNS to the internet.
To do this with ExternalDNS you can use the `--annotation-filter` to specifically tie an instance of ExternalDNS to
an instance of an ingress controller. Let's assume you have two ingress controllers `nginx-internal` and `nginx-external`
then you can start two ExternalDNS providers one with `--annotation-filter=kubernetes.io/ingress.class in (nginx-internal)`
and one with `--annotation-filter=kubernetes.io/ingress.class in (nginx-external)`.
To do this with ExternalDNS you can use the `--ingress-class` flag to specifically tie an instance of ExternalDNS to an instance of a ingress controller.
Let's assume you have two ingress controllers, `internal` and `external`.
You can then start two ExternalDNS providers, one with `--ingress-class=internal` and one with `--ingress-class=external`.

If you need to search for multiple values of said annotation, you can provide a comma separated list, like so:
`--annotation-filter=kubernetes.io/ingress.class in (nginx-internal, alb-ingress-internal)`.
If you need to search for multiple ingress classes, you can specify the flag multiple times, like so:
`--ingress-class=internal --ingress-class=external`.

Beware when using multiple sources, e.g. `--source=service --source=ingress`, `--annotation-filter` will filter every given source objects.
If you need to filter only one specific source you have to run a separated external dns service containing only the wanted `--source` and `--annotation-filter`.
The `--ingress-class` flag will check both the `spec.ingressClassName` field and the deprecated `kubernetes.io/ingress.class` annotation.
The `spec.ingressClassName` tasks precedence over the annotation if both are supplied.

**Note:** Filtering based on annotation means that the external-dns controller will receive all resources of that kind and then filter on the client-side.
In larger clusters with many resources which change frequently this can cause performance issues. If only some resources need to be managed by an instance
of external-dns then label filtering can be used instead of annotation filtering. This means that only those resources which match the selector specified
in `--label-filter` will be passed to the controller.
**Backward compatibility**

The previous `--annotation-filter` flag can still be used to restrict which objects ExternalDNS considers; for example, `--annotation-filter=kubernetes.io/ingress.class in (public,dmz)`.

However, beware when using annotation filters with multiple sources, e.g. `--source=service --source=ingress`, since `--annotation-filter` will filter every given source object.
If you need to use annotation filters against a specific source you have to run a separated external dns service containing only the wanted `--source` and `--annotation-filter`.

Note: the `--ingress-class` flag cannot be used at the same time as the `--annotation-filter=kubernetes.io/ingress.class in (...)` flag; if you do this an error will be raised.

**Performance considerations**

Filtering based on ingress class name or annotations means that the external-dns controller will receive all resources of that kind and then filter on the client-side.
In larger clusters with many resources which change frequently this can cause performance issues.
If only some resources need to be managed by an instance of external-dns then label filtering can be used instead of ingress class filtering (or legacy annotation filtering).
This means that only those resources which match the selector specified in `--label-filter` will be passed to the controller.

### How do I specify that I want the DNS record to point to either the Node's public or private IP when it has both?

Expand Down
3 changes: 1 addition & 2 deletions docs/tutorials/alibabacloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,8 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: foo
annotations:
kubernetes.io/ingress.class: "nginx" # use the one that corresponds to your ingress controller.
spec:
ingressClassName: nginx # use the one that corresponds to your ingress controller.
rules:
- host: foo.external-dns-test.com
http:
Expand Down
5 changes: 1 addition & 4 deletions docs/tutorials/aws-load-balancer-controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ as Kubernetes does with the AWS cloud provider.
In the examples that follow, it is assumed that you configured the ALB Ingress
Controller with the `ingress-class=alb` argument (not to be confused with the
same argument to ExternalDNS) so that the controller will only respect Ingress
objects with the `kubernetes.io/ingress.class` annotation set to "alb".
objects with the `ingressClassName` field set to "alb".

## Deploy an example application

Expand Down Expand Up @@ -80,7 +80,6 @@ kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
kubernetes.io/ingress.class: alb
name: echoserver
spec:
ingressClassName: alb
Expand Down Expand Up @@ -120,7 +119,6 @@ metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
external-dns.alpha.kubernetes.io/hostname: echoserver.mycluster.example.org, echoserver.example.org
kubernetes.io/ingress.class: alb
name: echoserver
spec:
ingressClassName: alb
Expand Down Expand Up @@ -159,7 +157,6 @@ metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/ip-address-type: dualstack
kubernetes.io/ingress.class: alb
name: echoserver
spec:
ingressClassName: alb
Expand Down
5 changes: 2 additions & 3 deletions docs/tutorials/aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -739,9 +739,8 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: "nginx" # use the one that corresponds to your ingress controller.
spec:
ingressClassName: nginx
rules:
- host: server.example.com
http:
Expand Down Expand Up @@ -936,7 +935,7 @@ Running several fast polling ExternalDNS instances in a given account can easily
* `--source=ingress --source=service` - specify multiple times for multiple sources
* `--namespace=my-app`
* `--label-filter=app in (my-app)`
* `--annotation-filter=kubernetes.io/ingress.class in (nginx-external)` - note that this filter would apply to services too..
* `--ingress-class=nginx-external`
* Limit services watched by type (not applicable to ingress or other types)
* `--service-type-filter=LoadBalancer` default `all`
* Limit the hosted zones considered
Expand Down
3 changes: 1 addition & 2 deletions docs/tutorials/azure-private-dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,8 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: nginx
spec:
ingressClassName: nginx
rules:
- host: server.example.com
http:
Expand Down
3 changes: 1 addition & 2 deletions docs/tutorials/coredns.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,8 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
ingressClassName: nginx
rules:
- host: nginx.example.org
http:
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/exoscale.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: nginx
external-dns.alpha.kubernetes.io/target: {{ Elastic-IP-address }}
spec:
ingressClassName: nginx
rules:
- host: via-ingress.example.com
http:
Expand Down
5 changes: 0 additions & 5 deletions docs/tutorials/kube-ingress-aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ Create the following Ingress to expose the echoserver application to the Interne
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: skipper
name: echoserver
spec:
ingressClassName: skipper
Expand Down Expand Up @@ -181,7 +179,6 @@ kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: echoserver.mycluster.example.org, echoserver.example.org
kubernetes.io/ingress.class: skipper
name: echoserver
spec:
ingressClassName: skipper
Expand Down Expand Up @@ -218,7 +215,6 @@ kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/ip-address-type: dualstack
kubernetes.io/ingress.class: skipper
name: echoserver
spec:
ingressClassName: skipper
Expand Down Expand Up @@ -256,7 +252,6 @@ kind: Ingress
metadata:
annotations:
zalando.org/aws-load-balancer-type: nlb
kubernetes.io/ingress.class: skipper
name: echoserver
spec:
ingressClassName: skipper
Expand Down
4 changes: 0 additions & 4 deletions docs/tutorials/nginx-ingress.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,6 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: nginx
spec:
ingressClassName: nginx
rules:
Expand Down Expand Up @@ -595,8 +593,6 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: nginx
spec:
ingressClassName: nginx
rules:
Expand Down
25 changes: 11 additions & 14 deletions docs/tutorials/public-private-route53.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ spec:

Consult [AWS ExternalDNS setup docs](aws.md) for installation guidelines.

In ExternalDNS containers args, make sure to specify `annotation-filter` and `aws-zone-type`:
In ExternalDNS containers args, make sure to specify `aws-zone-type` and `ingress-class`:

```yaml
apiVersion: apps/v1beta2
Expand Down Expand Up @@ -241,7 +241,7 @@ spec:
- --provider=aws
- --registry=txt
- --txt-owner-id=external-dns
- --annotation-filter=kubernetes.io/ingress.class in (external-ingress)
- --ingress-class=external-ingress
- --aws-zone-type=public
image: registry.k8s.io/external-dns/external-dns:v0.13.4
name: external-dns-public
Expand All @@ -251,7 +251,7 @@ spec:

Consult [AWS ExternalDNS setup docs](aws.md) for installation guidelines.

In ExternalDNS containers args, make sure to specify `annotation-filter` and `aws-zone-type`:
In ExternalDNS containers args, make sure to specify `aws-zone-type` and `ingress-class`:

```yaml
apiVersion: apps/v1beta2
Expand Down Expand Up @@ -279,28 +279,27 @@ spec:
- --provider=aws
- --registry=txt
- --txt-owner-id=dev.k8s.nexus
- --annotation-filter=kubernetes.io/ingress.class in (internal-ingress)
- --ingress-class=internal-ingress
- --aws-zone-type=private
image: registry.k8s.io/external-dns/external-dns:v0.13.4
name: external-dns-private
```

## Create application Service definitions

For this setup to work, you've to create two Service definitions for your application.
For this setup to work, you need to create two Ingress definitions for your application.

At first, create public Service definition:
At first, create a public Ingress definition:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "external-ingress"
labels:
app: app
name: app-public
spec:
ingressClassName: external-ingress
rules:
- host: app.domain.com
http:
Expand All @@ -313,18 +312,17 @@ spec:
pathType: Prefix
```

Then create private Service definition:
Then create a private Ingress definition:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "internal-ingress"
labels:
app: app
name: app-private
spec:
ingressClassName: internal-ingress
rules:
- host: app.domain.com
http:
Expand All @@ -347,12 +345,12 @@ metadata:
certmanager.k8s.io/acme-challenge-type: "dns01"
certmanager.k8s.io/acme-dns01-provider: "route53"
certmanager.k8s.io/cluster-issuer: "letsencrypt-production"
kubernetes.io/ingress.class: "external-ingress"
kubernetes.io/tls-acme: "true"
labels:
app: app
name: app-public
spec:
ingressClassName: "external-ingress"
rules:
- host: app.domain.com
http:
Expand All @@ -375,12 +373,11 @@ And reuse the requested certificate in private Service definition:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "internal-ingress"
labels:
app: app
name: app-private
spec:
ingressClassName: "internal-ingress"
rules:
- host: app.domain.com
http:
Expand Down
3 changes: 1 addition & 2 deletions docs/tutorials/rdns.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,8 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
ingressClassName: nginx
rules:
- host: nginx.lb.rancher.cloud
http:
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func main() {
Namespace: cfg.Namespace,
AnnotationFilter: cfg.AnnotationFilter,
LabelFilter: labelSelector,
IngressClassNames: cfg.IngressClassNames,
FQDNTemplate: cfg.FQDNTemplate,
CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation,
IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation,
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/externaldns/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type Config struct {
Namespace string
AnnotationFilter string
LabelFilter string
IngressClassNames []string
FQDNTemplate string
CombineFQDNAndAnnotation bool
IgnoreHostnameAnnotation bool
Expand Down Expand Up @@ -216,6 +217,7 @@ var defaultConfig = &Config{
Namespace: "",
AnnotationFilter: "",
LabelFilter: labels.Everything().String(),
IngressClassNames: nil,
FQDNTemplate: "",
CombineFQDNAndAnnotation: false,
IgnoreHostnameAnnotation: false,
Expand Down Expand Up @@ -413,6 +415,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("namespace", "Limit sources of endpoints to a specific namespace (default: all namespaces)").Default(defaultConfig.Namespace).StringVar(&cfg.Namespace)
app.Flag("annotation-filter", "Filter sources managed by external-dns via annotation using label selector semantics (default: all sources)").Default(defaultConfig.AnnotationFilter).StringVar(&cfg.AnnotationFilter)
app.Flag("label-filter", "Filter sources managed by external-dns via label selector when listing all resources; currently supported by source types CRD, ingress, service and openshift-route").Default(defaultConfig.LabelFilter).StringVar(&cfg.LabelFilter)
app.Flag("ingress-class", "Require an ingress to have this class name (defaults to any class; specify multiple times to allow more than one class)").StringsVar(&cfg.IngressClassNames)
app.Flag("fqdn-template", "A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN.").Default(defaultConfig.FQDNTemplate).StringVar(&cfg.FQDNTemplate)
app.Flag("combine-fqdn-annotation", "Combine FQDN template and Annotations instead of overwriting").BoolVar(&cfg.CombineFQDNAndAnnotation)
app.Flag("ignore-hostname-annotation", "Ignore hostname annotation when generating DNS names, valid only when using fqdn-template is set (optional, default: false)").BoolVar(&cfg.IgnoreHostnameAnnotation)
Expand Down
Loading

0 comments on commit c4dcbf7

Please sign in to comment.