Kubernetes default networking model mandates that each pod can talk to every other pod in the cluster. This is convenient in design and implementations. But in practice, there are usually requirements that restrict the direct access between pods belonging to different namespaces (NS) for security reasons. Contrail supports additional custom networking models that make available the many rich features of Contrail to the users of the Kubernetes cluster. One such feature is 'Network Isolation for Kubernetes Namespaces'. For more information, refer to the technical documentation on Namespace Isolation Mode
In this article provides an example in a lab environment for verifying how the routing isolation works.
Create a non-isolated namespace and an isolated namespace:
---- $ cat ns-non-isolated.yaml apiVersion: v1 kind: Namespace metadata: name: ns-non-isolated $ cat ns-isolated.yaml apiVersion: v1 kind: Namespace metadata: annotations: "opencontrail.org/isolation": "true" name: ns-isolated $ kubectl apply -f ns-non-isolated.yaml namespace/ns-non-isolated created $ kubectl apply -f ns-isolated.yaml namespace/ns-isolated created $ kubectl get ns | grep isolate ns-isolated Active 79s ns-non-isolated Active 73s ----
In both NS and the default NS, create a webserver deployment to launch a webserver pod:
---- #deploy-webserver-do.yaml apiVersion: apps/v1 kind: Deployment metadata: name: webserver labels: app: webserver spec: replicas: 1 selector: matchLabels: app: webserver matchExpressions: - {key: app, operator: In, values: [webserver]} template: metadata: name: webserver labels: app: webserver spec: containers: - name: webserver image: pingdocker/contrail-webserver securityContext: privileged: true ports: - containerPort: 80 ---- ---- $ kubectl apply -f deploy-webserver-do.yaml -n default deployment.extensions/webserver created $ kubectl apply -f deploy-webserver-do.yaml -n ns-non-isolated deployment.extensions/webserver created $ kubectl apply -f deploy-webserver-do.yaml -n ns-isolated deployment.extensions/webserver created $ kubectl get pod -o wide -n default NAME READY STATUS ... IP NODE ... webserver-85fc7dd848-tjfn6 1/1 Running ... 10.47.255.242 cent333 ... $ kubectl get pod -o wide -n ns-non-isolated... NAME READY STATUS ... IP NODE ... webserver-85fc7dd848-nrxq6 1/1 Running ... 10.47.255.248 cent222 ... $ kubectl get pod -o wide -n ns-isolated NAME READY STATUS ... IP NODE ... webserver-85fc7dd848-6l7j2 1/1 Running ... 10.47.255.239 cent222 ... ----
Ping between all pods in 3 namespaces :
:
---- #default ns to non-isolated new ns: succeed $ kubectl -n default exec -it webserver-85fc7dd848-tjfn6 -- ping 10.47.255.248 PING 10.47.255.248 (10.47.255.248): 56 data bytes 64 bytes from 10.47.255.248: seq=0 ttl=63 time=1.600 ms ^C --- 10.47.255.248 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 1.600/1.600/1.600 ms #default ns to isolated new ns: fail $ kubectl -n default exec -it webserver-85fc7dd848-tjfn6 -- ping 10.47.255.239 PING 10.47.255.239 (10.47.255.239): 56 data bytes ^C --- 10.47.255.239 ping statistics --- 3 packets transmitted, 0 packets received, 100% packet loss ----
The test result shows that bidirectional communication between two non-isolated namespaces (namespace `ns-non-isolated` and `default` in this case) works, but traffic from non-isolated NS (`default` NS) toward the isolated NS does not pass through. Ahat about traffic within the same isolated NS?
With the power of the 'deployment', we can quickly test it: in isolated NS `ns-isolated`, clone one more pod by `scale` the deployment with `replicas=2` and ping between the 2 pods:
---- $ kubectl scale deployment webserver --replicas=2 $ kubectl get pod -o wide -n ns-isolated NAME READY STATUS RESTARTS AGE IP NODE webserver-85fc7dd848-6l7j2 1/1 Running 0 8s 10.47.255.239 cent222 webserver-85fc7dd848-215k8 1/1 Running 0 8s 10.47.255.238 cent333 $ kubectl -n ns-isolated exec -it webserver-85fc7dd848-6l7j2 -- ping 10.47.255.238 PING 10.47.255.238 (10.47.255.238): 56 data bytes 64 bytes from 10.47.255.238: seq=0 ttl=63 time=1.470 ms ^C --- 10.47.255.238 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 1.470/1.470/1.470 ms ----
The ping packet passes through now. To summarize the test results:
Note: pod-level isolation can be achieved via Kubernetes network policy, or security groups in Contrail. However, this is a different topic and beyond the scope of this article.