Orchestrating a Kubernetes-Managed VNF With Cloudify

DZone 's Guide to

Orchestrating a Kubernetes-Managed VNF With Cloudify

VNFs are helpful when diving into containers, so you should probably know how to integrate them with Kubernetes to streamline your container orchestration.

· Cloud Zone ·
Free Resource

An important use case for virtual network functions (VNF) is using container technology rather than OS virtualization. The advantages of containerization include agility, performance, and density/efficiency. Kubernetes (managing Docker containers) is the leading (and most capable) container management platform today, and the logical platform to use for technical exploration. In this post, we'll explore a Cloudify-orchestrated example of deploying a VNF as a microservice in Kubernetes.

The Quagga router is software that turns a Linux host into a router. Any Linux host with IP forwarding capability can function as a router simply by modifying the kernel routing table using standard shell commands (.e.g. IP route). Quagga builds on this capability and provides dynamic routing capability via various standard routing protocols, including OSPF, RIP, BGP, and others. This post explores the process of containerizing Quagga and deploying it using Kubernetes. In the project, Cloudify is used to run Kubernetes and deploys Quagga as a microservice using TOSCA modeling.

Containerization Issues

Docker containers (on Linux) typically run in their own network namespace. In practical terms, this means they have a network stack (including routing tables) independent from the host network stack. Generally, this is highly desirable, but in the case of a VNF that emulates a general purpose router, it is not desireable. Fortunately, Docker containers can be configured to use the host network stack when running in privileged mode. In the case of Quagga, the practical consequence is that the inter-routing procotols will be visible, and changes to the host routing table will actually cause the node to behave as expected. Taking this approach sacrifices networking isolation on the target host, but the use case justifies it. Kubernetes supports the starting of privileged containers, so the pod configuration is straightforward. The key properties are hostNetwork and securityContext:

 hostNetwork: true
     - name: quagga
 image: quagga
 workingDir: /root
 command: ["bash","/root/start.sh"]
     - containerPort: 80
 privileged: true
     - name: INTERFACES
 value: eth0,eth1
     - name: ROUTES

Beyond networking configuration, the initial configuration of static routes needs to be addressed. Note the command property in the preceding excerpt. This identifies the start.sh script as the startup command for the container. This example uses environment variables, defined in the env section, to configure initial static routes by updating the Quagga configuration file and starting the Quagga service.

 echo "interface $I" >> /etc/quagga/zebra.conf
for R in $ROUTES
 echo "ip route $R" >> /etc/quagga/zebra.conf
service quagga start
tail -f /dev/null

After the script runs, Quagga modifies the host routing tables. This example only addressed static routing, which is the basis for the dynamic routing protocol implementation.


A multi-node Kubernetes deployment is likely to want to constrain the location of the router in the cluster to access multiple interfaces. Kubernetes permits the labeling of nodes in a cluster with arbitrary values, and then requesting the placement algorithm to filter candidates based on the labels. This is one area Cloudify can provide value as part of the Kubernetes installation. See the Kubernetes example blueprint for a sample Cloudify orchestration. A simple extension to the schema and some additional logic can provide the needed functionality. The addition of a labels input to the start.py script for the Kubernetes node provides the labels:

 implementation: scripts/kubernetes/node/start.py
 <<: *kubernetes_environment
     - role: router

Naturally, the start.py script needs to be modified to add the --labels parameter for the hyperkube startup. Once done, Kubernetes is ready to filter once started.

The Router Microservice Definition

A separate Cloudify blueprint from the blueprint that started Kubernetes can be used to model the Quagga router. The blueprint is small enough to include:

 type: cloudify.nodes.DeploymentProxy
     - 'kubernetes_info'
 type: cloudify.kubernetes.Microservice
 name: nginx
 ssh_username: ubuntu
 ssh_keyfilename: /root/.ssh/agent_key.pem
     - file: resources/kubernetes/pod.yaml
     - type: cloudify.kubernetes.relationships.connected_to_master
 target: kubernetes_proxy

Since no overrides are specified for the microservice, the Cloudify blueprint is fairly trivial. It identifies the Kubernetes master node and pod.yaml file (excerpt at the beginning of the post), as well as ssh information for logging into the Kubernetes. The reason the login information is needed is this sample implementation relies on the kubectl command line tool on the master. The only additional modification needed for placement is to the pod.yaml file to target the router node:

 hostNetwork: true
 role: router
     - name: quagga
 image: quagga
 workingDir: /root


Kubernetes, Docker, and Cloudify work together seamlessly to create a containerized VNF platform that can deliver high availability, high performance, and high density, while retaining the benefits of a micrservices architecture.

Come Meet us at Mobile World Congress

We are going to be on the ground at Mobile World Congress in Barcelona talking all about Cloud Native Virtual Network Functions, vCPE, and more. Just and let's meet!

cloud, cloudify, container orchestration, kubernetes, vnf

Published at DZone with permission of Dewayne Filppi , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}