Knowledge Search


×
 

[Contrail] How to verify network routing isolation for Kubernetes Namespaces

  [KB35123] Show Article Properties


Summary:

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.

Solution:

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:

  • Traffic is not isolated between non-isolated NS
  • Traffic is isolated between an isolated NS and all other tenant in the cluster
  • Traffic is not isolated in same NS 


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.

Related Links: