Select Page

Mastering Kubernetes with Cilium: Empowering L7 Traffic Control

by | Sep 5, 2023

With the new release of the Cilium CNI on our Kubernetes Service you’ll get the ability to filter traffic based on L7 properties. It’s very powerful and can help a lot with your services security.

In this tutorial, we’ll be securing an API endpoint to allow access only to specific routes by our client. All other traffic won’t even be forwarded to the service, thus keeping the load of the API as low as possible.

Prerequisites

Before you get started, you’ll need the following:

  1. A Kubernetes cluster up and running with Cilium.
  2. kubectl command-line tool installed and configured to communicate with your cluster.
  3. Basic knowledge of Kubernetes pods, services, and namespaces.

Creating API + API-Client

$ kubectl apply -f https://gist.github.com/modzilla99/0cbdd39cc838e752ae8cdb5ec3cdd03a/raw/adb7218bb1e9195c42192d71809f6f7043e50cd7/deploy.yaml
configmap/apiconfig created
deployment.apps/api created
service/api created
pod/api-client created

We’ve now created a service called “api” that is bound to the “api” deployment. It has two routes. The route /secret should be private and /greetings should be publicly accessible. Since we don’t have any NetworkPolcies defined, both routes are accessible by any pod running in the cluster.

Testing the API

So let’s try out the API first:

$ kubectl exec -it api-client -- curl -H 'X-Security-Header: mysecret' api/secret/mysecret
{
  "name": "mysecret",
  "secret": "syferghewg"
}
$ kubectl exec -it api-client -- curl api/greetings/World
Greetings, World!
$ kubectl exec -it api-client -- curl google.com
The document has moved

 

As you can see the API is fully accessible without any restrictions and the api-client pod has full access to the web.

Limiting Access

In order to minimize access, we aim to restrict the pods access exclusively to our api and api.github.com. The subsequent NetworkPolicy will effectively accomplish this goal:

---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-client-egress
spec:
  endpointSelector:
    # Apply policy to api client
    matchLabels:
      app: client
      type: production
  ingress:
  # Drop all incoming traffic
  - {}
  egress:
  # Allow API acccess to GitHub only via HTTPs
  - toFQDNs:
    - matchName: api.github.com
    toPorts:
    - ports:
      - port: "443"
  # Allow access to our API
  - toEndpoints:
    - matchLabels:
        app: api
        type: production
    toPorts:
    - ports: 
      - port: "6090"
        protocol: TCP
  # Allow DNS queries
  - toEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: kube-system
        k8s-app: kube-dns
    toPorts:
    - ports:
      - port: "53"
    rules:
      dns:
      - matchPattern: "*"

Now the pod can only talk to our and the GitHub API as well as query the kubernetes DNS server. Any request to other resources will fail now:

$ kubectl exec -it api-client -- curl -4 --connect-timeout 3 -v google.com
* processing: google.com
* Trying 142.250.184.238:80...
* ipv4 connect timeout after 2974ms, move on!
* Failed to connect to google.com port 80 after 3001 ms: Timeout was reached
* Closing connection
curl: (28) Failed to connect to google.com port 80 after 3001 ms: Timeout was reached
$ kubectl exec -it api-client -- curl -4 https://api.github.com/user
{
  "message": "Requires authentication",
  "documentation_url": "https://docs.github.com/rest/users/users#get-the-authenticated-user"
}

Let’s secure secure our api next. We don’t want the pod to able to communicate externally and it should only allow ingress traffic to our two routes. Since the /greetings Endpoint is supposed to be public, we’ll open the access to anyone whilst restricting the access to the /secret Route to our api-client.

---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-api-ingress
spec:
  endpointSelector:
    matchLabels:
      app: api
      type: production
  egress:
  # Deny any external traffic
  - {}
  ingress:
  # Allow access to /secret route from our api client 
  - fromEndpoints:
    - matchLabels:
        app: client
        type: production
    toPorts:
    - ports:
      - port: "6090"
        protocol: TCP
      rules:
        http:
        - method: "GET"
          path: "/secret/.*"
          # Require HTTP header for authorization
          headers:
          - 'X-Security-Header: mysecret'
  # Allow access to /greetings route from anyone
  - toPorts:
    - ports:
      - port: "6090"
        protocol: TCP
      rules:
        http:
        - method: "GET"
          path: "/greetings/.*"

