General Assumptions:
- You have a Kubernetes cluster running on stack8s.
- The respective serverless engine (Knative, OpenFaaS, Nuclio, Fission) is installed on your cluster.
- You have the CLI for the respective engine installed locally (
kn
,faas-cli
,nuctl
,fission
). - We'll assume an Ingress controller (like Nginx, Traefik, or the one bundled with the serverless engine like Kourier for Knative) is set up to expose services externally. If not, you might use
NodePort
orLoadBalancer
service types and directly hit the IP/port of the gateway/router service. For simplicity,YOUR_CLUSTER_IP_OR_DOMAIN
will represent this external access point.
1. Knative Serving
Knative Serving creates Kubernetes Services, Deployments, and (if you have a networking layer like Istio, Contour, or Kourier installed) Ingress-like resources (Route
, Ingress
) to expose your function.
Python "Hello World" (app.py
):
Knative can run any container that serves HTTP. A common way with Python is to use a minimal web framework like Flask.
# app.py
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def hello_world():
return "Hello World from Knative!"
if __name__ == "__main__":
port = int(os.environ.get("PORT", 8080))
app.run(debug=True, host='0.0.0.0', port=port)
Dockerfile:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
# Knative will set the PORT environment variable
ENV PORT 8080
EXPOSE 8080
CMD ["python", "app.py"]
requirements.txt:
Flask>=2.0
Deployment:
Deploy using kn
CLI (assuming you are in the default
namespace for simplicity):
kn service create hello-knative \
--image your-registry/knative-hello-py \
--port 8080 # The port your container listens on
Build and push your Docker image:
docker build -t your-registry/knative-hello-py .
docker push your-registry/knative-hello-py
API Endpoint Exposure:
Knative will create a URL for your service.
- Example Endpoint:
http://hello-knative.default.your-knative-domain.com
To find the URL:
kn service describe hello-knative
Look for the URL:
field in the output. It will typically be something like:http://hello-knative.default.your-knative-domain.com
(where your-knative-domain.com
is configured during Knative installation, e.g., 1.2.3.4.nip.io
if using nip.io
for local testing with an IP).
Invocation:
curl http://hello-knative.default.your-knative-domain.com
# Expected Output: Hello World from Knative!
2. OpenFaaS
OpenFaaS uses an API Gateway to route requests to functions.
Python "Hello World" (handler.py
for the python3-http
template):
# handler.py
def handle(event, context):
"""
handle a request to the function
Args:
event (obj): request body (if any)
context (obj): invocation context
"""
return {
"statusCode": 200,
"body": "Hello World from OpenFaaS!"
}
(Note: For the simpler python3
template, handle(req)
would just return the string.)
Stack file (hello.yml
):
version: 1.0
provider:
name: openfaas
gateway: http://YOUR_OPENFAAS_GATEWAY_IP:8080 # Replace with your gateway
functions:
hello-openfaas:
lang: python3-http # Or python3 for simpler string return
handler: ./ # Directory containing handler.py
image: your-registry/hello-openfaas-py:latest
# For python3-http, it expects a JSON serializable dict.
# For python3, it expects a string.
Deployment:
Deploy:
# Make sure your OPENFAAS_URL is set or provide --gateway
# export OPENFAAS_URL=http://YOUR_OPENFAAS_GATEWAY_IP:8080
faas-cli deploy -f hello.yml
(Optional, if you want to build locally first)
faas-cli build -f hello.yml
faas-cli push -f hello.yml
API Endpoint Exposure:
The API Gateway exposes functions under the /function/
path.
- Gateway URL: Find your OpenFaaS gateway service IP/port. If using
kubectl port-forward svc/gateway -n openfaas 8080:8080
, it'shttp://127.0.0.1:8080
. If exposed via Ingress, it'shttp://YOUR_CLUSTER_IP_OR_DOMAIN/openfaas/
. - Function Path:
/function/<function-name>
- Example Endpoint:
http://YOUR_OPENFAAS_GATEWAY_IP:8080/function/hello-openfaas
(If using a namespace, it might be.../function/hello-openfaas.namespace
)
Invocation:
curl http://YOUR_OPENFAAS_GATEWAY_IP:8080/function/hello-openfaas
# Expected Output (for python3-http): {"statusCode": 200, "body": "Hello World from OpenFaaS!"}
# If using the simpler python3 template, the output would be: Hello World from OpenFaaS!
3. Nuclio
Nuclio deploys functions that can be triggered by HTTP. It has its own dashboard which can act as a gateway, or functions can be exposed via Kubernetes Ingress.
Python "Hello World" (helloworld.py
):
# helloworld.py
def handler(context, event):
return context.Response(body='Hello World from Nuclio!',
headers={},
content_type='text/plain',
status_code=200)
Function Configuration (function.yaml
- optional, nuctl
can infer):
apiVersion: nuclio.io/v1beta1
kind: Function
metadata:
name: hello-nuclio
namespace: nuclio # Or your preferred namespace
spec:
runtime: python:3.9
handler: helloworld:handler # filename:handler_function_name
triggers:
http:
kind: http
maxWorkers: 1
# attributes:
# ingresses:
# my-ingress: # Rule name for an ingress
# host: my-func.example.com # if using ingress
# paths:
# - /hello
Deployment:
Use the nuctl
CLI.
nuctl deploy hello-nuclio \
--namespace nuclio \
--path ./helloworld.py \
--runtime python:3.9 \
--handler helloworld:handler \
--trigger http \
--port 8080 # Port function listens on internally; Nuclio handles external routing
This command deploys the function and by default sets up an HTTP trigger.
API Endpoint Exposure:
Nuclio functions are typically invoked through the Nuclio dashboard/gateway service or an Ingress.
- Default Path (if not using Ingress with custom paths):
Nuclio functions deployed via the CLI in a project (default project isdefault
) are often invoked via a path like:http://<nuclio-dashboard-or-ingress-ip>:<port>/<project-name>/<function-name>
If you didn't specify a project, it might be implicitly in thedefault
project within Nuclio.
If the function is deployed into thenuclio
Kubernetes namespace, and invoked directly via its service (less common for external access), the path might be simpler.However, a more common way is thatnuctl deploy
will also create a Kubernetes service for the function, e.g.,svc/nuclio-hello-nuclio
. If you have an Ingress controller, you'd create an Ingress rule pointing to this service.Thenuctl get func hello-nuclio -n nuclio -o yaml
command will show you thehttpPort
understatus
. - Invoking via
nuctl
(for testing):nuctl invoke hello-nuclio -n nuclio -m GET
This uses the Nuclio API, not a direct HTTP endpoint necessarily, but good for testing. - Direct HTTP Invocation (Example assuming NodePort on the function's service):
If Nuclio created a service for your function (e.g.,nuclio-hello-nuclio
) of type NodePort:kubectl get svc nuclio-hello-nuclio -n nuclio
(Find the NodePort, e.g., 31234)http://YOUR_K8S_NODE_IP:31234
Typical Ingress Setup:
You'd create an Ingress resource:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-nuclio-ingress
namespace: nuclio
spec:
rules:
- http:
paths:
- path: /nuclio/hello
pathType: Prefix
backend:
service:
name: nuclio-hello-nuclio # Service created by Nuclio for the function
port:
number: 8080 # The port the function's service listens on
Then the endpoint would be http://YOUR_CLUSTER_IP_OR_DOMAIN/nuclio/hello
Finding the Nuclio Dashboard/Gateway IP/Port:
kubectl get svc -n nuclio dashboard # Look for External IP or NodePort
Let's say it's YOUR_NUCLIO_DASHBOARD_IP:PORT
.
Invocation (assuming Ingress like above):
curl http://YOUR_CLUSTER_IP_OR_DOMAIN/nuclio/hello
# Expected Output: Hello World from Nuclio!
4. Fission
Fission uses a Router component to direct HTTP requests to function pods.
Python "Hello World" (hello.py
):
# hello.py
def main():
return "Hello World from Fission!"
(Fission's Python environment typically expects a main
function or a Flask app).
Deployment:
Create an HTTP trigger (route):
fission route create --name hello-route --method GET --url /hello-fission --function hello-fission
# Or fission httptrigger create --method GET --url /hello-fission --function hello-fission (newer CLI syntax)
Create the function:
fission function create --name hello-fission --env python --code hello.py
Ensure you have a Python environment in Fission (usually created by default):
fission env list
# If not, fission env create --name python --image fission/python-env
API Endpoint Exposure:
The Fission Router service handles incoming requests.
- Function Path: This is defined by the
--url
parameter infission route create
. - Example Endpoint:
http://YOUR_FISSION_ROUTER_IP:PORT/hello-fission
Finding the Fission Router IP/Port:
kubectl get svc router -n fission # Or your Fission installation namespace
# Look for External IP (if LoadBalancer) or NodePort
Let's say it's YOUR_FISSION_ROUTER_IP:PORT
.
Invocation:
curl http://YOUR_FISSION_ROUTER_IP:PORT/hello-fission
# Expected Output: Hello World from Fission!
Summary of Endpoint Patterns:
- Knative:
http://<service-name>.<namespace>.<knative-domain>/[path-if-any]
(highly dependent on networking layer config) - OpenFaaS:
http://<gateway-ip>:<port>/function/<function-name>[.namespace]
- Nuclio:
http://<dashboard/ingress-ip>:<port>/<project>/<function-name>
or custom Ingress path. Service-level access is also possible. - Fission:
http://<router-ip>:<port>/<url-path-defined-in-trigger>
Remember that YOUR_..._IP
and domain names are placeholders. You'll need to find the actual external IP addresses or configure DNS/Ingress for your specific Kubernetes and serverless engine setup. Using an Ingress controller with custom hostnames is the most common production approach.