Skip to content

A service to advertise records for Kubernetes resources on a LAN over multicast DNS.

License

Notifications You must be signed in to change notification settings

blake/external-mdns

Repository files navigation

External-mDNS

External-mDNS advertises exposed Kubernetes Services and Ingresses addresses on a LAN using multicast DNS (RFC 6762).

It is based on https://github.com/flix-tech/k8s-mdns/ and heavily inspired by External DNS.

What It Does

External-mDNS makes Kubernetes resources discoverable on a local network via multicast DNS without the need for a separate DNS server. It retrieves a list of resources (Services and Ingresses) from Kubernetes and serves the record to local clients via multicast DNS.

Hostnames associated with Ingress resources, or exposed services of type LoadBalancer, will be advertised on the local network.

By default External-mDNS will advertise hostnames for exposed resources in all namespaces. Use the -namespace flag to restrict advertisement to a single namespace, or -without-namespace=true for all namespaces.

DNS records are advertised with the format <hostname/service_name>.<namespace>.local. In addition, hostnames for resources in the -default-namespace will also be advertised with a short name of <hostname/service_name>.local.

Deploying External-mDNS

External-mDNS is configured using argument flags. Most flags can be replaced with environment variables. For instance, --record-ttl could be replaced with EXTERNAL_MDNS_RECORD_TTL=60, or --namespace kube-system could be replaced with EXTERNAL_MDNS_NAMESPACE=kube-system.

Manifest (without RBAC)

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-mdns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-mdns
  template:
    metadata:
      labels:
        app: external-mdns
    spec:
      securityContext:
        runAsUser: 65534
        runAsGroup: 65534
        runAsNonRoot: true
      hostNetwork: true
      serviceAccountName: external-mdns
      containers:
      - name: external-mdns
        securityContext:
          readOnlyRootFilesystem: true
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        image: blakec/external-mdns:latest
        args:
        - -source=ingress
        - -source=service

Manifest (with RBAC)

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-mdns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: external-mdns
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["list", "watch"]
- apiGroups: ["extensions","networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
 name: external-mdns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-mdns
subjects:
- kind: ServiceAccount
  name: external-mdns
  namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-mdns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-mdns
  template:
    metadata:
      labels:
        app: external-mdns
    spec:
      securityContext:
        runAsUser: 65534
        runAsGroup: 65534
        runAsNonRoot: true
      hostNetwork: true
      serviceAccountName: external-mdns
      containers:
      - name: external-mdns
        securityContext:
          readOnlyRootFilesystem: true
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        image: blakec/external-mdns:latest
        args:
        - -source=ingress
        - -source=service

Deploy External-mDNS using kubectl apply --filename external-mdns.yaml.

Check that External-mDNS has created the desired DNS records for your advertised services, and that it points to its load balancer's IP.

Test that the record is resolvable from the local LAN using the appropriate command for your operating system.

BSD/macOS

$ dns-sd -Q example.local a in
DATE: ---Sun 16 Aug 2020---
22:50:37.797  ...STARTING...
Timestamp     A/R    Flags if Name                          Type  Class   Rdata
22:50:37.959  Add        2  4 example.local.                Addr   IN     192.0.2.10

Linux

$ getent hosts example.local
192.0.2.10      example.local

Or, resolve the hostname using Avahi.

$ avahi-resolve-address -4 --name example.local
example.local 192.0.2.10

Note about Linux DNS lookups:

If /etc/nsswitch.conf is configured to use the mdns4_minimal module, libnss-mdns will reject the request if the request has more than two labels. Example: example.default.local is rejected.

In order to resolve hostnames that are published from non-default Kubernetes namespaces, modify /etc/nsswitch.conf and replace mdns4_minimal with mdns4. Also, create the file /etc/mdns.allow and insert the following contents.

# /etc/mdns.allow
.local.
.local

Hostnames with more than two labels should now be resolvable.

$ getent hosts example.default.local
192.0.2.10      example.default.local

About

A service to advertise records for Kubernetes resources on a LAN over multicast DNS.

Topics

Resources

License

Stars

Watchers

Forks