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

Is it possible to use external-dns with a Traefik 2.0 IngressRoute resource? #1257

Closed
mojochao opened this issue Nov 4, 2019 · 20 comments
Closed

Comments

@mojochao
Copy link

mojochao commented Nov 4, 2019

I was able to use external-dns with AWS Route53 and EKS cluster with a Traefik 1.7 Ingress resource, but have been unable to achieve the same with the Traefik 2.0 IngressRoute resource. I have annotated my service to provide the hostname information.

  annotations:
    external-dns.alpha.kubernetes.io/hostname: my.awesome.domain.com

Of course, my.awesome.domain.com is not my real domain, but is unimportant.

Does external-dns require a Kubernetes Ingress? If not how might I get it to work with a new CRD type, such as the Traefik 2.0 IngressRoute?

Many thanks in advance!

@njuettner
Copy link
Member

Here are the sources which are currently supported:

service, ingress, node, fake, connector, istio-gateway, cloudfoundry, contour-ingressroute, crd, empty

You can enable multiple sources.

So it does not require Kubernetes Ingress, e.g. Service is also fine.

@soosap
Copy link

soosap commented Dec 14, 2019

Actually, I don't think this topic should be closed. According to the externalDNS documentation the following is stated on Service:

ServiceSource: collects all Services that have an external IP and returns them as Endpoint objects. The desired DNS name corresponds to an annotation set on the Service or is compiled from the Service attributes via the FQDN Go template string.

Which means that all the services that do not have an external-ip (when inspecting w/ kubectl get svc) will not be processed - whether or not they have a external-dns annotation.

The other option that we have is to use external dns custom resource. An example definition of that custom resource looks like this:

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
  name: examplednsrecord
spec:
  endpoints:
  - dnsName: foo.bar.com
    recordTTL: 180
    recordType: A
    targets:
    - 192.168.99.216

Here the problem would be to dynamically update the target. How can I point als these custom DNSEndpoint resources to the LoadBalancer type service that is placed in front of traefik? I am concluding for the moment that Traefik2 is incompatible with ExternalDNS. Is that a correct assumption? How could we approach this?

@brondum
Copy link

brondum commented Jan 13, 2020

Any updates on how the two could work together ?

@jimbocoder
Copy link

@brondum I have had success with the Traefik 2.1 and external-dns 1.16.0 just now, like so:

external-dns config (not sure if all these are necessary, included what I thought is relevant or helpful):

fqdnTemplates: ["{{.Name}}.mydomain.com"]
aws:
  preferCNAME: true
combineFQDNAnnotation: true
publishInternalServices: false
registry: txt
txtPrefix: "_."
logLevel: debug

My traefik service is named traefik, so the above results in an ALIAS record traefik.mydomain.com to the ELB in Route53.

Now an ExternalName service:

kind: Service
apiVersion: v1
metadata:
  name: mysite-external-name
  annotations:
    external-dns.alpha.kubernetes.io/hostname: www.mydomain.com
spec:
  type: ExternalName
  externalName: traefik.mydomain.com

This should result in a CNAME www.mydomain.com -> traefik.mydomain.com.

Of course you have to do the requisite IAM setup and other stuff mentioned in the docs, first. But I can confirm this is all working as expected. This is a bit of a workaround, but notice that no intelligence about IngressRoute is necessary for external-dns to cope with this need.

Hope that helps you and/or googlers, even if not directly answering your question.

@brondum
Copy link

brondum commented Feb 11, 2020

@jimbocoder Nice workaround, had not thought about using the ExternalName.
I will definitely try that one out :)

@wizbit
Copy link

wizbit commented May 14, 2020

Our workaround was to create an empty Ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mysite-external-name-dns
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
    - host: www.mydomain.com

@seh
Copy link
Contributor

seh commented Jun 26, 2020

Related: traefik/traefik#4655.

@dirien
Copy link

dirien commented Aug 7, 2020

the workaround from @wizbit is not working and the one from @jimbocoder neither (Azure DNS) i think that Traefik is not suitable for external dns atm

@sbellan
Copy link

sbellan commented Sep 21, 2020

In Traefik 2.2, the following works,
providers.kubernetesIngress.ingressEndpoint.publishedService=/<traefik_service>
When this option is added to traefik ingress controller, the field "status.loadBalancer.ingress" is populated correctly, making external-dns to use the appropriate EXTERNAL-IP in the DNS.

@dirien
Copy link

dirien commented Sep 21, 2020

@sbellan : Cool, i have to test this..

@sbellan
Copy link

sbellan commented Sep 21, 2020 via email

@surj-bains
Copy link

@sbellan do you have a gist or yaml you could share for both the external-dns config/helm values and the same for traefik?

