3 Using Calico

This section provides examples of using the Kubernetes and Calico network policies to define network policies for traffic in an NGINX web server application. The Kubernetes network policy example uses the network policy available in the Kubernetes Network Policy API. The Calico network policy example uses extensions available in the Calico policy, and provides more options for setting network policies.

Kubernetes Network Policy

This section shows a basic example of using the Kubernetes network policy. More examples of the Kubernetes network policy are available in the upstream Calico documentation.

The example defines a NetworkPolicy to disable all network traffic between pods in a namespace. NetworkPolicy resources are created to define rules to specify allowed network traffic between the application pods. If a NetworkPolicy in a namespace selects a pod, that pod rejects any connections that aren't allowed by the NetworkPolicy.

To create a test application to use a Kubernetes network policy:

  1. Create a Kubernetes namespace for the test application:

    kubectl create namespace myapp
  2. Create an NGINX pod with label of app: nginx. This is created in the myapp namespace. On a control plane node, create a file named nginx.yaml and copy the following into the file.

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      namespace: myapp
      labels:
        app: nginx
    spec:
        containers:
        - name: nginx
          image: container-registry.oracle.com/olcne/nginx:1.17.7 
          ports:
          - containerPort: 80
  3. Start the NGINX pod:

    kubectl apply -f nginx.yaml
  4. Create an Oracle Linux 9 pod with label of app: nginx. This is created in the myapp namespace. Create a file named ol9.yaml and copy the following into the file:

    apiVersion: v1
    kind: Pod
    metadata:
      name: ol9
      namespace: myapp
      labels:
        app: nginx
    spec:
      containers:
      - name: ol9
        command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
        image: container-registry.oracle.com/os/oraclelinux:9-slim
  5. Start the pod using the kubectl command:
    kubectl apply -f ol9.yaml
  6. You can see the nginx-app and ol9 pods are running using the kubectl get pods command:

    kubectl get pods --namespace myapp -o wide

    The output looks similar to:

    NAME    READY   STATUS    RESTARTS   AGE   IP              NODE                        ...
    nginx   1/1     Running   0          38s   10.244.140.68   worker1.example.com         ...
    ol9     1/1     Running   0          22h   10.244.80.196   worker2.example.com         ...
  7. Mount the Oracle Linux 9 pod, ol9, and run curl to connect to the NGINX server pod, nginx, using the IP address assigned to the pod.
    kubectl exec -it ol9 --namespace myapp -- curl 10.244.140.68

    The output looks similar to:

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        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>
  8. Create a NetworkPolicy to deny all traffic to all pods in the myapp namespace. Create a file named deny-all.yaml and copy the following into the file.
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: default-deny
      namespace: myapp
    spec:
      podSelector:
        matchLabels: {}
  9. Create the NetworkPolicy using the kubectl command:
    kubectl apply -f deny-all.yaml

    Tip:

    You can get a list of all NetworkPolicies in the myapp namespace using:

    kubectl get networkpolicies --namespace myapp

    In addition, adding the -o yaml option lists details about the NetworkPolicies.

  10. Mount the Oracle Linux 9 pod, ol9, again and run curl to connect to the NGINX server pod.
    kubectl exec -it ol9 --namespace myapp -- curl 10.244.140.68

    This time no results are returned as the traffic between pods on that namespace isn't allowed. You can enter Ctrl+C to exit the command.

  11. Create a NetworkPolicy to allow ingress traffic on port 80 for pods in the myapp namespace. This lets pods connect to the NGINX server. Create a file named ingress.yaml and copy the following into the file:
    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: myapp-ingress
      namespace: myapp
    spec:
      podSelector:
        matchLabels:
          app: nginx
      ingress:
      - from:
        - podSelector:
            matchLabels:
              app: nginx 
        ports:
          - port: 80
  12. Create the NetworkPolicy using the kubectl command:
    kubectl apply -f ingress.yaml
  13. Mount the Oracle Linux 9 pod, ol9, again and run curl to connect to the NGINX server pod.
    kubectl exec -it ol9 --namespace myapp -- curl 10.244.140.68

    The NGINX page is now returned as ingress is allowed to the pods.

  14. You can delete the resources created in this Calico test using:

    kubectl delete pod --namespace myapp nginx 
    kubectl delete pod --namespace myapp ol9 
    kubectl delete networkpolicies --namespace myapp myapp-ingress 
    kubectl delete networkpolicies --namespace myapp default-deny 
    kubectl delete namespace myapp

Calico Network Policy

This section shows a basic example of using the Calico policy extensions for the Kubernetes Network Policy API. More examples of the Calico policy are available in the upstream documentation.

The example defines a GlobalNetworkPolicy to disable all network traffic, except for Kubernetes system and Calico pods. NetworkPolicy resources are created to define rules to specify allowed network traffic between the application pods. Any other pod traffic isn't allowed.

