Kubernetes NetworkPolicies Blocking DNS

12/23/2020

I have an AKS cluster (Azure CNI) which I'm trying to implement NetworkPolicies on. I've created the network policy which is

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: myserver
spec:
  podSelector:
    matchLabels:
      service: my-server
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          service: myotherserver
    - podSelector:
        matchLabels:
          service: gateway
    - podSelector:
        matchLabels:
          service: yetanotherserver
    ports:
     - port: 8080
       protocol: TCP
  egress:
    - to:
      ports:
       - port: 53
         protocol: UDP
       - port: 53
         protocol: TCP
       - port: 5432
         protocol: TCP
       - port: 8080
         protocol: TCP

but when I apply the policy I'm seeing recurring messages that the host name cannot be resolved. I've installed dnsutils on the myserver pod; and can see the DNS requests are timing out; and I've also tried installing tcpdump on the same pod; and I can see requests going from myserver to kube-dns. I'm not seeing any responses coming back.

If I delete the networkpolicy DNS comes straight back; so I'm certain there's an issue with my networkpolicy but can't find a way to allow the DNS traffic. If anyone can shed any light on where I'm going wrong it would be greatly appreciated!

-- Mike1980
azure-aks
dns
kubernetes
kubernetes-networkpolicy

2 Answers

2/15/2022

Solution which does not require a name label to the target namespace. It's necessary to define a namespaceSelector as well as a podSelector. The default namespaceSelector will target the pod's own namespace.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-access
  namespace: <your-namespacename>
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

EDIT: Changed namespaceSelector to only target kube-system namespace based on the kubernetes.io/metadata.name label. This assumes you have automatic labeling enabled. https://kubernetes.io/docs/concepts/overview/_print/#automatic-labelling

If you don't have this feature enabled, the next best thing is to define an allow-all namespaceSelector along with the podSelector.

-- Magnus
Source: StackOverflow

12/23/2020

To avoid duplication create a separate network policy for opening up DNS traffic. First we label the kube-system namespace. Then allow DNS traffic from all pod to kube-system namespace.

kubectl label namespace kube-system name=kube-system

kubectl create -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-access
  namespace: <your-namespacename>
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: UDP
      port: 53

EOF
-- Arghya Sadhu
Source: StackOverflow