Now we can only access the /secret route with the required header and from the api-client pod:

$ kubectl exec -it api-client -- curl api/secret/mysecret
Access denied
$ kubectl exec -it api-client -- curl -H 'X-Security-Header: mysecret' api/secret/mysecret
{
  "name": "mysecret",
  "secret": "adasge53whbetn"
}

Conclusion

Cilium NetworkPolicies are a powerful way to control network traffic within your cluster. By defining rules for ingress and egress traffic, you can secure your applications and isolate them as needed. This tutorial covered the basics of creating and using NetworkPolicies, but you can create more complex policies to suit your specific needs.

Need help with this topic? Feel free to send us a message or subscribe to our newsletter for more content on the topic.

Don’t miss our newsletter
More about Kubernetes
ReadWriteMany (RWX) with the NFS Ganesha Provisioner

ReadWriteMany (RWX) with the NFS Ganesha Provisioner

Introduction You have the desire that your application needs to scale across multiple nodes for load balancing, but needs access to a common PVC? For this purpose, you need a PVC that is RWX-enabled. As part of our Managed Kubernetes Cluster, it is possible to create...

Resizing Persistent Volumes in Kubernetes

Resizing Persistent Volumes in Kubernetes

You want to resize a PersistentVolume (PV) in Kubernetes? In this tutorial, you'll learn how to do it. If you don't already know what a PV is and how you can create one, you should check out the tutorial Creating Persistent Volumes in Kubernetes first.   Let's...

Custom Connection Limit for Load Balancers

Custom Connection Limit for Load Balancers

You need to set a custom limit for incoming connections on your load balancer? Here you can learn how to achieve this! About the Connection Limit The connection limit specifies the maximum allowed number of connections per second for a load balancer listener (open...

Automatic Fedora CoreOS Updates for your Kubernetes

Automatic Fedora CoreOS Updates for your Kubernetes

You want automated Fedora CoresOS updates for your Kubernetes? And what do Zincati and libostree have to do with it? Here you will quickly see an overview! Fedora CoreOS is used as the operating system for many Kubernetes clusters. This operating system, which...

X-Forwarded-For and Proxy-Protocol

X-Forwarded-For and Proxy-Protocol

You want to know how to get the IP addresses of your clients in your Kubernetes cluster? In five minutes you have an overview! From HTTP client to application In the nginx-Ingress-Controller tutorial, we showed how to make an application publicly accessible. In the...

Kubernetes Alerting with Prometheus Alert manager

Kubernetes Alerting with Prometheus Alert manager

In a previous post, Sebastian explained how to monitor your Kubernetes cluster with the Prometheus Operator. This post builds on that and shows how to set up notifications via email and as push notifications with the Alert Manager. Install the Monitoring Stack with...

Logging with Loki and Grafana in Kubernetes

Logging with Loki and Grafana in Kubernetes

You already know the most important building blocks for starting your application from our Tutorial-Serie. Are you still missing metrics and logs for your applications? After this blog post, you can tick off the latter. Logging with Loki and Grafana in Kubernetes - an...

Manage Kubernetes Nodegroups

Manage Kubernetes Nodegroups

As of this week, our customers can use the "node group feature" for their NWS Managed Kubernetes Cluster plan. What are node groups and what can I do with them? Our seventh blog post in the series explains this and more. What are Node Groups? With node groups, it is...

Creating Persistent Volumes in Kubernetes

Creating Persistent Volumes in Kubernetes

You want to create a persistent volume in Kubernetes? Here you can learn how it works with Openstack Cinder in a NWS Managed Kubernetes plan. Pods and containers are by definition more or less ephemeral components in a Kubernetes cluster and are created and destroyed...

Monitoring Kubernetes with Prometheus

Monitoring Kubernetes with Prometheus

Monitoring - for many a certain love-hate relationship. Some like it, others despise it. I am one of those who tend to despise it, but then grumble when you can't see certain metrics and information. Regardless of personal preferences on the subject, however, the...