Fully qualified domain name (FQDN) for services in Kubernetes not working? DNS-1035

2/21/2019

I am following this concept guide on the kubernetes docs to connect to a service in a different namespace using the fully qualified domain name for the service.

service.yml

---
# declare front service
kind: Service
apiVersion: v1
metadata:
  name: traefik-frontend-service
  namespace: traefik
spec:
  selector:
    k8s-app: traefik-ingress-lb
    tier: reverse-proxy
  ports:
    - port: 80
      targetPort: 8080
  type: NodePort

ingress.yml

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-web-ui-ingress
  namespace: traefik
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.frontend.passHostHeader: "false"
    traefik.frontend.priority: "1"
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: traefik-frontend-service.traefik.svc.cluster.local
              servicePort: 80

But I keep getting this error:

The Ingress "traefik-web-ui-ingress" is invalid: spec.rules[0].http.backend.serviceName: Invalid value: "traefik-frontend-service.traefik.svc.cluster.local": a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is 'a-z?')

The service name of traefik-frontend-service.traefik.svc.cluster.local:

  • starts with an alphanumeric character
  • ends with an alphanumeric character
  • only contains alphanumeric numbers or -

Not sure what I'm doing wrong here... unless a new ingress has to be created for each namespace.

-- Clement
kubernetes

1 Answer

2/21/2019

This is by design to avoid cross-namespace exposure, In this thread is explained why this limitation on the ingress specification was intentional.

That means, the Ingress can only expose services within the same namespace.

The values provided should be the service name, not the FQDN.

If you really need to design this way, your other alternatives are:

  • Expose Traefik as a LB Service and then create a data service to provide the routing rules to traefik.
  • Use Contour Ingress (by heptio) to delegate the routing to other namespaces.

    Using Contour would be something like this:

    # root.ingressroute.yaml
    apiVersion: contour.heptio.com/v1beta1
    kind: IngressRoute
    metadata:
      name: namespace-delegation-root
      namespace: default
    spec:
      virtualhost:
        fqdn: ns-root.bar.com
      routes:
        - match: /
          services:
            - name: s1
              port: 80
    # delegate the subpath, `/blog` to the IngressRoute object in the marketing namespace with the name `blog`
        - match: /blog
          delegate:
            name: blog
            namespace: marketing
    ------------------------------------------------------------
    # blog.ingressroute.yaml
    apiVersion: contour.heptio.com/v1beta1
    kind: IngressRoute
    metadata:
      name: blog
      namespace: marketing
    spec:
      routes:
        - match: /blog
          services:
            - name: s2
              port: 80
-- Diego Mendes
Source: StackOverflow