How to block all traffic to pods matching a label using a NetworkPolicy

11/8/2021

Afaik, the K8s NetworkPolicy can only allow pods matching a label to do something. I do not want to:

  • Deny all traffic
  • Allow traffic for all pods except the ones matching my label

but instead:

  • Allow all traffic
  • Deny traffic for pods matching my label

How do I do that?

From kubectl explain NetworkPolicy.spec.ingress.from:

DESCRIPTION:
     List of sources which should be able to access the pods selected for this
     rule. Items in this list are combined using a logical OR operation. If this
     field is empty or missing, this rule matches all sources (traffic not
     restricted by source). If this field is present and contains at least one
     item, this rule allows traffic only if the traffic matches at least one
     item in the from list.

As far as I understand this, we can only allow, not deny.

-- User12547645
kubernetes
kubernetes-networkpolicy
security

1 Answer

11/9/2021

As you mentioned in the comments, you are using the Kind tool for running Kubernetes. Instead of kindnet CNI plugin (default CNI plugin for Kind) which does not support Kubernetes network policies, you can use Calico CNI plugin which support Kubernetes network policies + it has its own, similar solution called Calico network policies.


Example - I will create cluster with disabled default kind CNI plugin + enabled NodePort for testing (assuming that you have kind + kubectl tools already installed):

kind-cluster-config.yaml file:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  disableDefaultCNI: true # disable kindnet
  podSubnet: 192.168.0.0/16 # set to Calico's default subnet
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
    listenAddress: "0.0.0.0" # Optional, defaults to "0.0.0.0"
    protocol: tcp # Optional, defaults to tcp

Time for create a cluster using above config:

kind create cluster --config kind-cluster-config.yaml

When cluster is ready, I will install Calico CNI plugin:

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

I will wait until all calico pods are ready (kubectl get pods -n kube-system command to check). Then, I will create sample nginx deployment + service type NodePort for accessing:

nginx-deploy-service.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30000

Let's apply it: kubectl apply -f nginx-deploy-service.yaml

So far so good. Now I will try to access nginx-service using node IP (kubectl get nodes -o wide command to check node IP address):

curl 172.18.0.2:30000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Okay, it's working.

Now time to install calicoctl and apply some example policy - based on this tutorial - to block ingress traffic only for pods with label app with value nginx:

calico-rule.yaml:

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: default-deny
spec:
  selector: app == "nginx"
  types:
  - Ingress

Apply it:

calicoctl apply -f calico-rule.yaml 
Successfully applied 1 'GlobalNetworkPolicy' resource(s)

Now I can't reach the address 172.18.0.2:30000 which was working previously. The policy is working fine!

Read more about calico policies:

Also check this GitHub topic for more information about NetworkPolicy support in Kind.

EDIT:

Seems like Calico plugin supports as well Kubernetes NetworkPolicy, so you can just install Calico CNI plugin and apply the following policy:

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny
spec:
  podSelector:
    matchLabels:
      app: nginx
  policyTypes:
  - Ingress

I tested it and seems it's working fine as well.

-- Mikolaj S.
Source: StackOverflow