Installing network policies

Network Policy support

Network policies are a recommended security control that allow you to control traffic flow to and from pods or namespaces within a Kubernetes cluster. In essence, they work like micro-firewalls, allowing or denying traffic based on the pod’s IP and port.

Network policies work by selecting resources (pods) based on labels and namespaces. This means you can apply them selectively to specific pods or namespaces to create a secure environment. Note that network policies are applied on the pod level, so using service labels or ports will not work.

  • Network policies work using labels and namespaces to select resources (pods) for which they apply.
  • Network policies use the pod’s IP and port. You should not configure network policies using a service labels and/or the port. Use a service endpoints (kubectl get endpoint <my-service>) instead.

Network policies can be installed using kubectl apply, like any other resource within Kubernetes.

  • kubectl get networkpolicies - list network policies within your current namespace
  • kubectl get networkpolicies -A - list all network policies within the cluster
  • kubectl describe networkpolicies <policy> - view a summary of the network policy

Notes about Network Policies

  • Network policies in Kubernetes are similar to security groups in cloud environments, but they are not the same thing. Network policies work at the pod and/or namespace level, while security groups work at the instance or virtual machine level.

  • While network policies can help improve the security of your Kubernetes environment, they are not a replacement for other security controls such as authentication, access controls, and encryption. You should use network policies in conjunction with these other controls to create a secure environment.

Network Policy specification

Description

A NetworkPolicy is a Kubernetes object that defines how network traffic is allowed or blocked within a Kubernetes cluster. It is a recommended security control to enforce network segmentation and restrict network access to certain pods. A NetworkPolicy works by selecting pods based on labels and then applying policyTypes, either Ingress, Egress, or both, to allow or deny traffic.

You can read up about the API reference here.

Spec

egress

The egress field lists the egress rules that are applied to the selected pods. It specifies the destination of outgoing traffic from the selected pods. If the egress field is empty, the NetworkPolicy object limits all outgoing traffic from the selected pods.

ingress

The ingress field lists the ingress rules that are applied to the selected pods. It specifies the allowed traffic sources for incoming traffic to the selected pods. If the ingress field is empty, the NetworkPolicy object does not allow any incoming traffic to the selected pods.

podSelector

The podSelector field selects the pods to which the NetworkPolicy object applies. The ingress and egress rules defined in the NetworkPolicy object are applied to any pods selected by this field. Multiple NetworkPolicy objects can select the same set of pods. In this case, the ingress and egress rules for each are combined additively. This field is not optional and follows standard label selector semantics. An empty podSelector matches all pods in the namespace.

policyTypes

The policyTypes field lists the types of rules that the NetworkPolicy object relates to. It can be set to Ingress, Egress, or both Ingress and Egress. If this field is not specified, it defaults based on the existence of Ingress or Egress rules.

Policies that contain an Egress section are assumed to affect Egress, and all policies (whether or not they contain an Ingress section) are assumed to affect Ingress.

To write an Egress-only policy, you must explicitly specify policyTypes: ["Egress"]. Similarly, to write a policy that specifies that no egress is allowed, you must specify a policyTypes value that includes Egress since such a policy would not include an Egress section and would otherwise default to just “Ingress”.

Default deny

This network policy should be installed in any namespace in your cluster. It will deny any network traffic for any pod running within the namespace this network policy is installed in.

This includes;

  • traffic between pods within the same namespace
  • traffic between pods in other namespaces
  • traffic to any external service (e.g. private IP ranges, public internet, etc)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny-all
  namespace: mynamespace
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
  ingress: []
  egress: []

Allow DNS traffic

Allow DNS traffic from your pod to the kube-system namespace. This is where the in cluster DNS resolver runs (CoreDNS).

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-egress-dns
  namespace: mynamespace
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Egress
  egress:
  - ports:
    # Allow DNS
    - port: 53
      protocol: UDP
    - port: 53
      protocol: TCP
    to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system

Allow ingress from ingress-controller

Be explicit when installing a policy that allows ingress traffic from anywhere. This means listing the ports to which this traffic is allowed.

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-traffic-from-ingress
  namespace: mynamespace
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: example
      app.kubernetes.io/instance: example-instance
  policyTypes:
    - Ingress
  ingress:
    - ports:
      - port: 8000
      from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: 'ingress-nginx'

The above policy allows any tcp traffic on port 8000 to any pods running in the mynamespace namespace, matching the labels from the podSelector.matchLabels, coming from the namespace ingress-nginx.

Egress to public network

If you wish to enable egress traffic from a pod to a public network, you can use the egress ipBlock rule. Note that you will want to combine this with an except list, in order to avoid also allowing traffic to any internal network, including any pod or private IP within your cloud environment. Otherwise, using just 0.0.0.0 means it works the same as simpily using no network policies and could have unintended consequences.

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-connections-to-external
  namespace: mynamespace
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: example
      app.kubernetes.io/instance: example-instance
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        # deny internal RFC1918 subnets
        - 10.0.0.0/8
        - 172.16.0.0/12
        - 192.168.0.0/16

The above policy allows egress traffic from pods with the labels app.kubernetes.io/name: example and app.kubernetes.io/instance: example-instance to any IP address outside of the cluster (0.0.0.0/0), except for private RFC1918 subnets (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16).

Other resources