Implement Kubernetes network policies with Calico for microsegmentation

Advanced 45 min Apr 23, 2026
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure Calico CNI to enforce network policies for pod-to-pod traffic control and namespace isolation. This tutorial covers advanced microsegmentation patterns, ingress/egress rules, and policy monitoring for production Kubernetes security.

Prerequisites

  • Kubernetes cluster with administrative access
  • kubectl configured and working
  • Internet connectivity for downloading Calico manifests

What this solves

Kubernetes network policies with Calico provide fine-grained traffic control between pods and namespaces. This enables zero-trust networking where you explicitly allow required communications while blocking everything else by default. You need this for compliance requirements, multi-tenant clusters, or any production environment where workloads should be isolated from each other.

Step-by-step installation

Install Calico CNI with network policy support

Install Calico as the primary CNI plugin for your Kubernetes cluster with policy enforcement enabled.

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/custom-resources.yaml

Verify Calico installation

Check that all Calico components are running and network policies are supported.

kubectl get pods -n calico-system
kubectl get nodes -o wide
kubectl get crd | grep calico

Install calicoctl for policy management

Install the Calico CLI tool for advanced policy management and troubleshooting.

curl -L https://github.com/projectcalico/calico/releases/download/v3.26.4/calicoctl-linux-amd64 -o calicoctl
sudo chmod +x calicoctl
sudo mv calicoctl /usr/local/bin/
curl -L https://github.com/projectcalico/calico/releases/download/v3.26.4/calicoctl-linux-amd64 -o calicoctl
sudo chmod +x calicoctl
sudo mv calicoctl /usr/local/bin/

Configure calicoctl datastore access

Set up calicoctl to communicate with your Kubernetes cluster for policy management.

apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "kubernetes"
  kubeconfig: "/root/.kube/config"

Create namespace-based network policies

Create test namespaces for microsegmentation

Set up separate namespaces to demonstrate isolation between different application tiers.

kubectl create namespace frontend
kubectl create namespace backend
kubectl create namespace database
kubectl label namespace frontend tier=frontend
kubectl label namespace backend tier=backend
kubectl label namespace database tier=database

Deploy test applications in each namespace

Create simple test pods to verify network policy enforcement between tiers.

apiVersion: v1
kind: Pod
metadata:
  name: frontend-pod
  namespace: frontend
  labels:
    app: frontend
    tier: frontend
spec:
  containers:
  - name: frontend
    image: nginx:1.25
    ports:
    - containerPort: 80
kubectl apply -f frontend-pod.yaml

Create backend and database test pods

Deploy additional test workloads to simulate a multi-tier application architecture.

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod
  namespace: backend
  labels:
    app: backend
    tier: backend
spec:
  containers:
  - name: backend
    image: httpd:2.4
    ports:
    - containerPort: 80
apiVersion: v1
kind: Pod
metadata:
  name: database-pod
  namespace: database
  labels:
    app: database
    tier: database
spec:
  containers:
  - name: database
    image: postgres:16
    env:
    - name: POSTGRES_PASSWORD
      value: "testpass123"
    ports:
    - containerPort: 5432
kubectl apply -f backend-pod.yaml
kubectl apply -f database-pod.yaml

Implement default deny policy

Create a global default deny policy that blocks all traffic between namespaces unless explicitly allowed.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: frontend
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: backend
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: database
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
kubectl apply -f default-deny.yaml

Implement pod-to-pod traffic controls

Allow frontend to backend communication

Create a policy that allows frontend pods to communicate with backend services on specific ports.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: backend
spec:
  podSelector:
    matchLabels:
      tier: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          tier: frontend
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 8080
kubectl apply -f frontend-to-backend.yaml

Allow backend to database communication

Configure policy to permit backend services to access the database tier with specific port restrictions.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-database
  namespace: database
spec:
  podSelector:
    matchLabels:
      tier: database
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          tier: backend
    ports:
    - protocol: TCP
      port: 5432
    - protocol: TCP
      port: 3306
kubectl apply -f backend-to-database.yaml

Configure egress policies for external access

