Serverless MicroK8s Kubernetes

Happy New Year!

Thinkpad, Code Keyboard and Novation Launchpap — my Christmas Setup 2015

At the end of the year 2018 I have discovered something what had blew my mind. Let’s see what is this.

MicroK8s from Ubuntu

What is this? Webpage says “Kubernetes in a snap that you can run locally”. This short description definitely sparked my attention, so I started to read more and following features attracted me even more:

  • Compliant (certified) with Kubernetes
  • Can be used in VM for CI/CD to tests Kubernetes
  • Allows to quick (below minute) setup on your workstation or laptop
  • You can launch Kubeflow on it

As a follow up of the last point, assuming that you have snap installed (which is a case by default in Ubuntu 18.04) you can install MicroK8s in a following way:

$ sudo snap install microk8s --classic`

which gives you access to the command kubectl with prefix microk8s (this is in purpose to avoid conflict:

$ microk8s.kubectl

If you do not have installed kubectl yet, you may simplify your life by making alias to kubectl command:

$ sudo snap alias microk8s.kubectl kubectl
$ kubectl auth can-i create pods
yes

Let’s test some available serverless solutions based on Kubernetes. Two most popular are Kubeless and Fission.

Kubeless

Kubeless, developed by Bitnami looks like a very robust solution with several very convincing features:

  • CLI compatible with AWS Lambda
  • Support for Python, Node.js, Ruby, PHP, Golang, .NET, Ballerina and custom routines
  • Plugin for Serverless framework

Installation process is described here: https://kubeless.io/docs/quick-start/#installation, and since MicroK8s by definition does not come with RBAC support, I picked non-RBAC Kubernetes cluster one.

Installation starts with creating namespace for kubeless:

$ kubectl create ns kubeless
namespace/kubeless created

For now everything is good :)

$ export RELEASE=$(curl -s https://api.github.com/repos/kubeless/kubeless/releases/latest | grep tag_name | cut -d '"' -f 4) 
$ kubectl create -f https://github.com/kubeless/kubeless/releases/download/$RELEASE/kubeless-non-rbac-$RELEASE.yaml
configmap/kubeless-config created
deployment.apps/kubeless-controller-manager created
serviceaccount/controller-acct created
customresourcedefinition.apiextensions.k8s.io/functions.kubeless.io created
customresourcedefinition.apiextensions.k8s.io/httptriggers.kubeless.io created
customresourcedefinition.apiextensions.k8s.io/cronjobtriggers.kubeless.io created

Good so far.

$ kubectl get pods -n kubeless
NAME READY STATUS RESTARTS AGE
kubeless-controller-manager-7c7bcb8db4-blww9 3/3 Running 0 50s
$ kubectl get deployment -n kubeless
NAME READY UP-TO-DATE AVAILABLE AGE
kubeless-controller-manager 1/1 1 1 6m15s
$ kubectl get customresourcedefinition
NAME CREATED AT
cronjobtriggers.kubeless.io 2019-01-04T21:35:37Z
functions.kubeless.io 2019-01-04T21:35:37Z
httptriggers.kubeless.io 2019-01-04T21:35:37Z

Still good. Time to install kubeless CLI:

$ curl -OL https://github.com/kubeless/kubeless/releases/download/$RELEASE/kubeless_$OS-amd64.zip && \
unzip kubeless_$OS-amd64.zip && \
sudo mv bundles/kubeless_$OS-amd64/kubeless /usr/local/bin/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 614 0 614 0 0 951 0 --:--:-- --:--:-- --:--:-- 951
100 7559k 100 7559k 0 0 3311k 0 0:00:02 0:00:02 --:--:-- 12.0M
Archive: kubeless_linux-amd64.zip
creating: bundles/kubeless_linux-amd64/
inflating: bundles/kubeless_linux-amd64/kubeless
[sudo] password for bluszcz:

And then installing first function (I am using python3.6):

$ cat test.py 
def hello(event, context):
print (event)
return event['data']
$ kubeless function deploy hello --runtime python3.6 --from-file test.py --handler test.hello
FATA[0000] Can not get kubernetes config: stat /home/bluszcz/.kube/config: no such file or directory 

Right… Let’s try to generate config:

$ microk8s.kubectl config view > $HOME/.kube/config$                                                                                

and rerun:

$ kubeless function deploy hello --runtime python3.6 --from-file test.py --handler test.hello
INFO[0000] Deploying function...
INFO[0000] Function hello submitted for deployment
INFO[0000] Check the deployment status executing 'kubeless function ls hello'

Voilà! Check if my function is available:

$ kubectl get functions
NAME AGE
hello 6m

So, let’s test if it works:

$ kubeless function call hello --data "Let's pray..."                                                                                 
Let's pray...

Yes, It works!. Any thought? In 5 minutes we have on our laptop running (based on Kubernetes) serverless platform! Fracking amazing. Simplicity and compatibility with AWS Lambda and Serverless framework will definitely make me spending more time with Kubeless.

Time to test the another solution.

Fission

Fission, competitive (provided by Platform8) solution has following features:

  • Supports for Python, NodeJS, Go, C#, PHP
  • Support Workflows is an open source framework that allows you to orchestrate a set of serverless functions without directly dealing with networking, message queues, (feature is still missing in Kubeless).
  • At the time writing of the article (first week of 2019) it does need RBAC installed, link to Github issue

Following a hint from the opened issue for the MicroK8s, I have “simulated” RBAC in my MicroK8s and started installation with helm:

$ helm install --name fission --namespace fission --set serviceType=NodePort,routerServiceType=NodePort https://github.com/fission/fission/releases/download/1.0-rc1/fission-all-1.0-rc1.tgz
NAME:   fission
LAST DEPLOYED: Sat Jan 5 00:44:31 2019
NAMESPACE: fission
STATUS: DEPLOYED
RESOURCES:
==> v1beta2/StatefulSet
NAME DESIRED CURRENT AGE
redis 1 1 54s
==> v1beta1/ClusterRole
NAME AGE
fission-prometheus-kube-state-metrics 54s
fission-prometheus-server 54s
==> v1/ClusterRole
NAME AGE
secret-configmap-getter 54s
package-getter 54s
==> v1beta1/RoleBinding
NAME AGE
fission-admin 54s
==> v1beta1/DaemonSet
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fission-prometheus-node-exporter 1 1 1 1 1 <none> 54s
logger 1 1 1 1 1 <none> 54s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
fission-prometheus-node-exporter-dg6dk 1/1 Running 0 54s
logger-rv485 1/1 Running 0 54s
fission-prometheus-alertmanager-7dd8795d65-f6897 0/2 Pending 0 54s
fission-prometheus-kube-state-metrics-6748f7d8-2nh26 1/1 Running 0 54s
fission-prometheus-pushgateway-66db5b98c9-wnfbl 1/1 Running 0 54s
fission-prometheus-server-7d85cf4fcb-pqgbh 0/2 Pending 0 54s
executor-759785c444-kmzzv 1/1 Running 0 54s
mqtrigger-nats-streaming-7f55678558-t292l 1/1 Running 0 54s
storagesvc-7d94dbbc8b-zq24k 0/1 Pending 0 54s
buildermgr-7857f48f78-8bc79 1/1 Running 0 53s
router-6564f6b95-xprg7 1/1 Running 0 53s
influxdb-868d78d79-bqxsp 0/1 ContainerCreating 0 53s
controller-66b9559c8f-4xcdz 1/1 Running 0 53s
timer-5cd5886755-kll2k 0/1 ContainerCreating 0 53s
kubewatcher-5584b7bd77-qggz2 0/1 ContainerCreating 0 53s
nats-streaming-576964bb64-k2nww 0/1 ContainerCreating 0 52s
redis-0 1/1 Running 0 54s
==> v1/Namespace
NAME STATUS AGE
fission-builder Active 54s
fission-function Active 54s
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
fission-prometheus-alertmanager Pending 54s
fission-prometheus-server Pending 54s
fission-storage-pvc Pending 54s
==> v1/ServiceAccount
NAME SECRETS AGE
fission-prometheus-alertmanager 1 54s
fission-prometheus-kube-state-metrics 1 54s
fission-prometheus-node-exporter 1 54s
fission-prometheus-pushgateway 1 54s
fission-prometheus-server 1 54s
fission-svc 1 54s
fission-fetcher 1 54s
fission-builder 1 54s
==> v1beta1/ClusterRoleBinding
NAME AGE
fission-prometheus-kube-state-metrics 54s
fission-prometheus-server 54s
fission-crd 54s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
fission-prometheus-alertmanager 1 1 1 0 54s
fission-prometheus-kube-state-metrics 1 1 1 1 54s
fission-prometheus-pushgateway 1 1 1 1 54s
fission-prometheus-server 1 1 1 0 54s
executor 1 1 1 1 54s
mqtrigger-nats-streaming 1 1 1 1 54s
storagesvc 1 1 1 0 54s
buildermgr 1 1 1 1 54s
router 1 1 1 1 54s
influxdb 1 1 1 0 54s
controller 1 1 1 1 54s
timer 1 1 1 0 54s
kubewatcher 1 1 1 0 54s
nats-streaming 1 1 1 0 54s
==> v1/Secret
NAME TYPE DATA AGE
influxdb Opaque 2 54s
==> v1/ConfigMap
NAME DATA AGE
fission-prometheus-alertmanager 1 54s
fission-prometheus-server 3 54s
feature-config 1 54s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
fission-prometheus-alertmanager ClusterIP 10.152.183.168 <none> 80/TCP 54s
fission-prometheus-kube-state-metrics ClusterIP None <none> 80/TCP 54s
fission-prometheus-node-exporter ClusterIP None <none> 9100/TCP 54s
fission-prometheus-pushgateway ClusterIP 10.152.183.149 <none> 9091/TCP 54s
fission-prometheus-server ClusterIP 10.152.183.128 <none> 80/TCP 54s
influxdb ClusterIP 10.152.183.87 <none> 8086/TCP 54s
executor ClusterIP 10.152.183.57 <none> 80/TCP 54s
redis ClusterIP 10.152.183.195 <none> 6379/TCP 54s
nats-streaming NodePort 10.152.183.98 <none> 4222:31316/TCP 54s
router NodePort 10.152.183.30 <none> 80:31314/TCP 54s
controller NodePort 10.152.183.93 <none> 80:31313/TCP 54s
storagesvc ClusterIP 10.152.183.104 <none> 80/TCP 54s
NOTES:
1. Install the client CLI.
[...]
Linux:
$ curl -Lo fission https://github.com/fission/fission/releases/download/1.0-rc1/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/
2. You're ready to use Fission!
[...]
# Run this function
$ fission function test --name hello
Hello, world!

Looks promising for now. Next step, create an environment and create python function inside this environment:

$ fission env create --name python --image fission/python                                                                           environment 'python' created
$ vim test2.py $ cat test2.py
def main():
return "Hello, world!\n"
$ fission function create --name hello --env python --code test2.py
Package 'test2-py-29ep' created
package 'test2-py-29ep' created
function 'hello' created

Function created. Let’s test it.

$ fission function test --name hello                                                                                                  
Error calling function hello: 500 Post http://executor.fission/v2/getServiceForFunction: dial tcp: i/o timeoutFatal error: Error querying logs: Post http://127.0.0.1:42057/proxy/influxdb?db=fissionFunctionLog&params=%7B%22funcuid%22%3A%22137c1481-107d-11e9-b057-8c1645bca5b9%22%2C%22time%22%3A0%7D&q=select+%2A+from+%22log%22+where+%22funcuid%22+%3D+%24funcuid+AND+%22time%22+%3E+%24time+LIMIT+1000: net/http: request canceled (Client.Timeout exceeded while awaiting headers)

So, it does not work, unfortunately. I could try to investigate error more, but at this moment I have decided to give up and make another approach to MicroK82+Fission in some time.