Introduction
Inside Kubernetes, by default, every pod or service can talk to each other. This creates a security problem if the frontend gets connected to the database.
So, we need to apply some kind of rule so that we can control which resource can connect to which one. This traffic can be egress (outgoing from the pod) or ingress (incoming to the pod).
These things will be defined in the network policy file, and we will apply that in the cluster.
Here is a sample network policy file, which will restrict the frontend from connecting with the DB, and only the backend can do that.
This one is with incoming or Ingress
where the backend pod is labeled as role=backend, and it will connect only on port 3306.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-backend
spec:
podSelector:
matchLabels:
name: mysql
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: backend
ports:
- port: 3306This one with Egress
Here, for example, DB can only connect to the backend, but incoming traffic is allowed for all.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-backend
spec:
podSelector:
matchLabels:
name: mysql
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
role: backendComplete setup
This is the complete file with ingress and egress applied.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-backend
spec:
podSelector:
matchLabels:
name: mysql
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: backend
ports:
- protocol: TCP
port: 3306
egress:
- to:
- podSelector:
matchLabels:
role: backendNow if you want to use IP instead of pod and service labels, here is an example for that.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-backend
spec:
podSelector:
matchLabels:
name: mysql
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 10.10.20.15/32
ports:
- protocol: TCP
port: 3306
egress:
- to:
- ipBlock:
cidr: 10.10.20.15/32Now if you want to restrict a whole namespace. Here only the namespace payments can connect to DB.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-payments-to-mysql
namespace: default
spec:
podSelector:
matchLabels:
name: mysql
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
team: payments
ports:
- protocol: TCP
port: 3306Remember while applying any egress rule, By default, pods can access everything, including the DNS server in your cluster.
When you define an egress NetworkPolicy, Kubernetes applies default deny for egress to the pods it selects. This means all outgoing traffic is blocked, including traffic to the DNS server. So after applying a restrictive egress policy, pods can no longer resolve domain names.
So you need to apply this complete file which will not block the DNS.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-backend-with-dns
namespace: default
spec:
podSelector:
matchLabels:
name: mysql
policyTypes:
- Ingress
- Egress
# Ingress: only backend pods can connect
ingress:
- from:
- podSelector:
matchLabels:
role: backend
ports:
- protocol: TCP
port: 3306
# Egress: only backend pods + DNS
egress:
# Allow egress to backend pods
- to:
- podSelector:
matchLabels:
role: backend
# Allow DNS traffic to kube-dns in kube-system
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53One more thing is there, not all CNIs supports this network policy. The kind-net CNI which comes by default with the kind and minikube cluster and Flannel does not support this. These some of the open-source CNI which supports Network Policy.
- Calico
- Cillium
- Kube-router
- Weave-Net
- Romana