Kubernetes - Ingress Policy
Kubernetes provides a resource called NetworkPolicy that allows rules to allow/deny network traffic, which works like a network firewall.By default using this resource doesn't do anything. To make it work, you need first to add a Kubernetes Networking plugin that implements it.Some Kubernetes cluster providers propose their implementation, like GKS and AKS. On the other side, you can use Calico, like recommended by AWS with EKS.
I have installed calico network policy agent for the network policy to work.
curl https://projectcalico.docs.tigera.io/v3.23/manifests/calico-policy-only.yaml -o calico.yaml
kubectl apply -f calico.yaml
Lets create a namespace "production".
root@master:~# kubectl create ns production
namespace/production created
root@master:~#
Creating a nginx pod under "production" namespace.
root@master:~# kubectl run nginx -n production --image nginx --labels app=nginx --expose --port 80
service/nginx created
pod/nginx created
root@master:~#
root@master:~# kubectl get all -n production
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 0 37s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx ClusterIP 10.98.247.195 <none> 80/TCP 37s
root@master:~#
Now try to access this Nginx pod from another pod. Use this command for the verification.
root@master:~# kubectl get pods -A -n production -o wide | grep -i nginx
production nginx 1/1 Running 0 2m43s 10.244.0.7 master <none> <none>
root@master:~#
Accessing pod IP from host machine:
root@master:~# curl 10.244.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@master:~#
Lets try to access from a pod on another namespace.
root@master:~# kubectl run test-pod --image nginx
pod/test-pod created
root@master:~#
root@master:~# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 1/1 Running 0 19s 10.244.0.10 master <none> <none>
root@master:~#
root@master:~# kubectl exec -it test-pod -- curl 10.244.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@master:~#
Deny All Traffic to Pod:
You should be able to access the Nginx pod without any issue. It is the default and expected behavior, and there is nothing new about this setup.
Let’s try to change this default behavior by introducing a network policy that should deny all incoming traffic by default for pods in the "production" namespace.
root@master:/kube# cat network_policy.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-all-policy
namespace: production # Namespace
spec:
podSelector:
matchLabels:
app: nginx # App label
ingress: []
root@master:/kube#
We implement this network policy in "production" namespace.
root@master:/kube# kubectl apply -f network_policy.yml
networkpolicy.networking.k8s.io/deny-all-policy created
root@master:/kube#
root@master:/kube# kubectl get networkpolicy -n production
NAME POD-SELECTOR AGE
deny-all-policy app=nginx 15s
root@master:/kube#
root@master:/kube# kubectl describe networkpolicy -n production
Name: deny-all-policy
Namespace: production
Created on: 2022-07-20 09:15:47 -0700 MST
Labels: <none>
Annotations: <none>
Spec:
PodSelector: app=nginx
Allowing ingress traffic:
<none> (Selected pods are isolated for ingress connectivity)
Not affecting egress traffic
Policy Types: Ingress
root@master:/kube#
Lets test it out.
root@master:/kube# kubectl exec -it test-pod -- curl 10.244.0.7
curl: (28) Failed to connect to 10.244.0.7 port 80: Connection timed out
command terminated with exit code 28
root@master:/kube#
Lets test connection by creating a pod under "production" namespace with the label “app=nginx”.
root@master:/kube# kubectl run test --image=nginx -l app=nginx -n production
pod/test created
root@master:/kube# kubectl get pod -n production --show-labels -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx 1/1 Running 0 83m 10.244.0.7 master <none> <none> app=nginx
test 1/1 Running 0 17s 10.244.0.17 master <none> <none> app=nginx
root@master:/kube#
root@master:/kube# kubectl exec -it test -n production sh -- curl 10.244.0.7
^Ccommand terminated with exit code 130
root@master:/kube#
DENY ALL - Going to deny all the incoming traffic.
Allow/limit Traffic to Pod:
In this section, you will allow traffic from only those pods with the matching label as app=nginx. To test this, use the following network policy.
root@master:/kube# cat network_policy.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-policy
namespace: production
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
app: nginx
root@master:/kube#
root@master:/kube# kubectl get networkpolicy -A
NAMESPACE NAME POD-SELECTOR AGE
production allow-policy app=nginx 2s
root@master:/kube#
root@master:/kube# kubectl get pods -n production -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx 1/1 Running 0 62m 10.244.0.7 master <none> <none> app=nginx
test 1/1 Running 1 (26s ago) 41s 10.244.0.13 master <none> <none> app=nginx
root@master:/kube#
root@master:/kube# kubectl get pods -n production -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx 1/1 Running 0 89m 10.244.0.7 master <none> <none> app=nginx
test 1/1 Running 0 6m34s 10.244.0.17 master <none> <none> app=nginx
root@master:/kube# kubectl exec -it test -n production sh -- curl 10.244.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@master:/kube#
Now I can access the pod from “production” namespace with the label “app=nginx". Lets create another pod under "production" namespace with different label "app=java".
root@master:/kube# kubectl get pods -n production -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
java 1/1 Running 0 8s 10.244.0.18 master <none> <none> app=java
nginx 1/1 Running 0 91m 10.244.0.7 master <none> <none> app=nginx
test 1/1 Running 0 8m37s 10.244.0.17 master <none> <none> app=nginx
root@master:/kube#
Lets test:
root@master:/kube# kubectl exec -it java -n production sh -- curl 10.244.0.17
^Ccommand terminated with exit code 130
root@master:/kube#
Not accessbile.
Now, Lets test by creating a pod under "default" namespace with the label “app=nginx".
root@master:/kube# kubectl run test --image=nginx -l app=nginx
pod/test created
root@master:/kube# kubectl get pods -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
test 1/1 Running 0 10s 10.244.0.19 master <none> <none> app=nginx
root@master:/kube#
root@master:/kube# kubectl exec -it test sh -- curl 10.244.0.7
^Ccommand terminated with exit code 130
root@master:/kube#
Not accessible. This policy is deployed to production namespace, so pods from other namespaces are not allowed.
Allow/limit Traffic to Pod from "dev" namespace:
Creating a "dev" namespace.
root@master:/kube# kubectl create ns dev
namespace/dev created
root@master:/kube#
Label the namespace as "env=dev".
root@master:/kube# kubectl describe ns dev
Name: dev
Labels: env=dev
kubernetes.io/metadata.name=dev
Annotations: <none>
Status: Active
No resource quota.
No LimitRange resource.
root@master:/kube#
root@master:/kube# cat ns_allow.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-different-namespace-policy
namespace: production
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
app: nginx
namespaceSelector:
matchLabels:
env: dev
root@master:/kube#
root@master:/kube# kubectl get networkpolicy -n production
NAME POD-SELECTOR AGE
allow-different-namespace-policy app=nginx 18s
root@master:/kube#
root@master:/kube# kubectl describe networkpolicy allow-different-namespace-policy -n production
Name: allow-different-namespace-policy
Namespace: production
Created on: 2022-07-20 10:52:30 -0700 MST
Labels: <none>
Annotations: <none>
Spec:
PodSelector: app=nginx
Allowing ingress traffic:
To Port: <any> (traffic allowed to all ports)
From:
NamespaceSelector: env=dev
PodSelector: app=nginx
Not affecting egress traffic
Policy Types: Ingress
root@master:/kube#
Lets create a test pod under "dev" namespace with label "app=nginx".
root@master:/kube# kubectl run test --image nginx -l app=nginx -n dev
pod/test created
root@master:/kube#
root@master:/kube# kubectl get pods -n dev -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
test 1/1 Running 0 19s 10.244.0.20 master <none> <none> app=nginx
root@master:/kube#
root@master:/kube# kubectl exec -it test -n dev sh -- curl 10.244.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@master:/kube#
It works.
Comments
Post a Comment