A rule lists peers and ports. A peer is a podSelector (Pods in this namespace), a namespaceSelector, both in one entry (matching Pods in matching namespaces), or an ipBlock (CIDR ranges). Traffic must be allowed at both ends, egress from the client and ingress to the server:
kubectl apply -f - <<'EOF' >/dev/null
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: allow-dns }
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to: [{ namespaceSelector: {}, podSelector: { matchLabels: { k8s-app: kube-dns } } }]
ports: [{ protocol: UDP, port: 53 }, { protocol: TCP, port: 53 }]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: client-to-server }
spec:
podSelector: { matchLabels: { role: client } }
policyTypes: [Egress]
egress: [{ to: [{ podSelector: { matchLabels: { app: server } } }], ports: [{ port: 80 }] }]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: server-from-client }
spec:
podSelector: { matchLabels: { app: server } }
policyTypes: [Ingress]
ingress:
- from: [{ podSelector: { matchLabels: { role: client } } }]
ports: [{ port: 80 }]
EOF
probe
kubectl run stranger --image=localhost:33500/booknest-web:1.3 >/dev/null
kubectl wait --for=condition=Ready pod/stranger >/dev/null && probe stranger
kubectl config set-context --current --namespace=booknest >/dev/null
kubectl delete namespace netpol-demo --wait=false >/dev/nullOutput
ok wget: download timed out
The labeled client gets through; an unlabeled Pod times out. Mind the classic trap in the DNS rule: its two selectors share one list entry, so both must match. As two entries they would be alternatives, and namespaceSelector: {} alone would open egress to every Pod in the cluster.