borchero / switchboard

Kubernetes Operator for Automatically Issuing DNS Records and TLS Certificates for Traefik Ingress Routes.
MIT License
155 stars 15 forks source link

Multiple target services for External DNS #118

Open AmilcarM11 opened 1 year ago

AmilcarM11 commented 1 year ago

Currently switchboard only allows selecting one Traefik target service for external-dns integration. This works great when there is a single LoadBalancer-type service for Traefik.

I have recently found a use-case where I need to have two LoadBalancer-type services for the same Traefik deployment:

This way I can expose webhooks to the internet, while keeping the rest of my API private. This is particularly useful for pre-production environments that require callbacks from external services. But this feature would also be helpful if there were multiple Traefik instances deployed on the same cluster.

Could there by a way to register more than one target service, and then select the desired one with an annotation on the IngressRoute object, so that the correct IP is used for the generated DNSEndpoint? For backwards compatibility, there could be a way to set the default target.

Let me know what you think!

borchero commented 1 year ago

The easiest way to achieve this with the current version of Switchboard is to run two instances of Switchboard that target the different Traefik instances.

These two Switchboard instances can already select ingresses based on the value of the kubernetes.io/ingress.class annotation.

Since I think that Switchboard is pretty lightweight, I would rather recommend to run two instances than to increase its complexity :eyes:

KrisM4c commented 2 weeks ago

So just doing some testing on this, and in general this would work if you had multiple individual load balancers, however a bit of an edge case (and ones that we are testing) is having a single load balancer with multiple services pointed to it.

For example, you have 1 service annotated to be an ext-lb, and one to be an int-lb.

In testing, what we saw was it did pick up the new ingressroute (we are using Traefik), and the DNS endpoint was created, and on the external-dns values, it was specified to point to the int-lb service, yet the DNS endpoint still assigned it the IP of the ext-lb and created the DNS record with that in the DNS zone.

Values below:

External

cert-manager:
  install: true
  installCRDs: false
certificateIssuer:
  create: true
  email: admin@example.com
  solvers:
  - dns01:
      cloudDNS:
        project: project-1
        serviceAccountSecretRef:
          key: dns-creds
          name: dns-creds
external-dns:
  crd:
    create: true
  domainFilters:
  - external.example.com
  google:
    project: project-1
    serviceAccountSecret: dns-creds
    serviceAccountSecretKey: dns-creds
    zoneVisibility: public
  install: true
  provider: google
  sources:
  - crd
  - service
  - ingress
image:
  name: ghcr.io/borchero/switchboard
integrations:
  certManager:
    certificateTemplate:
      spec:
        duration: 2160h
        issuerRef:
          kind: ClusterIssuer
          name: switchboard-letsencrypt-issuer
        renewBefore: 360h
    enabled: true
    extraArgs:
    - --dns01-recursive-nameservers-only=true
  externalDNS:
    enabled: true
    targetService:
      name: traefik-ext-lb
      namespace: traefik-controller
metrics:
  enabled: true
  port: 9090
podAnnotations: {}
replicas: 1
resources:
  limits:
    cpu: 50m
    memory: 40Mi
  requests:
    cpu: 5m
    memory: 25Mi

Internal

cert-manager:
  install: true
  installCRDs: false
certificateIssuer:
  create: true
  email: admin@example.com
  solvers:
  - dns01:
      cloudDNS:
        project: project-1
        serviceAccountSecretRef:
          key: dns-creds
          name: dns-creds
external-dns:
  crd:
    create: false
  domainFilters:
  - internal.example.com
  google:
    project: project-1
    serviceAccountSecret: dns-creds
    serviceAccountSecretKey: dns-creds
    zoneVisibility: private
  install: true
  provider: google
  sources:
  - crd
  - service
  - ingress
image:
  name: ghcr.io/borchero/switchboard
integrations:
  certManager:
    certificateTemplate:
      spec:
        duration: 2160h
        issuerRef:
          kind: ClusterIssuer
          name: switchboard-letsencrypt-issuer
        renewBefore: 360h
    enabled: true
    extraArgs:
    - --dns01-recursive-nameservers-only=true
  externalDNS:
    enabled: true
    targetService:
      name: traefik-int-lb
      namespace: traefik-controller
metrics:
  enabled: true
  port: 9090
podAnnotations: {}
replicas: 1
resources:
  limits:
    cpu: 50m
    memory: 40Mi
  requests:
    cpu: 5m
    memory: 25Mi

Not sure if there would be any other way around getting this to work.