AWS Open Source Blog

Running FaaS on a Kubernetes Cluster on AWS using Kubeless

使用 Kubeless 在 AWS 上的 Kubernetes 集群中运行 FaaS

Serverless computing allows you to build and run applications and services without provisioning, scaling, or managing any servers. FaaS (Functions as a Service) is the runtime that enables serverless computing by firing off bits of code (functions) as they are needed, freeing the developer from managing infrastructure and enabling the developer to simply write business logic code. With the rise of Kubernetes, several open source FaaS platforms have been created. This two-part post will introduce one such FaaS, Kubeless, and how to get it up and running on a Kubernetes cluster on AWS.

Arun


Kubeless is an open source Function as a Service (FaaS) solution built on top of Kubernetes. Inspired by AWS Lambda, Kubeless aims to bring the functional programming paradigm to Kubernetes users, by bringing function-based packaging into the container. The technical strength of Kubeless lies in the fact that it is a Kubernetes extension using the Custom Resource Definition API object. Kubeless uses k8s primitives to build a Lambda-like system which enables developers to deploy small units of code as functions without worrying about underlying infrastructure. When you use Kubernetes, using Kubeless to deploy small units of code is as straightforward as creating a Kubernetes resource. While you can use Kubeless to deploy HTTP webhooks, you can also deploy functions that can be triggered by events happening in your cloud, such as a file being uploaded to a storage bucket, a data stream, and so on.

Since Kubeless is built on top of upstream Kubernetes, it will be deployable in Amazon EKS, and any functions deployed can be triggered based on multiple AWS sources.

In this post we’ll show you how to run Kubeless on a Kubernetes cluster on AWS created using kops, and how to deploy a trivial function. In a follow up post, we will show you how to trigger your Kubeless functions based on events published to Kinesis streams.

Create a cluster on AWS with kops

kops is one of the provisioning tools available to create a Kubernetes cluster, with very advanced AWS support. Detailed documentation is available. Here we will only show the main steps, so do make sure to check out the full walkthrough, especially if this is your first time using kops. (For more information, read Manage Kubernetes Clusters on AWS Using Kops.)

Get the pre-reqs and set up your environment, create a kops IAM user with required roles, then create an S3 bucket which will store your cluster configuration, set two environment variables, and make sure you know which zone you are going to use, like so:

aws s3api create-bucket --bucket kops-Kubeless --region us-east-1

export NAME=Kubeless.k8s.local

export KOPS_STATE_STORE=s3://kops-Kubeless

aws ec2 describe-availability-zones --region eu-west-1

You are then ready to create your cluster:

kops create cluster --zones eu-west-1a ${NAME}

kops update cluster Kubeless.k8s.local --yes

Remember to delete it once you are all done:

kops delete cluster --name ${NAME} --yes

Install Helm to Deploy an Ingress Controller

Using an Ingress controller allows us to expose functions to the public internet.

Get the Helm client from the GitHub release page, then create a service account with proper RBAC privileges.

kubectl create serviceaccount --namespace kube-system tiller

kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller

kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'

helm init --service-account tiller --upgrade

Deploy an nginx Ingress controller with a Load Balancer service:

helm install --name nginx-ingress stable/nginx-ingress --set rbac.create=true

Once your Ingress controller is running, you can get the public DNS hostname used:

kubectl get svc nginx-ingress-nginx-ingress-controller -o json | jq -r .status.loadBalancer.ingress[0].hostname

Deploy Kubeless

To deploy on Kubeless on the cluster, you need to create a dedicated namespace and then post a few manifests to the Kubernetes API server. Those manifests will create a custom resource definition to declare a new Function object kind, and will launch the Kubeless controller.

Below are the two command lines that show you how to create the namespaces and how to launch the latest version of Kubeless:

kubectl create ns kubeless

kubectl create -f https://github.com/Kubeless/Kubeless/releases/download/v1.0.0-alpha.2/Kubeless-v1.0.0-alpha.2.yaml

Finally, to be able to use Kubeless from the command line, you will need to install the CLI. You can get it from the Github release page or, if you are an OSX user, you can get it directly from brew.

$ brew install kubeless

Deploy a function

Let’s create a simple echo function in Python:

cat << EOF >> echo.py

def handler(event, context):

print(event['data'])

return event['data']

EOF

Deploy the function:

kubeless function deploy foo --runtime python3.6 --from-file echo.py --handler echo.handler

Soon the function will be ready and a corresponding pod will be running (note that you can configure autoscaling so that your functions scale based on requests or load).

$ kubeless function ls

NAME    NAMESPACE    HANDLER        RUNTIME      DEPENDENCIES    STATUS

foo     default      echo.handler    python3.6                   1/1 READY

$ kubectl get pods|grep foo

foo-697454fcd4-n7g5g     1/1 Running 0      1m

Create a route to the function. Note that the function will be exposed publicly (adding TLS and authentication is possible but not explained here, please see the full documentation).

kubeless trigger http create foo --function-name foo --gateway nginx

Once the function is up, you can call it using the Host header defined in the Ingress object and the public endpoint of the Ingress controller.

$ export FOO_HOST=$(kubectl get ingress foo -o json |jq -r .spec.rules[0].host)

$ export FOO_INGRESS=$(kubectl get svc nginx-ingress-nginx-ingress-controller -o json | jq -r .status.loadBalancer.ingress[0].hostname)

$ curl -d '{"kubeless": "on AWS"}' -H "Host: ${FOO_HOST}" -H "Content-Type:application/json" ${FOO_INGRESS}

{"kubeless": "on AWS"}

Conclusion

Congratulations! If you made it this far, you have a running Kubeless installation in an Kubernetes cluster on AWS. In a follow up post, we will show you the really exciting part: how to trigger your function based on cloud events, focusing on AWS Kinesis.

Sebastien GoasguenSebastien Goasguen is a twenty year open source veteran. A member of the Apache Software Foundation, he worked on Apache CloudStack for several years before diving into the container world. He is the founder of Skippbox, a Kubernetes startup acquired by Bitnami. He is the creator of Kubeless and is its current tech lead and product manager. An avid blogger, he enjoys spreading the word about new cutting edge technologies. Sebastien is the author of the O’Reilly Docker Cookbook and co-author of the Kubernetes Cookbook.

The content and opinions in this post are those of the third-party author and AWS is not responsible for the content or accuracy of this post.

 

 

Arun Gupta

Arun Gupta

Arun Gupta is a Principal Open Source Technologist at Amazon Web Services. He focuses on everything containers and open source at AWS. He is responsible for CNCF strategy within AWS, and participates at CNCF Board and technical meetings actively. He has built and led developer communities for 12+ years at Sun, Oracle, Red Hat and Couchbase. He has extensive speaking experience in more than 40 countries on myriad topics and is a JavaOne Rock Star for four years in a row. Gupta also founded the Devoxx4Kids chapter in the US and continues to promote technology education among children. A prolific blogger, author of several books, an avid runner, a globe trotter, a Docker Captain, a Java Champion, a JUG leader, NetBeans Dream Team member, he is easily accessible at @arungupta.