@sbellan
Copy link

sbellan commented Oct 1, 2020

External DNS

apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: external-dns
rules:
  - apiGroups: ['']
    resources: ['endpoints', 'pods', 'services']
    verbs: ['get', 'watch', 'list']
  - apiGroups: ['extensions']
    resources: ['ingresses']
    verbs: ['get', 'watch', 'list']
  - apiGroups: ['']
    resources: ['nodes']
    verbs: ['list']
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: external-dns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
  - kind: ServiceAccount
    name: external-dns
    namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
        - name: external-dns
          image: k8s.gcr.io/external-dns/external-dns:v0.7.3
          args:
            - --source=service
            - --source=ingress
            - --registry=txt
            - --domain-filter=somedomain.com
            - --provider=aws
            - --aws-zone-type=public
            - --txt-owner-id=eks-dev

Deploy Traefik RBAC and Core in traefik namespace..

Traefik RBAC

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses/status
    verbs:
      - update

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
  - kind: ServiceAccount
    name: traefik-ingress-controller
    namespace: traefik

Traefik core

apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller

---

kind: Deployment
apiVersion: apps/v1
metadata:
  name: traefik
  labels:
    app: traefik

spec:
  replicas: 1
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      containers:
        - name: traefik
          image: traefik:v2.2
          args:
            - --log.level=DEBUG
            - --api
            - --api.insecure
            - --entrypoints.web.address=:80
            - --entrypoints.websecure.address=:443
            - --providers.kubernetesingress
            - --providers.kubernetesIngress.ingressEndpoint.publishedService=traefik/traefik
          ports:
            - name: web
              containerPort: 80
            - name: websecure
              containerPort: 443
            - name: admin
              containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: traefik
spec:
  type: LoadBalancer
  selector:
    app: traefik
  ports:
    - protocol: TCP
      port: 80
      name: web
      targetPort: 80
    - protocol: TCP
      port: 443
      name: websecure
      targetPort: 443
    - protocol: TCP
      port: 8080
      name: admin
      targetPort: 8080

Sample Ingress

kind: Ingress
apiVersion: networking.k8s.io/v1beta1
metadata:
  name: myingress
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls: "true"

spec:
  rules:
    - host: example.eks4.somedomain.com
      http:
        paths:
          - path: /bar
            backend:
              serviceName: whoami
              servicePort: 80
          - path: /foo
            backend:
              serviceName: whoami
              servicePort: 80
  tls:
  - secretName: example.eks4.somedomain.com-cert

Certificate

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: example.eks4.somedomain.com-cert
spec:
  commonName: example.eks4.somedomain.com
  dnsNames:
  - example.eks4.somedomain.com
  secretName: example.eks4.somedomain.com-cert
  issuerRef:
    name: cert-manager
    kind: ClusterIssuer
    group: cert-manager.io

@voidengineer
Copy link

@sbellan Your solution is about Kubernetes ingress, not about Traefik IngressRoute (as stated in the title).

@arctica
Copy link

arctica commented Nov 28, 2020

I've noticed using a NodePort service makes external-dns populate the DNS records with the external IPs of Traefik which we expose directly via HostPort. This wastes a random port but at least the setup works. It would be great if external-dns was able to expose the external IPs of nodes where pods are using HostPort. The solution in the tutorials with a headless service resulted in internal IPs being used which for external dns seems wrong.

@kien-eng
Copy link

I've noticed using a NodePort service makes external-dns populate the DNS records with the external IPs of Traefik which we expose directly via HostPort. This wastes a random port but at least the setup works. It would be great if external-dns was able to expose the external IPs of nodes where pods are using HostPort. The solution in the tutorials with a headless service resulted in internal IPs being used which for external dns seems wrong.

@arctica can you help to show us what you've done with nodeport? Thanks

@anthr76
Copy link

anthr76 commented Jan 12, 2021

Has there been any updates to support IngressRoute CRD?

@arctica
Copy link

arctica commented Jan 12, 2021

@arctica can you help to show us what you've done with nodeport? Thanks

Nothing fancy, In my traefik-values.yml (using the traefik helm chart) I have the following:

service:
  enabled: true
  type: NodePort
  annotations:
    external-dns.alpha.kubernetes.io/hostname: traefik.example.com
    external-dns.alpha.kubernetes.io/ttl: "120"
  spec:
    externalTrafficPolicy: Local

@borchero
Copy link

I built Switchboard to solve this issue: it is a Kubernetes operator which watches all IngressRoute objects in your cluster and generates DNSEndpoint (an external-dns CRD) resources as required.

@dewet22
Copy link

dewet22 commented Apr 20, 2023

@borchero this is amazing, thanks for solving this for my use case!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests