Kubernetes Network Policy - Allowing traffic to service over specific port only

Viewed 773

I have a GKE cluster v1.21 and have network policy enabled.

I denied all ingress and egress traffic within the cluster using:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-traffic
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

And I have a deployment and an internal load balancer the listens on 443:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
spec:
  selector:
    app: my-webserver
  ports:
    - port: 443
      targetPort: 8080
  type: LoadBalancer

And another deployment called my-deployment from which I want to send https requests to my-webserver.

I've setup the following policies:

Allow ingress for my-webserver

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-ingress-my-webserver
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: my-webserver
  ingress:
  - from:     
    - podSelector:
        matchLabels:
          app: my-deployment
    ports:
    - protocol: TCP
      port: 443

Allow egress for my-deployment

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress-my-deployment
spec:
  podSelector:
    matchLabels:
      app: my-deployment
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: my-webserver
    ports:
    - protocol: TCP
      port: 443

Those network policies don't allow me to send requests to my-webserver from my-deployment.

However, when removing the ports section on both policies this works - I can make https calls from my-deployment to my-webserver.

But, I want to be able to allow connections only on a specific port and a specific protocol.

Is there a way for me to restrict connections only to a specific port?

1 Answers

I am assuming you are testing from a my-deployment's Pod and hitting the External LB's IP address, if that is the case; this is happening because the communication you are allowing is just from the source Pod to the service, you are missing the part from the service to the destination Pod.

As per Google's documentation:

You can use GKE's Network Policy Enforcement to control the communication between your cluster's Pods and Services. You define a network policy by using the Kubernetes Network Policy API to create Pod-level firewall rules. These firewall rules determine which Pods and Services can access one another inside your cluster.

What you need to do, is to allow the port 8080 as well in both policies:

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-ingress-my-webserver
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: my-webserver
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: my-deployment
    ports:
    - protocol: TCP
      port: 8080
    - protocol: TCP
      port: 443
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress-my-deployment
spec:
  podSelector:
    matchLabels:
      app: my-deployment
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: my-webserver
    ports:
    - protocol: TCP
      port: 8080
    - protocol: TCP
      port: 443
Related