Kubeless on Packet Cloud
In this post we’ll walk thought setting up Kubeless on a Kubernetes cluster running on Packet bare metal cloud.
Kubeless is a Kubernetes-native serverless framework that lets you deploy small bits of code (functions) without having to worry about the underlying infrastructure.
Kubernetes is the premier orchestration platform for managing containerized applications across multiple hosts. Originally developed at Google, the project has been contributed the Cloud Native Computing Foundation (CNCF).
Packet is a bare metal cloud platform built for developers. The platform brings the promise of the virtualized cloud to bare metal with premium Intel and ARMv8 based server configurations.
Setting up a Kubernetes cluster
In this section we will quickly go over the creation of a Kubernetes cluster on Packet cloud. Head over to https://www.packet.net/ and sign up for a account. Packet cloud is very happy to support our users with a 25 USD credit to try out Kubeless. Use the promo code kubeless25
to avail these credits.
Once you’ve logged in add your personal SSH key under the SSH Keys section.
Set up the master node
From the Packet cloud create a new project named Kubernetes
and deploy a new server named kube-master
. As the name suggests, this we’ll configure this as the master node of the Kubernetes cluster.
Log into the kube-master
server using SSH and execute the following command sequence to install the required components to the server.
$ apt-get update && apt-get install -y apt-transport-https
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" >> /etc/apt/sources.list.d/kubernetes.list
$ apt-get update && apt-get install -y docker.io kubelet kubeadm kubectl kubernetes-cni
$ swapoff -a && apt-get install linux-image-$(uname -r)
Next, use kubeadm
to initialize the server as the master node.
$ kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=$(ip address show label bond0:0 | sed -n 's/[ ]*inet \([^\/]*\).*/\1/p') --kubernetes-version stable-1.8
The kubeadm init
command execution will display the kubeadm join
command that should be used to join nodes to the cluster. Please make a note of this command before continuing.
Next, create a regular user named packet
.
$ useradd -G sudo -m packet
$ passwd packet
Switch to the packet
account with su — packet
and execute,
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
Next, we should deploy a pod network to the cluster. Flannel is an overlay network provider . To install the latest release the flannel pod network execute the following command sequence:
$ FLANNEL_RELEASE=v0.9.1
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/$FLANNEL_RELEASE/Documentation/kube-flannel.yml
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/$FLANNEL_RELEASE/Documentation/k8s-manifests/kube-flannel-rbac.yml
Set up worker nodes
From the Packet cloud console create two more servers named kube-worker-1
and kube-worker-2
. Login to each of these nodes and execute the following commands to set them up:
$ apt-get update && apt-get install -y apt-transport-https
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" >> /etc/apt/sources.list.d/kubernetes.list
$ apt-get update && apt-get install -y docker.io kubelet kubeadm kubectl kubernetes-cni
$ swapoff -a && apt-get install linux-image-$(uname -r)
Next, invoke the kubeadm join
command on each worker node to join the Kubernetes cluster. The same command that was obtained earlier from the output of kubeadm init
command on the master node.
From this point, unless specified otherwise, all listed commands should be executed on the master node as the packet
user.
Check the status of the nodes in the cluster by executing the following command :
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-master Ready master 10m v1.8.4
kube-worker-1 Ready <none> 4m v1.8.4
kube-worker-2 Ready <none> 31s v1.8.4
Here you can see that our Kubernetes cluster consists of a master and two worker nodes and you could just as easily add more worker nodes to the cluster.
Setting up an Ingress controller
To allow inbound connections to reach the cluster services we should install a ingress controller to the cluster. The easiest way to install an ingress controller is using the helm
client.
Helm is a package manager for Kubernetes and is a tool to manage pre-configured packages known as Charts to a Kubernetes cluster.
Install the latest version of the helm
client on the master node:
$ HELM_RELEASE=v2.7.2
$ wget -c https://storage.googleapis.com/kubernetes-helm/helm-${HELM_RELEASE}-linux-amd64.tar.gz
$ tar zxf helm-${HELM_RELEASE}-linux-amd64.tar.gz --strip 1 linux-amd64/helm
$ chmod +x helm
$ sudo mv helm /usr/local/bin/helm
On clusters with role-based access control (RBAC) enabled, we need to create a service account for tiller with the cluster-admin
role and specify it while initializing tiller. Execute the following commands to create the service account with the required permissions.
$ cat > rbac-config.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
EOF
$ kubectl create -f rbac-config.yaml
Now that a service account is created, deploy tiller
to the cluster with:
$ helm init --service-account tiller
We can now install the ingress controller simply by deploying the stable/nginx-ingress
chart to the cluster using the helm
CLI:
$ helm install --name nginx-ingress stable/nginx-ingress --set rbac.create=true,controller.service.type=NodePort,controller.service.nodePorts.http=30080
With the above command the ingress controller exposes port 30080
of the master node outside the cluster. Any services deployed on the cluster which have an ingress endpoint (kubectl get ingress
) can be reached externally at this port.
To learn more about Kubernetes on Packet cloud, check out https://help.packet.net/solutions/platforms/kubernetes.
Installing Kubeless
Grab the latest release of the Kubeless CLI and use the following command sequence to install it to the master node of your cluster.
$ KUBELESS_RELEASE=v0.3.0
$ sudo apt-get install -y unzip
$ wget -c https://github.com/kubeless/kubeless/releases/download/${KUBELESS_RELEASE}/kubeless_linux-amd64.zip
$ unzip kubeless_linux-amd64.zip
$ chmod +x bundles/kubeless_linux-amd64/kubeless
$ sudo mv bundles/kubeless_linux-amd64/kubeless /usr/local/bin/
Next, download the Kubeless deployment manifest,
$ curl -LO https://github.com/kubeless/kubeless/releases/download/${KUBELESS_RELEASE}/kubeless-rbac-${KUBELESS_RELEASE}.yaml
Our Kubernetes cluster on Packet does not have support for the PersistentVolumeClaim
storage type. As a temporary measure we’ll need to edit the manifest and remove it’s usage.
P.S. It is not advisable to remove these persistent volumes on a production cluster as deleting/restarting Kubeless would result in a complete loss of the application state and all deployed functions.
Open the downloaded manifest file kubeless-rbac-${KUBELESS_RELEASE}.yaml
and deleted the volumeMounts
and volumeClaimTemplates
definitions for the kafka
and zookeeper
StatefulSets
and deploy the manifest to the cluster using the following commands:
$ kubectl create namespace kubeless
$ kubectl create -f kubeless-rbac-${KUBELESS_RELEASE}.yaml
Check the status of the deployment with the following command:
$ kubectl get pods --namespace kubeless
You should have Kubeless successfully installed to the cluster and notice a CustomResourceDefinition
(CRD) named functions.k8s.io
added.
$ kubectl get crd
NAME AGE
functions.k8s.io 39m
Deploying functions
Kubeless currently supports various of language runtimes for writing functions and you could also add support for a new runtime.
For this demonstration we’ll use the Python runtime to write a simple greeting
function and deploy it to the cluster using the kubeless
CLI.
Create a file named hello.py
with a function named greeting
as shown below:
def greeting():
return "hello, world!"
Save this file and deploy the function with the following command:
$ kubeless function deploy greeting --runtime python2.7 \
--from-file hello.py \
--handler hello.greeting \
--trigger-http
Check the deployment status of the function:
$ kubeless function ls
After the deployment is in the READY
state, execute the following command to call the function and you should see the output of the function, i.e. the text hello, world!
, printed out.
$ kubeless function call greeting
As we installed an Ingress controller (via the stable/nginx-ingress
chart), we can set up an ingress endpoint for our function, allowing us to call the function externally over the internet.
$ kubeless ingress create greeting --function greeting
Execute the following command to get the list of ingress routes currently set up and the host name for each of these routes.
$ kubeless ingress ls
+----------+-----------+----------------------------+------+--------------+--------------+
| NAME | NAMESPACE | HOST | PATH | SERVICE NAME | SERVICE PORT |
+----------+-----------+----------------------------+------+--------------+--------------+
| greeting | default | greeting.10.80.55.1.nip.io | / | greeting | 8080 |
+----------+-----------+----------------------------+------+--------------+--------------+
Kubeless creates a default host name in form of .nip.io
. Alternatively, you can provide a real host name with --hostname
flag to the kubeless ingress create
command. Please refer to the ingress support documentation for more details.
You can now call this function externally (over the internet) with:
$ curl --header "Host: FUNCTION_HOST" MASTER_NODE_IP_ADDRESS:30080
Replace the placeholders FUNCTION_HOST
and MASTER_NODE_IP_ADDRESS
with the host name of the ingress route to the function and the IP address of the master node.
Upon execution you should see the text hello, world!
printed out on the terminal.
With Kubeless we were able to effortless deploy a simple function to the Kubernetes infrastructure without having to worry about web servers, virtual host configurations and so on.
This was a basic demonstration of deploying a function and executing it over the internet. To get a glimpse of the use-cases you could unlock using Kubeless watch the following demo video.
To learn more about Kubeless refer to the documentation and remember to join us in the #kubeless channel at the Bitnami OSS Slack community. Visit http://slack.oss.bitnami.com/ for an invite to join the community. We would love to hear from you.