netscaler / netscaler-k8s-ingress-controller

NetScaler Ingress Controller for Kubernetes:
https://developer-docs.citrix.com/projects/citrix-k8s-ingress-controller/en/latest/
308 stars 91 forks source link

Support AAAA DNS records for Ingress resources #614

Open lbaker-esnet opened 11 months ago

lbaker-esnet commented 11 months ago

Is your feature request related to a problem? Please describe. The "dns-hostname" annotation appears to only work for services that utilize IPv4 addresses. However, when I attempt to use this feature with an IPv6 based service, the nitroapi interface returns an error and does not create a DNS entry.

For example, given the following service (note, demonstration addresses and domains are used for this issue):

apiVersion: v1
kind: Service
metadata:
  name: lbexample
  annotations:
    service.citrix.com/dns-hostname: "service.example.com"
  labels:
    name: lbexample
spec:
  externalTrafficPolicy: Local
  loadBalancerIP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
  type: LoadBalancer
  ipFamilyPolicy: PreferDualStack
  ipFamilies:
  - IPv6
  - IPv4
  selector:
    app: lbexample
  ports:
  - name: http
    port: 80
    targetPort: http

The citrix-ingress-controller pod logs the following:

2023-10-19 20:22:25,638  - INFO - [kubernetes.py:kubernetes_service_to_nsapps:3200] (MainThread) Adding DNS entry {'service.example.com'}/2001:0db8:85a3:0000:0000:8a2e:0370:7334
2023-10-19 20:22:25,720  - WARNING - [nitrointerface.py:add_dns_entry:4468] (MainThread) Failed to add DNS entry. Exception: (1110, 'Invalid IP address [2001:0db8:85a3:0000:0000:8a2e:0370:7334]', 'ERROR')

Describe the solution you'd like If possible, update the check_n_add_dns_entries to determine if the IP is IPv6.

If the address is IPv6, call add_dns_aaaa_entry which will invoke an IPv6 version of dnsaddrec.py

    def check_n_add_dns_entries(self, hostnames, ip):
        """
        This method checks the existing configuration and applies diff.
        Precondition: ip must be valid
        """
        if not hostnames:
            logger.debug("Skipping as there is no DNS entry to process")
            return
        configured_hostnames = self.get_configured_hostnames(ip)
        given_hostnames = hostnames
        to_add_hostnames = given_hostnames - configured_hostnames
        logger.debug("Started processing {} DNS entry addition".format(len(to_add_hostnames)))
        for hostname in to_add_hostnames:
            if hostname.startswith('*'):
                logger.warning("Wildcard domain names should be added through wildcarddnsentries CRD only. Ignoring the host {} "
                               "to be added to address records through ingress".format(hostname))
                continue
            # proposed #
            if is_ipv6(ip):
                self.add_dns_aaaa_entry(hostname, ip)
            else:
                self.add_dns_entry(hostname, ip)
            # end_proposed #
        logger.debug("Finished processing DNS entry addition")

def is_ipv6(ip):
    is_v6 = False
    try:
        parsed_ip = ipaddress.ip_address(ip)
        if isinstance(parsed_ip, ipaddress.IPv6Address):
            is_v6 = True
        return is_v6
    except ValueError:
        return "Invalid IP Address"

Describe alternatives you've considered Manually create AAAA records.

Additional context It does appear that the nitroapi supports IPv6 record additions (api reference).