Shashikant shah

Wednesday, 26 February 2025

Network Policy in Kubernetes.

 Network Policy :-


Network Policy in Kubernetes is a specification that defines how groups of pods are allowed to communicate with each other and other network endpoints. It acts as a firewall for your Kubernetes cluster, controlling traffic at the IP address or port level (OSI layer 3 or 4). Network Policies require a compatible CNI (Container Network Interface) plugin that supports the Network Policy API such as Calico, Cilium, or Weave Net.

Flannel does not support network policy.

Ingress: incoming

Egress: outgoing

features of Network Policies:

  • They are namespace-scoped.
  • They use labels to select pods and define rules for ingress (incoming) and egress (outgoing) traffic.
  • If no Network Policy is applied to a pod, it allows all traffic by default.(depending on the network plugin configuration).

 1. podSelector (Target Pods)

  • Defines which Pods the policy applies to.
  • Uses labels to select Pods.

Example: Apply policy to all Pods with app: backend

podSelector:

  matchLabels:

    app: backend

 If empty ({}), it applies to all Pods in the namespace.

2. policyTypes (Traffic Direction)

  • Defines whether the policy controls Ingress (incoming) or Egress (outgoing) traffic.
  • Can have:
    • Ingress → Controls incoming traffic.
    • Egress → Controls outgoing traffic.
    • Both.

Example: Apply only to incoming traffic

policyTypes:

  - Ingress

3. ingress (Allowed Incoming Traffic)

  • Defines which sources can send traffic to the selected Pods.
  • Uses from field with:
    • podSelector (Allow specific Pods)
    • namespaceSelector (Allow Pods from specific namespaces)
    • ipBlock (Allow specific IP ranges)

Example: Allow traffic only from Pods with app: frontend

ingress:

  - from:

      - podSelector:

          matchLabels:

            app: frontend

4. egress (Allowed Outgoing Traffic)

  • Defines which destinations the selected Pods can talk to.
  • Uses to field with:
    • podSelector (Allow traffic to specific Pods)
    • namespaceSelector (Allow traffic to specific namespaces)
    • ipBlock (Allow traffic to specific IPs)

Example: Allow outgoing traffic only to app: database Pods

egress:

  - to:

      - podSelector:

          matchLabels:

            app: database

5. ports (Restrict by Port & Protocol)

  • Defines specific ports that are allowed.
  • Supports:
    • protocol: TCP/UDP
    • port: <port_number>

Example: Allow only HTTP (port 80) traffic

ingress:

  - from:

      - podSelector:

          matchLabels:

            app: frontend

    ports:

      - protocol: TCP

        port: 80

 6. namespaceSelector (Restrict by Namespace)

  • Allows traffic only from specific namespaces.

Example: Allow traffic from trusted namespace

ingress:

  - from:

      - namespaceSelector:

          matchLabels:

            security: trusted

 7. ipBlock (Restrict by IP Range)

  • Allows or denies traffic based on CIDR IP ranges.
  • Does not work with Pod IPs (only external networks).

Example: Allow only 192.168.1.0/24

ingress:

  - from:

      - ipBlock:

          cidr: 192.168.1.0/24


Parameter

Purpose

Example

podSelector

Select which Pods the policy applies to

matchLabels: {app: backend}

policyTypes

Control Ingress and/or Egress

policyTypes: [Ingress, Egress]

Ingress

Define allowed incoming traffic at pods, namespace, IPBlock.

from: {podSelector: {app: frontend}}

Egress

Define allowed outgoing traffic at pods, namespace, IPBlock.

to: {podSelector: {app: database}}

Ports

Restrict by port & protocol

port: 80, protocol: TCP

namespaceSelector

Allow traffic only from specific namespaces

namespaceSelector: {security: trusted}

ipBlock

Restrict by IP range (CIDR)

cidr: 192.168.1.0/24


Scenarios for Network Policy in Kubernetes.

Here are some common scenarios where Network Policies are used:

Isolate Pods in a Namespace:

o   Only frontend pods can communicate with backend pods.

o   All other traffic to backend pods is blocked.

o   Allow Traffic Based on Pod Labels. Example: Allow only pods with the label role: frontend to communicate with pods labeled role: backend. 


i)Deploy the Applications

Create two deployments: frontend and backend.

# vim backend-deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: backend

  namespace: isolate-ns

  labels:

    app: backend

spec:

  replicas: 1

  selector:

    matchLabels:

      app: backend

  template:

    metadata:

      labels:

        app: backend

    spec:

      containers:

      - name: nginx

        image: nginx

        ports:

        - containerPort: 80


# vim frontend-deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: frontend

  namespace: isolate-ns

  labels:

    app: frontend

spec:

  replicas: 1

  selector:

    matchLabels:

      app: frontend

  template:

    metadata:

      labels:

        app: frontend

    spec:

      containers:

      - name: busybox

        image: nginx

        command: ["sleep", "3600"]

 

# kubectl apply -f backend-deployment.yaml

# kubectl apply -f frontend-deployment.yaml

 

Verify Pod Communication

# kubectl get pods  -n isolate-ns




 

# cat service.yaml

apiVersion: v1

