Computer scienceSystem administration and DevOpsKubernetes

Ingress and Egress Network Policies

17 minutes read

By default, every pod can communicate with all other pods within the Kubernetes cluster using their unique pod IP addresses. However, in certain scenarios, there's a need to restrict access to specific pods. For instance, consider a backend database pod holding sensitive information; we want to ensure that only specific frontend pods can connect to it.

This topic will explore the usage of NetworkPolicy, a Kubernetes resource, to establish isolated pods or control access to designated groups of pods. It provides a way to define rules that govern the flow of network traffic between pods, enabling us to enforce fine-grained security measures within the cluster.

NetworkPolicy

networkpolicy usecase

Consider a scenario where an application is deployed within a Kubernetes cluster, comprising three distinct components: frontend, backend, and a database. In this setup, it is important to note that the frontend pod should not have direct communication with the database pod. By default, every pod can communicate with all other pods within the Kubernetes cluster using their unique pod IP addresses. Allowing such access from the frontend to the database could potentially result in security vulnerabilities and compromise data integrity, leading to possible data breaches or loss. Preventing communication between the frontend pod and the database can be accomplished by implementing NetworkPolicy.

In Kubernetes, a Network Policy is a resource that allows you to define and control the traffic flow between different pods within a cluster. It acts as a firewall for your Kubernetes network, enabling fine-grained control over inbound and outbound traffic at the pod level. NetworkPolicy allows you to specify rules that control traffic flow between pods, these rules govern how pods communicate with each other, both in terms of traffic coming into the pods(Ingress) and traffic going out of the pods (Egress). This allows you to enforce security measures and isolate different parts of your application stack.

NetworkPolicy resource

NetworkPolicy deals with traffic within the cluster and operates at the pod-level. NetworkPolicies are namespace scoped, that is they are created inside a namespace in a Kubernetes cluster just like pods. Policies are applied to pods using label selectors.

Let us see an example of how to define a NetworkPolicy

kind: NetworkPolicy
metadata:
  name: mynetworkpolicy
  namespace: prod
spec:
  # podSelector field lists the pods that will be managed by this NetworkPolicy. In this example pods having label exactly as "role: backend" will be selected
  podSelector:
    matchLabels:
      role: backend

  policyTypes:
  - Ingress
  - Egress

  # ingress defines rules for the traffic comming into the pod
  ingress:
  # from field defines from which pods is the traffic allowed into the managed pods
  - from:
     # this specifies that traffic is allowed into the managed pods(pods managed by this networkpolicy) only from those pods that have the label "role: frontend"
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6060

  # egress defines rules for the traffic going out of the managed pods
  egress:
  - to:
     # this specifies that the managed pods(pods managed by this networkpolicy) can only send traffc to those pods that have the label "role: database"
    - podSelector:
        matchLabels:
          role: database
    ports:
    - protocol: TCP
      port: 5432

Similar to other Kubernetes resources, the NetworkPolicy resource includes the standard fields such as apiVersion, kind, metadata, and spec.In the example above, this NetworkPolicy will be created within the prod namespace. In case no namespace is specified, it defaults to the default namespace.

The podSelector field pinpoints the specific group of pods for management. In the given example, this NetworkPolicy exclusively manage pods with label role: backend. It is important to note that when the podSelector field is omitted, the NetworkPolicy will select all the pods within its namespace.

The policyTypes field specifies the types of policies to be applied to the selected pods. There are two available types: Ingress and Egress. The ingress field defines rules for incoming traffic to the managed pods, while egress defines the outbound traffic from these pods.

To deploy a NetworkPolicy, you first have to create a YAML file. Let's call it np.yaml, where you can copy the example manifest shown above. Once the NetworkPolicy manifest is ready, you can use the kubectl command to deploy it to your Kubernetes cluster. Open your terminal and navigate to the directory where you saved the np.yaml file. Then, run the following command:

kubectl apply -f np.yaml

The ingress field within a NetworkPolicy manifest specifies rules determining the allowed incoming traffic destined for the pods that are managed by the NetworkPolicy. Conversely, the egress field in a NetworkPolicy manifest outlines rules governing outgoing traffic originating from the pods that are managed by the NetworkPolicy. These rules can define various aspects, including permitted traffic sources (which pods are allowed to send traffic to the managed pods), destination endpoints (pods that the managed pods can communicate with), as well as the permitted communication protocols (such as TCP, UDP, etc.) and specific ports. There are three ways for selecting traffic sources(for ingress) or endpoints(for egress), they are podSelector, namespaceSelector and ipBlock.

Ingress and Egress traffic rules using PodSelector

podSelector demo for ingress podSelector demo for egress

The above example demonstrates defining an ingress(left) and egress(right) rules using podSelector. In the context of ingress, the podSelector field specifies the specific group of pods that are allowed to send traffic into the pods managed by this NetworkPolicy. Specifically, this NetworkPolicy only permits incoming traffic from pods that are within it's namespace and have the label app: app1. The ports sub-field defines the rules for incoming traffic. In the above example (on the left), it specifically allows incoming traffic with the TCP network protocol, directing it to the managed pods on port 6060.

In the context of egress, podSelector field specifies the group of pods permitted to receive outgoing traffic originating from pods managed by this NetworkPolicy. Specifically, this NetworkPolicy allows outgoing traffic exclusively to pods labeled app: app1 within its namespace. The ports sub-field defines the rules for outgoing traffic. In the above example (on the right), it specifically allows outgoing traffic using the TCP network protocol from the managed pods, targeting a destination on port 6060.

It is important to note that the podSelector mentioned here resides within the spec.ingress sub-field, is different from spec.podSelector.

Ingress and Egress traffic rules using NamespaceSelector

namespaceSelector demo for ingress namespaceSelector demo for egress

The above example demonstrates defining an ingress(left) and egress(right) rules using namespaceSelector. In the context of ingress, the namespaceSelector field specifies the specific group of pods that are allowed to send traffic into the pods managed by this NetworkPolicy. Specifically, this NetworkPolicy only permits incoming traffic from all the pods that are within the namespace that has label env: analytics.

In the context of egress, the namespaceSelector field specifies the group of pods permitted to receive outgoing traffic originating from pods managed by this NetworkPolicy. Specifically, this NetworkPolicy allows outgoing traffic exclusively to pods that are in the namespace which has label env: analytics.

Ingress and Egress traffic rules using NamespaceSelector and PodSelector

It is also possible to combine both namespaceSelector and podSelector in a single rule like in the example below.

namespaceSelector and podSelector demo for ingress namespaceSelector and podSelector demo for egress

The above example demonstrates defining an ingress(left) and egress(right) rules using namespaceSelector and podSelector. In the context of ingress, this NetworkPolicy only permits incoming traffic from all the pods that are within the namespace that has label env: analytics and also have label app: app1.

In the context of egress, this NetworkPolicy allows outgoing traffic exclusively to pods that are in the namespace which has label env: analytics and also have label app: app1.

Ingress and Egress traffic rules using IPBlock

ipBlock demo for ingress ipBlock demo for egress

The above example demonstrates defining an ingress(left) and egress(right) rule using ipBlock, which offers the ability to specify allowed traffic based on IP addresses or ranges. In the context of ingress, this functionality grants control over pod access based on source IP addresses or defined IP ranges. The cidr sub-field specifies the IP in CIDR notation (172.17.0.0/16 in this case). Pods within this NetworkPolicy's namespace and having IP addresses within this specified range are permitted to send traffic to the pods managed by this NetworkPolicy, except for the pods whose IP addresses fall in the cidr range specified by the except sub-field(172.17.1.0/24 in this case).

In the context of egress, this functionality grants control over pod access based on destination IP addresses or defined IP ranges. The cidr sub-field specifies the IP in CIDR notation (172.17.0.0/16 in this case). Pods within this NetworkPolicy's namespace and having IP addresses within this specified range are allowed to receive outgoing traffic from the pods managed by this NetworkPolicy, except for the pods whose IP addresses fall in the cidr range specified by the except sub-field(172.17.1.0/24 in this case).

Putting everything together

Let us now take a look at a full NetworkPolicy manifest in order to understand how everything fits together

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
      podSelector:
        matchLabels:
          role: frontend
    - podSelector:
        matchLabels:
          role: backend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

