Introduction to On-Premises Serverless Function as a Service with OpenFaaS and Go — Part 2
In this second part of our series we will look at the creation of a custom serverless FaaS Go functions using a lab environment with OpenFaaS that we built in Part 1.
OpenFaaS provides a library of templates to assist in building functions. The library can be accessed as follows:
faas-cli template store list
It will provide the necessary templates to build a custom function with entry point and required images.
For example:
We can now use this information to begin creating our Go function.
For now we will use docker hub. To begin let’s configure the relevant ENV VAR.
export OPENFAAS_PREFIX=robrockdataio
First we create the function artifacts from the Go template:
faas-cli new --lang go faasoracle
Now inspect these artefacts:
├── faasoracle
├── faasoracle.yml
└── template
The template has created a go.mod file and our isomorphic handler.
Our newly created handler looks thus:
package function
import (
"fmt"
)
// Handle a serverless request
func Handle(req []byte) string {
return fmt.Sprintf("Hello, Go. You said: %s", string(req))
}
The template implements a basic function that we can test now and elaborate on in the future. So let’s do that.
It has also created the YAML file faasoracle.yml as follows:
version: 1.0
provider:
name: openfaas
gateway: http://127.0.0.1:8080
functions:
faasoracle:
lang: go
handler: ./faasoracle
image: robrockdataio/faasoracle:latest
The faasoracle.yml file describes how we would like our function to be deployed to OpenFaaS.
faas-cli build -f faasoracle.yml
Our function will now be built.
For example you can introspect the build/faasoracle/Dockerfile to see the Dockefile build product.
For example:
FROM - platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/classic-watchdog:0.2.1 as watchdog
FROM - platform=${BUILDPLATFORM:-linux/amd64} golang:1.18-alpine3.15 as build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
ARG TARGETOS
ARG TARGETARCH
# Required to enable Go modules
RUN apk add - no-cache git
# Allows you to add additional packages via build-arg
ARG ADDITIONAL_PACKAGE
ARG CGO_ENABLED=0
ARG GO111MODULE="off"
ARG GOPROXY=""
ARG GOFLAGS=""
COPY - from=watchdog /fwatchdog /usr/bin/fwatchdog
RUN chmod +x /usr/bin/fwatchdog
ENV CGO_ENABLED=0
WORKDIR /go/src/handler
COPY . .
# Run a gofmt and exclude all vendored code.
RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; }
WORKDIR /go/src/handler/function
RUN mkdir -p /go/src/handler/function/static
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=${CGO_ENABLED} go test ./… -cover
WORKDIR /go/src/handler
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=${CGO_ENABLED} \
go build - ldflags "-s -w" -a -installsuffix cgo -o handler .
FROM - platform=${TARGETPLATFORM:-linux/amd64} alpine:3.15 as ship
RUN apk - no-cache add ca-certificates \
&& addgroup -S app && adduser -S -g app app
WORKDIR /home/app
COPY - from=build - chown=app /usr/bin/fwatchdog .
COPY - from=build - chown=app /go/src/handler/handler .
COPY - from=build - chown=app /go/src/handler/function/static static
USER app
ENV fprocess="./handler"
EXPOSE 8080
HEALTHCHECK - interval=3s CMD [ -e /tmp/.lock ] || exit 1
CMD ["./fwatchdog"]
With our function built, it’s now time to push it to a registry.
Now we can push the function image.
faas-cli push -f faasoracle.yml
Which can now be seen in docker hub.
We deploy our faasoracle function next using the faas-cli.
faas-cli deploy -f faasoracle.yml
Here we can now see our function defined in the OpenFaaS UI.
Next, unlike Part 1; where we used the command line to invoke the function, we will use the OpenFaaS UI.
And there we have it. Our custom function returns the desired response.
Conclusion
In Part 2 of this series we have built upon the knowledge of Part 1 and moved on to use the supplied templates from the OpenFaaS template store to start to improve our knowledge.
We have successfully built an OpenFaaS function in the Go programming language, then deployed its image to a remote image store. We have then deployed our function to our lab OpenFaaS cluster on Kind, demonstrated that it is installed using the OpenFaaS UI and then used said UI to invoke the function.
In Part 3 this knowledge will be built on further to outline a more elaborate function which we will integrate with Kafka thereby demonstrating a serverless event driven function.