Allow specific namespaces to access external services like DNS and package repositories.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-egress
  namespace: frontend
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to: []
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  - to:
    - namespaceSelector:
        matchLabels:
          tier: backend
    ports:
    - protocol: TCP
      port: 80
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-external-egress
  namespace: backend
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to: []
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  - to:
    - namespaceSelector:
        matchLabels:
          tier: database
    ports:
    - protocol: TCP
      port: 5432
kubectl apply -f allow-dns-egress.yaml

Configure advanced selectors and monitoring

Implement pod-specific policies with labels

Create granular policies using pod labels for fine-grained access control within namespaces.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-gateway-policy
  namespace: backend
spec:
  podSelector:
    matchLabels:
      app: api-gateway
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    - namespaceSelector:
        matchLabels:
          name: frontend
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: auth-service
    ports:
    - protocol: TCP
      port: 9090
  - to: []
    ports:
    - protocol: UDP
      port: 53
kubectl apply -f pod-specific-policy.yaml

Enable network policy logging

Configure Calico to log network policy decisions for monitoring and troubleshooting.

calicoctl patch felixconfiguration default --patch '{"spec":{"policySyncPathPrefix":"/var/run/calico","chainInsertMode":"insert","logSeverityScreen":"Info","logFilePath":"/var/log/calico/felix.log"}}'

Create Calico GlobalNetworkPolicy for cluster-wide rules

Implement cluster-wide policies that apply across all namespaces using Calico-specific resources.

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: deny-all-non-system
spec:
  order: 100
  selector: projectcalico.org/namespace != "kube-system" && projectcalico.org/namespace != "calico-system"
  types:
  - Ingress
  - Egress
  egress:
  - action: Allow
    destination:
      selector: projectcalico.org/namespace == "kube-system"
    protocol: TCP
    destination:
      ports:
      - 53
  - action: Allow
    destination:
      selector: projectcalico.org/namespace == "kube-system"
    protocol: UDP
    destination:
      ports:
      - 53
calicoctl apply -f global-policy.yaml

Configure monitoring and alerts for policy violations

Set up logging to track denied connections and policy violations for security monitoring.

kubectl create configmap calico-config -n kube-system --from-literal=calico_backend=kubernetes
kubectl patch daemonset calico-node -n calico-system --patch='{"spec":{"template":{"spec":{"containers":[{"name":"calico-node","env":[{"name":"FELIX_LOGSEVERITYSCREEN","value":"Info"},{"name":"FELIX_CHAININSERTMODE","value":"insert"}]}]}}}}'

Test network policy enforcement

Test allowed connections

Verify that explicitly allowed traffic flows work correctly between tiers.

kubectl exec -n frontend frontend-pod -- curl -m 5 backend-pod.backend.svc.cluster.local
kubectl exec -n backend backend-pod -- nc -zv database-pod.database.svc.cluster.local 5432

Test blocked connections

Confirm that unauthorized traffic is properly blocked by the network policies.

kubectl exec -n frontend frontend-pod -- nc -zv database-pod.database.svc.cluster.local 5432
kubectl exec -n database database-pod -- curl -m 5 frontend-pod.frontend.svc.cluster.local

Verify your setup

kubectl get networkpolicies --all-namespaces
calicoctl get networkpolicy --all-namespaces
calicoctl get globalnetworkpolicy
kubectl get pods --all-namespaces -o wide
Note: Network policies are additive. Multiple policies can apply to the same pod, and traffic is allowed if any policy permits it. Always test your policies in a development environment before applying to production.

Common issues

SymptomCauseFix
Pods cannot communicate after policy applicationMissing DNS egress rulesAdd UDP/TCP port 53 egress to all pods
Services timing out intermittentlyMissing kube-system namespace accessAllow egress to kube-system for system services
Ingress controller not workingNetwork policy blocking ingress podCreate policy allowing traffic from ingress namespace
calicoctl commands failIncorrect kubeconfig pathSet KUBECONFIG environment variable or update calicoctl.cfg
Policies not enforcedCNI not supporting network policiesVerify Calico is installed as primary CNI

Next steps

Running this in production?

Need this managed? Running network policies at scale adds complexity around policy testing, compliance auditing, and incident response when legitimate traffic gets blocked. Our managed platform covers monitoring, policy validation, and 24/7 response by default.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle private cloud infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.