About
DevConf.CZ is an annual, free, Red Hat sponsored community conference for developers, admins, DevOps engineers, testers, documentation writers and other contributors to open source technologies. At DevConf.CZ, FLOSS communities sync, share, and hack on upstream projects together.
DevConf.cz Mini is a bi-annual, highly focused, local, in-person version of DevConf.cz. It offers an opportunity to return to our conference themes in a smaller setting and establishes a platform for the Czech Republic and EMEA based community to sync, share and hack on upstream projects together.
There is no admission or ticket charge for DevConf.CZ events. However, you are required to complete a free registration. Watch this site for updates about registration.
We are committed to fostering an open and welcoming environment at our conference. We set expectations for inclusive behavior through our code of conduct and media policies, and are prepared to enforce these.
Schedule
Writing a K8s Operator for Knative Functions
Serverless and Function as a Service (FaaS) are getting more and more attention from customers and developers as a way to develop, run and manage applications functionality without the burden of infrastructure related knowledge. All big cloud providers offer them already, e.g., AWS Lambda, Google Cloud Functions or Microsoft Azure Functions. One of the most relevant upstream projects for serverless is Knative, which recently added support for functions (create, build, and deploy) on top of K8s clusters.
This workshop will introduce you to the the PHYSICS European project and its FaaS model, as well as to building Kubernetes operators. You will implement a K8s Operator, using the operatorsdk framework, to provide the functionality of the Knative CLI. This will allow easier creation, build and deployment of functions with Knative just by creating Kubernetes (CR) objects, and will help you learn the internals about how K8s Operators work in a real life example.
Friday June 16, 2023 • 2:15pm - 3:35pm CEST
Speakers
- Luis Tomas Bolivar - Software Engineer at Red Hat
- Jose Castillo Lema - Software Engineer at Red Hat
Links
Workshop
physics-devconf
This repository provides an easy way to deploy a KinD cluster with Knative (using this script) on top of a Fedora 37 VM.
It also provides a couple of sample scripts to deploy a Knative service and a function.
Index
Goals
- Get familiar on how to create/test Knative functions
- Get familiar with the operator SDK
Deploy the environment (VM)
The VM requires 4 vCPUs and 6GB of memory. It takes approximately 10 minutes to come up:
$ vagrant up
Bringing machine 'default' up with 'libvirt' provider...
==> default: Checking if box 'fedora/37-cloud-base' version '37.20221105.0' is up to date...
==> default: Creating image (snapshot of base box volume).
==> default: Creating domain with the following settings...
...
default: configmap/config-br-defaults configured
default: ⑦ Dapr
default: ./allocate.sh: line 251: dapr: command not found
default: popd
default: ~/go/src/github.com/knative/func
default:
default: cat <<EOF | sudo tee /etc/docker/daemon.json
default: {"insecure-registries": ["localhost:50000"]}
default: EOF
default: {"insecure-registries": ["localhost:50000"]}
The provision script installs:
- Docker
- Golang
- Pip
- Git
- Curl
- Wget
- Cosign
- Kubectl
- Kn - the Knative client
- Func - Knative functions
- Kind
- Operator-sdk
Access the environment
- Login into the virtual machine just created:
$ vagrant ssh
- Check if all the pods are running:
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
contour-external contour-56cfd44877-gmzdd 1/1 Running 0 2m30s
contour-external contour-56cfd44877-wj844 1/1 Running 0 2m30s
contour-external contour-certgen-v1.22.0-qbbx6 0/1 Completed 0 2m30s
contour-external envoy-4j2vr 2/2 Running 0 2m30s
contour-internal contour-865fdc98f9-48vv9 1/1 Running 0 2m29s
contour-internal contour-865fdc98f9-l22kw 1/1 Running 0 2m29s
contour-internal contour-certgen-v1.22.0-5t52p 0/1 Completed 0 2m30s
contour-internal envoy-vlxrb 2/2 Running 0 2m29s
knative-eventing eventing-controller-64b4b79c45-bxk6f 1/1 Running 0 4m5s
knative-eventing eventing-webhook-86f7dd95db-phc9x 1/1 Running 0 4m5s
knative-eventing imc-controller-769d8b7f66-hx2lj 1/1 Running 0 3m33s
knative-eventing imc-dispatcher-55979cf74b-8n2w9 1/1 Running 0 3m33s
knative-eventing mt-broker-controller-f97f8747-r7nnr 1/1 Running 0 3m21s
knative-eventing mt-broker-filter-77c75d69fb-j4972 1/1 Running 0 3m21s
knative-eventing mt-broker-ingress-d96f6d8b5-g4ng6 1/1 Running 0 3m21s
knative-serving activator-75777fd57c-hwsth 1/1 Running 0 4m49s
knative-serving autoscaler-57d647d6ff-cs2bx 1/1 Running 0 4m49s
knative-serving controller-677995dc7b-9tbmj 1/1 Running 0 4m48s
knative-serving domain-mapping-5676fb7bcf-92xmf 1/1 Running 0 4m48s
knative-serving domainmapping-webhook-fcbd7dff4-5v26r 1/1 Running 0 4m48s
knative-serving net-contour-controller-847758c4bf-kltdx 1/1 Running 0 2m
knative-serving webhook-544b958c69-h7vmz 1/1 Running 0 4m48s
kube-system coredns-6d4b75cb6d-btqsp 1/1 Running 0 5m16s
kube-system coredns-6d4b75cb6d-shbkf 1/1 Running 0 5m16s
kube-system etcd-func-control-plane 1/1 Running 0 5m35s
kube-system kindnet-mr2xx 1/1 Running 0 5m16s
kube-system kube-apiserver-func-control-plane 1/1 Running 0 5m30s
kube-system kube-controller-manager-func-control-plane 1/1 Running 0 5m30s
kube-system kube-proxy-vpb8z 1/1 Running 0 5m16s
kube-system kube-scheduler-func-control-plane 1/1 Running 0 5m32s
local-path-storage local-path-provisioner-6b84c5c67f-575j5 1/1 Running 0 5m16s
metallb-system controller-6c58495cbb-j52ls 1/1 Running 0 3m3s
metallb-system speaker-v5hd2 1/1 Running 0 3m3s
- Check if the local registry is running:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
59be051ba43c registry:2 "/entrypoint.sh /etc…" 2 minutes ago Up 2 minutes 127.0.0.1:50000->5000/tcp func-registry
caf78811a6a9 kindest/node:v1.24.6 "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes 127.0.0.1:39609->6443/tcp, 127.0.0.1:80->30080/tcp, 127.0.0.1:443->30443/tcp func-control-plane
Create a new (python) function and invoke it
- Create the Knative function:
$ func create -l python test-hw
Created python function in /home/vagrant/test-hw
- Take a look around and change the
func.py
code as follows:
$ cd test-hw
$ ls
app.sh func.py func.yaml Procfile README.md requirements.txt test_func.py
$ cat func.py
from parliament import Context
from flask import Request
import json
# parse request body, json data or URL query parameters
def payload_print(req: Request) -> str:
if req.method == "GET":
return "DevConf.cz 2023!"
def main(context: Context):
"""
Function template
The context parameter contains the Flask request object and any
CloudEvent received with the request.
"""
# Add your business logic here
print("Received request")
if 'request' in context.keys():
return payload_print(context.request), 200
else:
print("Empty request", flush=True)
return "{}", 200
- Build (and push) the function to the internal registry:
$ export FUNC_REGISTRY=localhost:50000/kn-user
$ func build --push
🙌 Function image built: localhost:50000/kn-user/test-hw:latest
🕕 Pushing function image to the registry "localhost:50000" using the "" user credentials
- Check that the image has been correctly pushed into the internal registry:
$ curl localhost:50000/v2/_catalog
{"repositories":["kn-user/test-hw"]}
- Deploy the function to the kind cluster:
$ func deploy --build=false --push=false
✅ Function deployed in namespace "default" and exposed at URL:
http://test-hw.default.127.0.0.1.sslip.io
- Check that the function has been correctly deployed. A new Knative service (ksvc) object is created, which triggers the Knative controllers to create the other k8s objects (deployment and route). After approximately one minute minute the deployment is scaled down to 0 replicas if not used to spare resources:
$ kubectl get ksvc
NAME URL LATESTCREATED LATESTREADY READY REASON
test-hw http://test-hw.default.127.0.0.1.sslip.io test-hw-00001 test-hw-00001 True
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
test-hw-00001-deployment 0/0 0 0 104s
$ kubectl get route
NAME URL READY REASON
test-hw http://test-hw.default.127.0.0.1.sslip.io True
$ kubectl get pods
(empty if more than a minute has passed)
- Invoke the function:
$ curl http://test-hw.default.127.0.0.1.sslip.io
DevConf.cz 2023!
- Check that the deployment has been scaled up:
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
test-hw-00001-deployment 1/1 1 1 3s
Fork the base operator github repository and deploy locally
Fork this github repository into your github account:
https://github.com/luis5tb/devconf-knative-operator
Clone your fork locally inside the VM (change YOUR_USER by yours):
$ git clone https://github.com/YOUR_USER/devconf-knative-operator.git
In case you want to start an operator from scratch do the next instead (change YOUR_USER by yours):
$ mkdir devconf-knative-operator
$ cd devconf-knative-operator
# Create base operator
$ operator-sdk init --domain example.com --repo github.com/YOUR_USER/devconf-knative-operator
# Add API
$ operator-sdk create api --group knf --version v1alpha1 --kind KnativeFunction --resource --controller
- There are three important files to consider:
- controllers/knativefunction_controller.go : implements the operator reconcile loop
- api/v1alpha1/knativefunction_types.go : the KnativeFunction CRD definition
- config/samples/knf_v1alpha1_knativefunction.yaml : an example KnativeFunction CRD
- Let’s take a look at api/v1alpha1/knativefunction_types.go , as you can see it defines an example
Foo
field:
...
type KnativeFunctionSpec struct {
// Foo is an example field of KnativeFunction. Edit knativefunction_types.go to remove/update
Foo string `json:"foo,omitempty"`
}
...
Let’s modify the operator reconcyle loop in controllers/knativefunction_controller.go :
Test your code by deploying it. You will need two terminals, T1 and T2.
[T2] In a second terminal create a sample CRD:
$ cat <<EOF | kubectl apply -f -
---
apiVersion: knf.example.com/v1alpha1
kind: KnativeFunction
metadata:
labels:
app.kubernetes.io/name: knativefunction
app.kubernetes.io/instance: knativefunction-sample
app.kubernetes.io/part-of: devconf-knative-operator
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: devconf-knative-operator
name: knativefunction-sample
spec:
foo: test
EOF
- [T1] In the first terminal you should see something like:
2023-06-16T08:12:54Z INFO Received a request to create a new knativefunction {"controller": "knativefunction", "controllerGroup": "knf.example.com", "controllerKind": "KnativeFunction", "KnativeFunction": {"name":"knativefunction-sample","namespace":"default"}, "namespace": "default", "name": "knativefunction-sample", "reconcileID": "9be34733-bca6-4134-bf6d-8f0ed69106bd", "Foo =": "test"}
- [Challenge] The goal now is to extend the operator to deploy the existing Knative function (from step 6). Once this is accomplished, extend the operator to build, push and deploy any function located on a given github repository.
Solution
Deploy a CR to force the controller to reconcile and get the function deployed. First you need to edit the
config/samples/knf_v1alpha1_knativefunction.yaml
with the desired options:To check the operator did its job, beside seeing the
make install run
logs, you can check as before:
Top comments (0)