Exposing ports 53/udp and 53/tcp does not work as expected

Hi! I'm trying to get pihole working as a DNS server on port 53/udp and 53/tcp in K3s and got stuck with the following problem regarding traefik.

To isolate the problem, instead of using the pihole image, I used one that contains a simple UDP echo server to test the connection.

First the setup where the DNS requests work via udp:
Here is my echo server:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: udplog
  labels:
    app: udplog
spec:
  replicas: 1
  selector:
    matchLabels:
      app: udplog
  template:
    metadata:
      labels:
        app: udplog
    spec:
      containers:
      - name: udplog
        image: mendhak/udp-listener
        env:
        - name: UDPPORT
          value: "53"
        ports:
        - containerPort: 53
          protocol: UDP

And here is my service:

apiVersion: v1
kind: Service
metadata:
  name: udplog-service
spec:
  selector:
    app: udplog
  ports:
  - port: 53
    protocol: UDP

The udp port is exposed with this HelmChartConfig:

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
    - "--entryPoints.dnsudp.address=:53/udp"
    ports:
      dnsudp:
        port: 53
        exposedPort: 53
        expose: true
        protocol: UDP

And here the IngressRouteUDP:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteUDP
metadata:
  name: udplog-ingressroute-udp
spec:
  entryPoints:
  - dnsudp
  routes:
  - services:
    - name: udplog-service
      port: 53

When I try to resolve a domain name, I see the requests in the log of the echo server. So far so good. But I also want to enable port 53/tcp:

I change the HelmChartConfig as follows to also expose port 53/tcp. But already after enabling these changes the communication via udp does not work anymore.

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
    - "--entryPoints.dnsudp.address=:53/udp"
    - "--entryPoints.dnstcp.address=:53/tcp"
    ports:
      dnsudp:
        port: 53
        exposedPort: 53
        expose: true
        protocol: UDP
      dnstcp:
        port: 53
        exposedPort: 53
        expose: true
        protocol: TCP

What am I doing wrong?

Hey @Hypertrophy,

I started running into a similar situation when trying to configure this out in k3s on my homelab cluster and I think it sounds like it might be a similar issue.

I ended up finding this post here: How a Kubernetes bug won't let you expose a service over TCP and UDP on a same port - ben's lab which mentions that after creating a deployment that exposes a port number with a given protocol it'll only create the port with that protocol until the deployment is deleted and reapplied with BOTH ports specified right away. Can't have it specified as UDP and then add in the TCP port configuration at a later point. Have to do it at the same time you create the deployment.

For me since I am using the traefik instance installed with k3s I did the following:

helm delete traefik -n kube-system
systemctl restart k3s

# Then I edited one of the traefik config files in /var/lib/rancher/k3s/server/manifests directory

After editing the traefik config file the helm installer job gets kicked off and it should facilitate recreating the deployment and at that point both of my ports are open now.

1 Like