Skip to content
This repository has been archived by the owner on Apr 25, 2024. It is now read-only.

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Defining a Network Policy

What is Network Policy?

Kubernetes Network Policy objects allow for fine-grained network policy enforcement, ensuring that traffic within your Kubernetes cluster can only flow in the direction that you specify. As an example, if we take a scenario where Kubernetes namespaces are used to enforce boundaries between products, or even enforce boundaries between different environments (e.g. development vs production), network policies can be configured to ensure no unauthorized network traffic is allowed beyond its boundary. Think of it as being similar to applying Security Groups in the AWS world.

Implementations

Network policies are implemented by an add-on; there are several available. Any of these solutions allow you to specify a network policy and then enforce the rules while your services are running.

Calico

Calico is an open-source plugin that implements pod networking and Network Policy.

Weave Net

Weave Net is an open-source plugin that implements pod networking and Network Policy.

If you’re using Weave Cloud you can visualize your container networks and services all from a single dashboard and also configure monitoring to alert you about any suspicious network activity.

Enforcing network isolation

You must install one of the above Network Policy add-ons before continuing. Then we will configure Kubernetes Network Policies.

We will create a namespace, deploy some test pods into it, and see the before and after effects of configuring a Network Policy, which will be enforced by the add-on you just installed.

All configuration files for this chapter are in the network-policies directory. Make sure you change to that directory before giving any commands in this chapter.

Precheck

  1. Create a namespace:

    $ kubectl create ns ns-1
    namespace "ns-1" created
  2. Deploy a container into namespace ns-1 that will expose an http endpoint, and log all requests it receives. First, create a Deployment, ReplicaSet and Pod using the command:

    $ kubectl run --namespace=ns-1 http-echo --image=solsson/http-echo --env="PORT=80" --port=80
    deployment "http-echo" created
  3. Label the pod (we will use labels as part of defining network policies):

    $ kubectl label po --selector=run=http-echo --namespace=ns-1 app=http-echo
    pod "http-echo-1790350443-z2v7n" labeled
  4. Create a Service to expose the pod:

    $ kubectl expose --namespace=ns-1 deployment http-echo --port=80
    service "http-echo" exposed

    Monitor the logs of the deployed container by querying the name of the pod defined with the label run=http-echo, then passing it to the kubectl logs command:

    kubectl get po \
      --selector=run=http-echo \
      --namespace=ns-1 \
      -o jsonpath='{.items[*].metadata.name}' | \
      xargs kubectl logs -f --namespace=ns-1

    This command will sit silently until http-echo logs a request.

    Let’s say this is shell 1.

  5. In another shell, say shell 2, deploy a second container:

    $ kubectl run \
      --namespace=ns-1 \
      -i --tty \
      busybox \
      --image=busybox \
      --restart=Never \
      -- sh
    If you don't see a command prompt, try pressing enter.
    / #
  6. We will now attempt to call the http-echo pod from our busybox pod by performing an HTTP POST . As we have no network policies in place, we should see the following command return successfully with a 200 response, along with a log message being output in the http-echo shell window:

    / # wget -S http://http-echo.ns-1.svc.cluster.local/test --post-data '{"message":"hello"}' -O test
    Connecting to http-echo.ns-1.svc.cluster.local (100.71.77.153:80)
      HTTP/1.1 200 OK
      X-Powered-By: Express
      Content-Type: application/json; charset=utf-8
      Content-Length: 533
      ETag: W/"215-KyoPN1JoGjQlzW9TxpIay22VPF8"
      Date: Thu, 26 Oct 2017 00:53:21 GMT
      Connection: close
    
    test                 100% |*************************************************************************************************|   533   0:00:00 ETA

    HTTP POST request succeeds.

Create default network policy

Let’s now create a Network Policy, but we will not configure any rules which by default will deny all traffic within the namespace. Leaving the 2 shells open from the previous steps, run the following in another shell, say shell 3:

$ kubectl create -f templates/deny-all-by-default-network-policy.yaml --namespace=ns-1
networkpolicy "deny-all-by-default" created

When running the following command again in shell 2, we should see it eventually timeout and fail (note that rather than waiting for it to time out, you can press Ctrl + C to quit after about 10 seconds once satisfied that no response will be returned):

/ # wget -S http://http-echo.ns-1.svc.cluster.local/test --post-data '{"message":"hello"}' -O test
Connecting to http-echo.ns-1.svc.cluster.local (100.64.161.56:80)
wget: can't connect to remote host (100.64.61.223): Connection timed out

Create network policy with a rule

We will now delete the NetworkPolicy that we just created, and create a new NetworkPolicy with a rule defined. If you cat templates/allow-network-policy.yaml you will see the following rule defined:

spec:
  podSelector:
    matchLabels:
      app: http-echo
  ingress:
    - from:
      - podSelector:
          matchLabels:
            app: busybox

The rule above is stating that for every pod that has the label app: http-echo defined, allow access to it from pods that have the label app: busybox defined.

Run the following in shell 3 to remove the deny all by default rule, and replace with the above allow rule:

$ kubectl delete netpol deny-all-by-default --namespace=ns-1
networkpolicy "deny-all-by-default" deleted
$ kubectl create -f templates/allow-network-policy.yaml --namespace=ns-1
networkpolicy "allow" created

If we repeat the following command in shell 2, the call should still timeout and fail (again, you can press CTRL-C to quit after 10 seconds rather than waiting for the full timeout to occur):

/ # wget -S http://http-echo.ns-1.svc.cluster.local/test --post-data '{"message":"hello"}' -O test
Connecting to http-echo.ns-1.svc.cluster.local (100.64.161.56:80)
wget: can't connect to remote host (100.64.61.223): Connection timed out

Why is this still failing even after creating a rule? It is failing because we configured the rule so that only pods with the label app: busybox are authorized to call pods with the label app: http-echo. Let’s go ahead and label our busybox pod on shell 3:

/ # kubectl label po --selector=run=busybox --namespace=ns-1 app=busybox
pod "busybox" labeled

Repeating the test in shell 2 again should now be successful:

/ # wget -S http://http-echo.ns-1.svc.cluster.local/test --post-data '{"message":"hello"}' -O test
Connecting to http-echo.ns-1.svc.cluster.local (100.64.161.56:80)
  HTTP/1.1 200 OK
  X-Powered-By: Express
  Content-Type: application/json; charset=utf-8
  Content-Length: 536
  ETag: W/"218-xgvU8WZSN+2SEyOX6Q2R/AhLuRM"
  Date: Thu, 26 Oct 2017 02:15:32 GMT
  Connection: close

test                100% |*************************************************************************************************|   534   0:00:00 ETA

Teardown

Remove all the resources and the namespace using the command:

$ kubectl delete ns ns-1
namespace "ns-1" deleted

You are now ready to continue on with the workshop!

button continue developer

button continue operations

Go to Developer Index

Go to Operations Index