kind: Service

metadata:

  name: backend-service

  namespace: isolate-ns

spec:

  selector:

    app: backend

  ports:

    - protocol: TCP

      port: 80      # Service Port

      targetPort: 80  # Container Port

  type: ClusterIP  # Change to NodePort or LoadBalancer if needed

 

# kubectl get svc -n isolate-ns



 

# vim backend-policy.yaml

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: backend-policy

  namespace: isolate-ns

spec:

  podSelector:

    matchLabels:

      app: backend

  policyTypes:

    - Ingress

  ingress:

    - from:

        - podSelector:

            matchLabels:

              app: frontend

      ports:

        - protocol: TCP

          port: 80

# kubectl apply -f backend-policy.yaml

# kubectl get networkpolicies -n isolate-ns




# kubectl describe networkpolicies -n isolate-ns



 





Verify connectivity :-

# kubectl get all -n isolate-ns







Nginx not connect from test-pod.

# kubectl get svc -n isolate-ns




# kubectl run test-pod --image=nginx --restart=Never -- sleep 3600

# kubectl exec -it test-pod  -- /bin/bash





The frontend pod will only connect to the Nginx backend pod.

# kubectl exec -it --namespace=isolate-ns frontend-7766f6c5f8-k8m2l -- curl 10.99.1.82:80








# kubectl exec -it --namespace=isolate-ns frontend-9585465bd-rz4q5 -- curl backend-service:80



 





Allow Traffic from Specific Namespaces:

 

o   Permit traffic from pods in one namespace to pods in another namespace.

o   Example: Allow monitoring tools in the monitoring namespace to scrape metrics from pods in the app namespace.


# kubectl create namespace frontend-ns

# kubectl create namespace backend-ns

# kubectl get ns backend-ns frontend-ns



Deploy Applications

# cat backend-deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: backend

  namespace: backend-ns

  labels:

    app: backend

spec:

  replicas: 2

  selector:

    matchLabels:

      app: backend

  template:

    metadata:

      labels:

        app: backend

    spec:

      containers:

      - name: nginx

        image: nginx

        ports:

        - containerPort: 80

# kubectl apply -f backend-deployment.yaml

# kubectl get pods -n backend-ns



Deploy Service.

# vim backend-service.yaml

apiVersion: v1

kind: Service

metadata:

  name: backend-service

  namespace: backend-ns

spec:

  selector:

    app: backend

  ports:

    - protocol: TCP

      port: 80

      targetPort: 80

# kubectl apply -f backend-service.yaml

# kubectl get svc -n backend-ns



 


# cat frontend-deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: frontend

  namespace: frontend-ns

  labels:

    app: frontend

spec:

  replicas: 1

  selector:

    matchLabels:

      app: frontend

  template:

    metadata:

      labels:

        app: frontend

    spec:

      containers:

      - name: busybox

        image: nginx

        command: ["sleep", "3600"]


# backend-policy.yaml

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: backend-policy

  namespace: backend

spec:

  podSelector:

    matchLabels:

      app: backend

  policyTypes:

    - Ingress

  ingress:

    - from:

        - namespaceSelector:

            matchLabels:

              kubernetes.io/metadata.name: frontend-ns

      ports:

        - protocol: TCP

          port: 80

# kubectl apply -f backend-policy.yaml

# kubectl describe networkpolicies -n backend-ns










5. Test the Network Policy

Allowed Traffic:

  • Exec into the frontend pod and test connectivity to the backend pod:





# kubectl exec -it -n frontend-ns frontend-9585465bd-qp4d4 -- curl 10.109.247.255:80



 





Blocked Traffic:

  • Create a new pod in a different namespace (e.g., dev) and try to access the backend pod:

# kubectl run test-pod -n dev --image=nginx --restart=Never -- sleep 3600

# kubectl exec -it test-pod -n dev -- /bin/bash



 


3.Disable internet access for Kubernetes pods.


Network Policies to block all egress traffic to external IPs. This ensures that pods can only communicate within the cluster or with explicitly allowed external endpoints.

# busybox-deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: busybox

spec:

  replicas: 1

  selector:

    matchLabels:

      app: busybox

  template:

    metadata:

      labels:

        app: busybox

    spec:

      containers:

      - name: busybox

        image: busybox

        command: ["sleep", "3600"]

# kubectl get pods





Without network policy,

# kubectl exec -it busybox-6fc6c44c5b-k2qxp -- ping google.com



 


 Create a Network Policy to Disable Internet Access

# cat disable-internet-policy.yaml

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: disable-internet

spec:

  podSelector: {} # Applies to all pods in the namespace

  policyTypes:

    - Egress

  egress:

    - to:

        - ipBlock:

            cidr: 0.0.0.0/0

            except:

              - 10.0.0.0/8 # Allow internal cluster traffic (replace with your cluster's CIDR)

              - 172.16.0.0/12

              - 192.168.0.0/16

 

# kubectl get netpol

# kubectl describe netpol disable-internet



 








# kubectl exec -it busybox-6fc6c44c5b-k2qxp -- ping google.com



 

Note :- Only the default namespace will not run on the internet and other namespaces will run on the internet.