To create a test application to use a Calico network policy:

  1. Create a Kubernetes namespace for the test application:

    kubectl create namespace myapp
  2. Create an NGINX pod with label of app: nginx. This is created in the myapp namespace. On a control plane node, create a file named nginx.yaml and copy the following into the file.

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      namespace: myapp
      labels:
        app: nginx
    spec:
        containers:
        - name: nginx
          image: container-registry.oracle.com/olcne/nginx:1.17.7 
          ports:
          - containerPort: 80
  3. Start the NGINX pod:

    kubectl apply -f nginx.yaml
  4. Create an Oracle Linux 9 pod with label of app: nginx. This is created in the myapp namespace. Create a file named ol9.yaml and copy the following into the file:

    apiVersion: v1
    kind: Pod
    metadata:
      name: ol9
      namespace: myapp
      labels:
        app: nginx
    spec:
      containers:
      - name: ol9
        command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
        image: container-registry.oracle.com/os/oraclelinux:9-slim
  5. Start the pod using the kubectl command:
    kubectl apply -f ol9.yaml
  6. You can see the nginx-app and ol9 pods are running using the kubectl get pods command:

    kubectl get pods --namespace myapp -o wide

    The output looks similar to:

    NAME    READY   STATUS    RESTARTS   AGE   IP              NODE                        ...
    nginx   1/1     Running   0          38s   10.244.140.68   worker1.example.com         ...
    ol9     1/1     Running   0          22h   10.244.80.196   worker2.example.com         ...
  7. Mount the Oracle Linux 9 pod, ol9, and run curl to connect to the NGINX server pod, nginx, using the IP address assigned to the pod.
    kubectl exec -it ol9 --namespace myapp -- curl 10.244.140.68

    The output looks similar to:

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        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>
  8. Create a GlobalNetworkPolicy to deny all traffic to all pods in the namespaces that aren't in the kube-system, calico-system or calico-apiserver namespaces. Create a file named deny-all.yaml and copy the following into the file.
    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: default-deny
    spec:
      selector: projectcalico.org/namespace not in  {'kube-system', 'calico-system', 'calico-apiserver'}
      types:
      - Ingress
      - Egress
  9. Create the GlobalNetworkPolicy using the kubectl command:
    kubectl apply -f deny-all.yaml

    Tip:

    You can get a list of all Calico GlobalNetworkPolicies in the myapp namespace using:

    kubectl get globalnetworkpolicies.crd.projectcalico.org --namespace myapp

    In addition, adding the -o yaml option lists details about the GlobalNetworkPolicies.

  10. Mount the Oracle Linux 9 pod, ol9, again and run curl to connect to the NGINX server pod.
    kubectl exec -it ol9 --namespace myapp -- curl 10.244.140.68

    This time no results are returned as the traffic between pods on that namespace isn't allowed. You can enter Ctrl+C to exit the command.

  11. Create a NetworkPolicy to allow ingress traffic on port 80 for pods in the myapp namespace. This lets pods connect to the NGINX server. Create a file named ingress.yaml and copy the following into the file:
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: allow-nginx-ingress
      namespace: myapp
    spec:
      selector: app == 'nginx'
      types:
      - Ingress
      ingress:
      - action: Allow
        protocol: TCP 
        source:
          selector: app == 'nginx'
        destination:
          ports:
            - 80
  12. Create the NetworkPolicy using the kubectl command:
    kubectl apply -f ingress.yaml

    Tip:

    You can get a list of all Calico NetworkPolicies in the myapp namespace using:

    kubectl get networkpolicies.crd.projectcalico.org --namespace myapp

    In addition, adding the -o yaml option lists details about the NetworkPolicies.

  13. Mount the Oracle Linux 9 pod, ol9, again and run curl to connect to the NGINX server pod.
    kubectl exec -it ol9 --namespace myapp -- curl 10.244.140.68

    No results are returned as egress traffic between pods on that namespace isn't allowed. You can enter Ctrl+C to exit the command.

  14. Create a NetworkPolicy to allow egress traffic for pods in the myapp namespace. Create a file named egress.yaml and copy the following into the file:
    apiVersion: projectcalico.org/v3
    kind: NetworkPolicy
    metadata:
      name: allow-nginx-egress
      namespace: myapp
    spec:
      selector: app == 'nginx'
      types:
      - Egress
      egress:
      - action: Allow
  15. Create the NetworkPolicy using the kubectl command:
    kubectl apply -f egress.yaml
  16. Mount the Oracle Linux 9 pod, ol9, again and run curl to connect to the NGINX server pod.
    kubectl exec -it ol9 --namespace myapp -- curl 10.244.140.68

    The NGINX page is now returned as both ingress and egress is allowed for the pods.

  17. You can delete the resources created in this Calico test using:

    kubectl delete pod --namespace myapp nginx 
    kubectl delete pod --namespace myapp ol9 
    kubectl delete networkpolicies.crd.projectcalico.org --namespace myapp default.allow-nginx-egress 
    kubectl delete networkpolicies.crd.projectcalico.org --namespace myapp default.allow-nginx-ingress
    kubectl delete globalnetworkpolicies.crd.projectcalico.org --namespace myapp default.default-deny 
    kubectl delete namespace myapp