Fundamentals of Kubernetes Network Policy Simplified - Part 2
Source: www.cajieh.com
Pre-requisite:
- Basic knowledge of Container technology and kubernetes are required
- Proficient in the use of command line tools i.e. Bash terminal
- Access to a Kubernetes cluster that supports NetworkPolicy if you want to experiment with the example in this tutorial
Introduction
NetworkPolicy is a key technique for isolating and restricting pod-to-pod communications in Kubernetes cluster environment. They are often used to control the access to/from pods in the same namespace or separate namespaces. By default, every pod can communicate with each other and have unrestricted access which is not ideal in most situations.
In part 1 of this tutorial series, I demonstrated how Kubernetes NetworkPolicy resources are implemented in the same namespace by creating three pods in the default namespace: frontend, backend, and database. Then, I applied it to control the flow of traffic from/to pod resources according to the specifications. To see part 1 on Fundamentals of Kubernetes Network Policy Simplified, click the following link: Fundamentals of Kubernetes NetworkPolicy Simplified
In this tutorial, I'll be explaining the fundamentals of Kubernetes NetworkPolicy, using an example of pod communication within separate or interconnecting namespaces In the part 1 of the tutorial, I mentioned that there are four unique selector types that can be used to target endpoints which are:
podSelector
: Select a particular pod and allow traffic to/from communication with Pods that match a specific label in the same namespacenamespaceSelector
: Select particular namespaces for which all pods within the namespace are granted permission to communicatepodSelector
andnamespaceSelector
: Select a combination ofnamespaceSelector
andpodSelector
for specific Pods within certain namespaces.ipBlock
: Select an IP address within the specified block and allow the connection.
An example of Kubernetes NetworkPolicy specifications and implementation for inter-namespace communications
To demonstrate how the Kubernetes NetworkPolicy resource works for inter-namespace pod communications, let's start by creating two namespaces, namely houston and durham, and a pod in each, named pod1 and pod2 respectively. Then to valid the implementation, let’s create a pod in the default namespace and name it pod-test.
Usually, I like using alias
command to shorten the kubectl
command e.g.
alias k=kubectl
This would allow me to use the letter k
instead of kubectl
which makes typing easy and fast.
k create ns houston
namespace/houston created
k create ns durham
namespace/durham created
k run pod1 --image=nginxdemos/hello:plain-text -n houston
pod/pod1 created
k run pod2 --image=nginxdemos/hello:plain-text -n durham
pod/pod2 created
k run pod-test --image=nginxdemos/hello:plain-text
pod/pod-test created
Verify that each pod can communicate with each other
Get the pod IP addresses
k get po -o wide -n houston
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod1 1/1 Running 0 7m54s 192.168.0.11 controlplane <none> <none>
k get po -o wide -n durham
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod2 1/1 Running 0 7m53s 192.168.0.12 controlplane <none> <none>
co
k get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-test 1/1 Running 0 87s 192.168.0.13 controlplane <none> <none>
Verify pod1 in houston namespace can access pod2 in durham namespace
k -n houston exec -it pod1 -- curl 192.168.0.12
Server address: 192.168.0.12:80
Server name: pod2
Date: 26/Jun/2024:20:10:23 +0000
URI: /
Request ID: 2bdb7b18d75dc2dce6dcdd12623c8960
Verify pod2 in durham namespace can access pod2 houston namespace
k -n durham exec -it pod2 -- curl 192.168.0.11
Server address: 192.168.0.11:80
Server name: pod1
Date: 26/Jun/2024:20:11:12 +0000
URI: /
Request ID: 56307ba7893a6e4fbf0217452a15905b
Verify pod-test in default namespace can access pod1 ns houstonnamespace
k exec -it pod-test -- curl 192.168.0.11
Server address: 192.168.0.11:80
Server name: pod1
Date: 26/Jun/2024:20:12:11 +0000
URI: /
Request ID: 25dc1bb7f09ab19f4c666b81192bdbbe
Verify pod-test in default namespace can access pod2 durham namespace
k exec -it pod-test -- curl 192.168.0.12
Server address: 192.168.0.12:80
Server name: pod2
Date: 26/Jun/2024:20:12:46 +0000
URI: /
Request ID: 3157da37dbc3e094cc7e82d53fd35e6b
These are absolutely working as expected because pod communications are non-isolated by default, and given that no NetworkPolicies have been implemented.
Implement two NetworkPolicies to allow connections from/to houston and hurham
Let's implement two NetworkPolicies to allow connections from/to houston and hurham. Refer to the diagram above for a quick overview of the architectural setup of the namespaces, pods, and NetworkPolicy types. The NetworkPolicy rules will allow the egress and ingress traffic from/to the houston and durham namespaces, and deny traffic to and from other namespaces using the namespaceSelector
selector on port 80.
houston-np.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: houston-np
namespace: houston
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: durham
ports:
- protocol: TCP
port: 80
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: durham
ports:
- protocol: TCP
port: 80
The houston-np.yaml Kubernetes NetworkPolicy specification manifest defines a NetworkPolicy named houston-np in the houston namespace. Here's what it does:
podSelector
: { }- This selects all pods in the houston namespace because it's an empty selector.policyTypes
: - This specifies that the policy will apply to both incomingIngress
and outgoingEgress
traffic.ingress
: This section defines the ingress rules. Where thefrom
specifies the sources of incoming traffic. ThenamespaceSelector
with thematchLabels
uses thekubernetes.io/metadata.name
to target the namespace ofdurham
. This allows traffic from any pod in the durham namespace. Theports
TCP protocol allows incoming TCP traffic on port 80.egress
: This section defines the egress rules. Where theto
specifies the destinations for outgoing traffic. ThenamespaceSelector
with thematchLabels
uses thekubernetes.io/metadata.name
to target the namespace ofdurham
. This allows traffic to any pod in the durham namespace. Theports
TCP protocol allows incoming TCP traffic on port 80.
In summary, this NetworkPolicy allows TCP traffic on port 80 from/to all pods in the houston namespace to all pods in the durham namespace. Next let's look at the NetworkPolicy specification for durham namespace
durham-np.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: durham-np
namespace: durham
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: houston
ports:
- protocol: TCP
port: 80
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: houston
ports:
- protocol: TCP
port: 80
The durham-np.yaml Kubernetes NetworkPolicy specification manifest similar vey similar to houston-np.yaml but defines a NetworkPolicy named durham-np in the durham namespace, and podSelector: { }
to selects all pods in the durham. Then, it specifies that the policy will apply to both incoming Ingress
and outgoing Egress
traffic in houston namespace.
Let’s apply the NetworkPolicy using the houston-ns.yaml and durham-np.yaml files
k create -f houston-ns.yaml
networkpolicy.networking.k8s.io/network-policy created
k create -f durham-ns.yaml
networkpolicy.networking.k8s.io/network-policy created
Verify the connection again.
k exec -it pod-test -- curl 192.168.0.11
curl: (7) Failed to connect to 192.168.0.11 port 80 after 1012 ms: Couldn't connect to server
command terminated with exit code 7
k exec -it pod-test -- curl 192.168.0.12
curl: (7) Failed to connect to 192.168.0.12 port 80 after 1017 ms: Couldn't connect to server
command terminated with exit code 7
Verify if pod1 houston can still access pod2
k -n houston exec -it pod1 -- curl 192.168.0.12
Server address: 192.168.0.12:80
Server name: pod2
Date: 26/Jun/2024:20:31:51 +0000
URI: /
Request ID: 88e965de127b88e96604edd0580fa41d
Verify if pod2 durham can still access pod1
k -n durham exec -it pod2 -- curl 192.168.0.11
Server address: 192.168.0.11:80
Server name: pod1
Date: 26/Jun/2024:20:33:45 +0000
URI: /
Request ID: f3f0085f7d7c49cb50cc16c637f0c6b4
Verify that pod1 and pod2 in houston and durham respectively cannot access pods in default namespce.
k -n houston exec -it pod1 -- curl 192.168.0.13
curl: (7) Failed to connect to 192.168.0.13 port 80 after 1012 ms: Couldn't connect to server
command terminated with exit code 7
k -n durham exec -it pod2 -- curl 192.168.0.13
curl: (7) Failed to connect to 192.168.0.13 port 80 after 1012 ms: Couldn't connect to server
command terminated with exit code 7
That concludes the fundamentals of Kubernetes NetworkPolicy on how to restrict access across namespaces using the NetworkPolicy resource. This was explained with an example of inter-namespace pod communication using the Egress
and Ingress
policy types and the namespaceSelector
selector.
I hope this helps! Go to the contact page and let me know if you have any further questions.
Happy learning!