-
Notifications
You must be signed in to change notification settings - Fork 754
Python Runtime
Here is a toy python function called hello.py
that we want to create:
import json
def handler():
return "hello world"
We generate a configmap, with the naming convention <module_name>.<function_handler>:
kubectl create configmap hello.handler --from-file=hello.py
With AWS Lambda, the lambda is created like this:
aws lambda create-function \
...
--function-name HelloPython \
...
--handler hello_python.my_handler \
--runtime python2.7
This roughly equates to a custome resource that the user creates (via yet to be written CLI) will generate the following:
apiVersion: lambda.example.com/v1
kind: lambda
metadata:
name: HelloPython
spec:
runtime: python2.7
handler: hello.handler
lambda: |
import json
def handler():
return "hello world"
The controller will detect the custom resource and populate the following configmap:
$ kubectl get configmap hello.handler -o yaml
apiVersion: v1
data:
hello.py: |
import json
def handler():
return "hello world"
kind: ConfigMap
Now to inject this into a HTTP runtime (a wrapper). We use the bottle
WSGI micro framework, we could use flask
as well. The code of the runtime is:
#!/usr/bin/env python
import sys
import os
import imp
from bottle import route, run, template
mod_name = os.getenv('MOD_NAME')
func_handler = os.getenv('FUNC_HANDLER')
mod_path = '/kubeless/' + mod_name + '.py'
try:
mod = imp.load_source('lambda', mod_path)
except ImportError:
print("No valid module found for the name: lambda, Failed to import module")
@route('/')
def handler():
return getattr(mod, func_handler)()
run(host='0.0.0.0', port=8080)
Note that the module name (aka hello) and the function handler name (aka handler) are read as environment variables. We will need to define those in our deployment.
We can create a Docker image with:
FROM python:2.7.11-alpine
RUN apk add --no-cache python py-pip git
RUN pip install --upgrade pip
RUN pip install bottle
ADD kubeless.py /
CMD ["python", "/kubeless.py"]
And a Kubernetes deployment will look like this:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: lambda-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: lambda
spec:
containers:
- name: lambda
image: runseb/kubeless:0.0.5
ports:
- containerPort: 8080
env:
- name: FUNC_HANDLER
value: "handler"
- name: MOD_NAME
value: "hello"
volumeMounts:
- name: lambda
mountPath: /kubeless
volumes:
- name: lambda
configMap:
name: hello.handler
Note that we set the environment variables and the name of the config map. This will be generated by the kubeless controller on the fly.
You create the deployment and then you expose the service:
kubectl create -f lambda.yaml
kubectl expose deployment lambda-deployment --port=8080 --type=NodePort
And you can curl your function.