Sure shot question 9: Securing Database Pods in Kubernetes: Restricting Access Between Namespaces

Question format

 

You have a Kubernetes cluster and running pods in multiple namespaces, The security team has mandated that the db pods on Project-a namespace only accessible from the service pods that are running in Project-b namespace.

 

Prerequisites

A Kubernetes cluster with a CNI plugin that supports Network Policies (e.g., Calico, Cilium, or Weave Net).

kubectl configured to interact with the cluster.

Existing namespaces project-a (for databases) and project-b (for services).

Step 1: Label the Namespaces

Add labels to the namespaces to simplify targeting in policies.

Label the project-b namespace:

kubectl label namespace project-b project=project-b

Verify labels:

kubectl get namespaces --show-labels

 

Step 2: Identify Pod Labels

 

Ensure your pods have labels for identification.

Database Pods in project-a:

Example label: app=db (e.g., add via kubectl label pod <db-pod> app=db -n project-a).

Service Pods in project-b:

Example label: app=service (e.g., add via kubectl label pod <service-pod> app=service -n project-b).

 

Step 3: Create a Network Policy

Create a policy to restrict traffic to the db pods in project-a only from project-b service pods.

Create a file named db-access-policy.yaml:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: allow-project-b-to-db
 namespace: project-a  # Applies to the database pods in project-a
spec:
 podSelector:
   matchLabels:
     app: db  # Targets pods labeled "app=db"
 policyTypes:
   - Ingress  # Controls incoming traffic
 ingress:
   - from:
       - namespaceSelector:  # Restrict to namespaces labeled "project=project-b"
           matchLabels:
             project: project-b
         podSelector:  # Restrict to pods labeled "app=service"
           matchLabels:
             app: service
     ports:  # Specify the database port (e.g., 3306 for MySQL)
       - protocol: TCP
         port: 3306

Replace port: 3306 with your database’s actual port.

Apply the policy:

kubectl apply -f db-access-policy.yaml

 

Step 4: Verify the Network Policy

Check the policy status:

kubectl -n project-a get networkpolicies

Test connectivity:

From project-b service pod (should succeed):

kubectl -n project-b exec -it <service-pod> -- curl http://db.project-a.svc.cluster.local:3306

From pods in other namespaces (should fail):

kubectl -n default exec -it <other-pod> -- curl http://db.project-a.svc.cluster.local:3306

 

How It Works

 

podSelector: Selects pods in project-a with the label app=db.

namespaceSelector: Restricts traffic to pods from namespaces labeled project=project-b.

podSelector (inside from): Further restricts traffic to pods labeled app=service in project-b.

Default Deny: All other ingress traffic to db pods is blocked.

 

Troubleshooting

 

Pods Can’t Communicate:

Ensure the CNI plugin supports Network Policies.

Verify pod and namespace labels match the policy.

Check for conflicting policies (kubectl get networkpolicies -A).

Port Mismatch:

Ensure the port in the policy matches the database pod’s listening port.