external-dns/docs/tutorials/kube-ingress-aws.md
Rich 7c23e01e31
feat(aws): always create AAAA alias records in route53 (#5111)
* First pass based on existing PR, what is currently on master and some
extra tests.

* Try to resolve AWS service documentation

* Add documentation on how to opt-out of AAAA record creation

* Address documentation concerns

* Add some IPv6 tests to sources

* Make recommended changes to documentation
2025-03-03 00:21:00 -08:00

329 lines
9.2 KiB
Markdown

# kube-ingress-aws-controller
This tutorial describes how to use ExternalDNS with the [kube-ingress-aws-controller][1].
[1]: https://github.com/zalando-incubator/kube-ingress-aws-controller
## Setting up ExternalDNS and kube-ingress-aws-controller
Follow the [AWS tutorial](aws.md) to setup ExternalDNS for use in Kubernetes clusters
running in AWS. Specify the `source=ingress` argument so that ExternalDNS will look
for hostnames in Ingress objects. In addition, you may wish to limit which Ingress
objects are used as an ExternalDNS source via the `ingress-class` argument, but
this is not required.
For help setting up the Kubernetes Ingress AWS Controller, that can
create ALBs and NLBs, follow the [Setup Guide][2].
[2]: https://github.com/zalando-incubator/kube-ingress-aws-controller/tree/HEAD/deploy
### Optional RouteGroup
[RouteGroup][3] is a CRD, that enables you to do complex routing with
[Skipper][4].
First, you have to apply the RouteGroup CRD to your cluster:
```sh
kubectl apply -f https://github.com/zalando/skipper/blob/HEAD/dataclients/kubernetes/deploy/apply/routegroups_crd.yaml
```
You have to grant all controllers: [Skipper][4],
[kube-ingress-aws-controller][1] and external-dns to read the routegroup resource and
kube-ingress-aws-controller to update the status field of a routegroup.
This depends on your RBAC policies, in case you use RBAC, you can use
this for all 3 controllers:
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube-ingress-aws-controller
rules:
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses/status
verbs:
- patch
- update
- apiGroups:
- zalando.org
resources:
- routegroups
verbs:
- get
- list
- watch
- apiGroups:
- zalando.org
resources:
- routegroups/status
verbs:
- patch
- update
```
See also current RBAC yaml files:
- [kube-ingress-aws-controller](https://github.com/zalando-incubator/kubernetes-on-aws/blob/dev/cluster/manifests/ingress-controller/01-rbac.yaml)
- [skipper](https://github.com/zalando-incubator/kubernetes-on-aws/blob/dev/cluster/manifests/skipper/rbac.yaml)
- [external-dns](https://github.com/zalando-incubator/kubernetes-on-aws/blob/dev/cluster/manifests/external-dns/01-rbac.yaml)
[3]: https://opensource.zalando.com/skipper/kubernetes/routegroups/#routegroups
[4]: https://opensource.zalando.com/skipper
## Deploy an example application
Create the following sample "echoserver" application to demonstrate how
ExternalDNS works with ingress objects, that were created by [kube-ingress-aws-controller][1].
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
spec:
replicas: 1
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- image: gcr.io/google_containers/echoserver:1.4
imagePullPolicy: Always
name: echoserver
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: echoserver
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: ClusterIP
selector:
app: echoserver
```
Note that the Service object is of type `ClusterIP`, because we will
target [Skipper][4] and do the HTTP routing in Skipper. We don't need
a Service of type `LoadBalancer` here, since we will be using a shared
skipper-ingress for all Ingress. Skipper use `hostNetwork` to be able
to get traffic from AWS LoadBalancers EC2 network. ALBs or NLBs, will
be created based on need and will be shared across all ingress as
default.
## Ingress examples
Create the following Ingress to expose the echoserver application to the Internet.
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echoserver
spec:
ingressClassName: skipper
rules:
- host: echoserver.mycluster.example.org
http: &echoserver_root
paths:
- path: /
backend:
service:
name: echoserver
port:
number: 80
pathType: Prefix
- host: echoserver.example.org
http: *echoserver_root
```
The above should result in the creation of an (ipv4) ALB in AWS which will forward
traffic to skipper which will forward to the echoserver application.
If the `--source=ingress` argument is specified, then ExternalDNS will create
DNS records based on the hosts specified in ingress objects. The above example
would result in two alias records (A and AAAA) being created for each of the
domains: `echoserver.mycluster.example.org` and `echoserver.example.org`. All
four records alias the ALB that is associated with the Ingress object. As the
ALB is IPv4 only, the AAAA alias records have no effect.
If you would like ExternalDNS to not create AAAA records at all, you can add the
following command line parameter: `--exclude-record-types=AAAA`. Please be
aware, this will disable AAAA record creation even for dualstack enabled load
balancers.
Note that the above example makes use of the YAML anchor feature to avoid having
to repeat the http section for multiple hosts that use the exact same paths. If
this Ingress object will only be fronting one backend Service, we might instead
create the following:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: echoserver.mycluster.example.org, echoserver.example.org
name: echoserver
spec:
ingressClassName: skipper
rules:
- http:
paths:
- path: /
backend:
service:
name: echoserver
port:
number: 80
pathType: Prefix
```
In the above example we create a default path that works for any hostname, and
make use of the `external-dns.alpha.kubernetes.io/hostname` annotation to create
multiple aliases for the resulting ALB.
## NLBs
AWS has
[NLBs](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html)
and [kube-ingress-aws-controller][1] is able to create NLBs instead of ALBs.
The Kubernetes Ingress AWS controller supports the `zalando.org/aws-load-balancer-type`
annotation (which defaults to `alb`) to determine this. If this annotation is
set to `nlb` then ExternalDNS will create an NLB instead of an ALB.
Example:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
zalando.org/aws-load-balancer-type: nlb
name: echoserver
spec:
ingressClassName: skipper
rules:
- host: echoserver.example.org
http:
paths:
- path: /
backend:
service:
name: echoserver
port:
number: 80
pathType: Prefix
```
The above Ingress object will result in the creation of an NLB. A
successful create, you can observe in the ingress `status` field, that is
written by [kube-ingress-aws-controller][1]:
```yaml
status:
loadBalancer:
ingress:
- hostname: kube-ing-lb-atedkrlml7iu-1681027139.$region.elb.amazonaws.com
```
ExternalDNS will create A and AAAA alias records for: `echoserver.example.org`.
ExternalDNS will use these alias records to automatically maintain IP addresses
of the NLB.
## Dualstack Load Balancers
AWS [supports both IPv4 and "dualstack" (both IPv4 and IPv6) interfaces for ALBs][5]
and [NLBs][6]. The Kubernetes Ingress AWS controller supports the `alb.ingress.kubernetes.io/ip-address-type`
annotation (which defaults to `ipv4`) to determine this. ExternalDNS creates
both A and AAAA alias DNS records by default, regardless of this annotation.
It's possible to create only A records with the following command line
parameter: `--exclude-record-types=AAAA`
[5]: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#ip-address-type
[6]: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#ip-address-type
Example:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/ip-address-type: dualstack
name: echoserver
spec:
ingressClassName: skipper
rules:
- host: echoserver.example.org
http:
paths:
- path: /
backend:
service:
name: echoserver
port:
number: 80
pathType: Prefix
```
The above Ingress object will result in the creation of an ALB with a dualstack
interface.
## RouteGroup (optional)
[Kube-ingress-aws-controller][1], [Skipper][4] and external-dns
support [RouteGroups][3]. External-dns needs to be started with
`--source=skipper-routegroup` parameter in order to work on RouteGroup objects.
Here we can not show [all RouteGroup
capabilities](https://opensource.zalando.com/skipper/kubernetes/routegroups/),
but we show one simple example with an application and a custom https
redirect.
```yaml
apiVersion: zalando.org/v1
kind: RouteGroup
metadata:
name: my-route-group
spec:
backends:
- name: my-backend
type: service
serviceName: my-service
servicePort: 80
- name: redirectShunt
type: shunt
defaultBackends:
- backendName: my-service
routes:
- pathSubtree: /
- pathSubtree: /
predicates:
- Header("X-Forwarded-Proto", "http")
filters:
- redirectTo(302, "https:")
backends:
- redirectShunt
```