This network policy when created is called test-network-policy, it will be created in the default namespace. This NetworkPolicy will be responsible for isolating or managing the pods that are in the default namespace having label as role: db. The policyTypes field in the above manifest suggests that both ingress and egress rules will be applied to the selected pods.

Based on spec.ingress sub-field in the example above we can conclude that this NetworkPolicy will allow traffic into the managed pods only from:

  • pods in the default namespace having IP address in the cidr range 172.17.0.0/16 except for those whose IP address fall in the cidr range 172.17.1.0/24.
  • pods that are in the namespace that has label project: myproject having label role: frontend.
  • pods that are in the default namespace having label role: backend.

This NetworkPolicy only allows incoming traffic with the TCP network protocol, directing it to the managed pods on port 6379.

Based on spec.egress sub-field in the example above we can conclude that this NetworkPolicy will allow traffic from the managed pods only to all the pods in the default namespace having IP address in the cidr range 10.0.0.0/24. This NetworkPolicy only allows incoming traffic with the TCP network protocol, directing it to the managed pods on port 5978.

Default policies

By default, if no policies exist in a namespace, then all ingress and egress traffic is allowed to and from pods in that namespace.

To set the default to deny all incoming traffic, use the following manifest

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  # this selects all the pods in the default namespace to manage
  podSelector: {}
  # rules applied only for the incoming traffic, egress remains uneffected
  policyTypes:
  - Ingress

This NetworkPolicy ensures that pods, regardless of other NetworkPolicy settings, will have no incoming traffic allowed. The outgoing traffic from the managed pods remains unaffected.

To set the default to allow all incoming traffic, use the following manifest

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  # this selects all the pods in the default namespace to manage
  podSelector: {}
  # this allows traffic from any pod in the default namespace to the managed pods
  ingress:
  - {}
  # rules applied only for the incoming traffic, egress remains uneffected
  policyTypes:
  - Ingress

This NetworkPolicy ensures that pods in the default namespace will accept incoming connections regardless of any other policies. The outgoing traffic from the managed pods remains unaffected.

To set the default to deny all outgoing traffic, use the following manifest

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  # this selects all the pods in the default namespace
  podSelector: {}
  # rules applied only for the outgoing traffic, ingress remains uneffected
  policyTypes:
  - Egress

This NetworkPolicy ensures that pods, even if not specified by other NetworkPolicies, cannot send traffic outside. The incoming traffic into the managed pods remains unaffected.

To set the default to allow all outgoing traffic, use the following manifest

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  # this selects all the pods in the default namespace
  podSelector: {}
  # this allows traffic from the managed pods to any destination
  egress:
  - {}
  # rules applied only for the outgoing traffic, ingress remains uneffected
  policyTypes:
  - Egress

This NetworkPolicy ensures that pods will allow outgoing connections without restrictions, unaffected by other policies. The incoming traffic into the managed pods remains unaffected.

By setting the default to deny all ingress and deny all egress administrators can enforce strict control over incoming traffic to pods as well as ensure that no pods can initiate outgoing connections by default. Administrators can then define precise rules specifying the allowed sources, protocols, ports, and destinations essential for the application's intended functionality. This fine-grained control ensures that only necessary communication is permitted and restricts any unwanted or potentially harmful traffic within the Kubernetes environment. Deny all ingress and deny all egress can be achieved by using the following manifest:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  # this selects all the pods in the default namespace to manage
  podSelector: {}
  # this controlls both the incoming and the outgoing traffic
  policyTypes:
  - Ingress
  - Egress

Conclusion

Kubernetes NetworkPolicy is a Kubernetes resource that provides fine-grained control over pod-to-pod communication within a cluster.

By default, all ingress and egress traffic is permitted to and from pods within a namespace. However, configuring the default to deny all ingress and deny all egress establishes fundamental security measures. This approach allows administrators to construct precise NetworkPolicies, explicitly defining authorized traffic pathways. Consequently, this strategy significantly bolsters the security and compliance standards within the Kubernetes cluster.

By defining rules for ingress and egress traffic, NetworkPolicy provides robust network isolation and security, allowing administrators to enforce specific traffic policies based on pod labels, namespaces, IP addresses, and ports. This feature facilitates enhanced security measures and helps create a more controlled and secure networking environment within Kubernetes clusters.

2 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo