This brief is to demonstrate how one can leverage selected SAP BTP Kyma runtime serverless features.
This instalment covers:
|
Requirements and Disclaimers:Sample code: |
Putting it all together.
SAP BTP, Kyma runtime is SAP’s fully managed commercial kubernetes offering, part of SAP Business Technology Platform. It is often bundled with SAP Commerce Cloud and nowadays is becoming an extensibility runtime of choice.
Kyma brings additional components on top of a plain gardener cluster. And serverless is one of them.
Good to know:
- The serverless features described in this and following instalments can be used with both unmanaged OS Kyma on Gardener and SAP-managed SAP BTP, Kyma runtime.
Serverless Architecture
The serveless architecture is far from being trivial. Please study the diagram carefully.
Next, let’s have a look at the Function’s specification.
Seemingly, one of the coolest features with Kyma serverless CRD is the ability to override the base runtime image of a function.
This can be really useful when the default runtime image is just not good enough to accommodate some specific runtime dependencies.
However, please mind the gap. The kyma default base runtime function images are Alpine based. And Alpine based nodejs images have an extremely low count of security vulnerabilities;
Override function base image
For the sake of this brief, let’s try it out with the nodejs16 functions. However, same approach is valid with any other supported serverless runtime, for instance with python 3.9.
In order to replace a default base image of a nodejs16 function we should try to understand how kyma does it.
Let’s have a look at a Dockerfile definition used by kyma itself to create a function base image, namely:
# image base on 16.19.0-alpine3.17
FROM node@sha256:e427ffd1ba7915ca8d8aeba45806ef3f1f1e6b65ce152b363645cd7428f8d75a
ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
ENV npm_config_cache /tmp/
RUN mkdir -p /usr/src/app
RUN mkdir -p /usr/src/app/lib
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install && npm cache clean --force
COPY lib /usr/src/app/lib
COPY server.js /usr/src/app/server.js
CMD ["npm", "start"]
EXPOSE 8888
The build of the above Dockerfile will result in the following stock image, that eventually will be used in the function kaniko build
eu.gcr.io/kyma-project/function-runtime-nodejs16:v20230117-d8ab8401
Good to know:
- The docker files used in the function build are stored as config maps in a kyma cluster namespaces. Goto your cluster to look them up.
Building a custom image.
In order the build a custom image first you need to clone the project kyma github repository:
gh repo clone kyma-project/kyma
cd components/function-runtimes/nodejs16/
...............
add your Dockerfile, build the custom image and push it
to an internet facing docker repository
...............
cp Dockerfile Dockerfile.custom.nodejs16
nano Dockerfile.custom.nodejs16
...............
edit your Dockerfile.custom.nodejs16 then save it
and build your custom image
...............
docker build --platform amd64 -t <docker_id>/<docker_repo>:bullseye-slim16 -f ./Dockerfile.custom.nodejs16 .
You also need to make a decision about a new base nodejs16 image. That’s an important decision as you are entirely liable/responsible for this choice and the custom image that will be built based upon it.
For the sake of this brief I have picked a public node:16.19.0-bullseye-slim as my new nodejs16 base image.
Next, you can create a custom function base image using a custom Dockerfile.custom.nodejs16
definition.
Last but not least, you shall need to publish the image to a public and internet facing docker repository.
For instance, let’s say the new nodejs base image is node:16.19.0-bullseye-slim
and that we are going to add a bunch of linux libraries to accommodate for any specific runtime dependencies, as follows:
FROM node:16.19.0-bullseye-slim
ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
ENV npm_config_cache /tmp/
RUN mkdir -p /usr/src/app
RUN mkdir -p /usr/src/app/lib
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install && npm cache clean --force
RUN apt-get update
RUN apt-get install -y openssl python make g++
COPY lib /usr/src/app/lib
COPY server.js /usr/src/app/server.js
CMD ["npm", "start"]
EXPOSE 8888
Let’s build and then publish the custom image:
docker build --platform amd64 -t <docker_id>/<docker_repo>:bullseye-slim16 -f ./Dockerfile.custom.nodejs16 .
[+] Building 2.4s (16/16) FINISHED
=> [ 1/10] FROM docker.io/library/node:16.19.0-bullseye-slim@sha256:cfb2b5e2b39f341056ac624d32fae00ba0ab94145364111b7edfd9db703526e0 0.0s
=> CACHED [ 2/10] RUN mkdir -p /usr/src/app 0.0s
=> CACHED [ 3/10] RUN mkdir -p /usr/src/app/lib 0.0s
=> CACHED [ 4/10] WORKDIR /usr/src/app 0.0s
=> CACHED [ 5/10] COPY package.json /usr/src/app/ 0.0s
=> CACHED [ 6/10] RUN npm install && npm cache clean --force 0.0s
=> CACHED [ 7/10] RUN apt-get update 0.0s
=> CACHED [ 8/10] RUN apt-get install -y openssl python make g++ 0.0s
=> CACHED [ 9/10] COPY lib /usr/src/app/lib 0.0s
=> CACHED [10/10] COPY server.js /usr/src/app/server.js 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => naming to docker.io/<docker_id>/<docker_repo>:bullseye-slim16
Publishing the custom image:
- docker push
<docker_id>/<docker_repo>:bullseye-slim16
Eventually, this custom image can be used with kyma serverless nodejs16 functions definitions, for instance:
apiVersion: serverless.kyma-project.io/v1alpha2
kind: Function
metadata:
name: runtime-image-override
labels:
app.kubernetes.io/name: runtime-image-override
annotations: {}
namespace: default
spec:
runtime: nodejs16
source:
inline:
source: |-
module.exports = {
main: async function (event, context) {
const message = `Hello World`
+ ` from the Kyma Function ${context["function-name"]}`
+ ` running on ${context.runtime}!`;
console.log(message);
return message;
}
}
runtimeImageOverride: <docker_id>/<docker_repo>:bullseye-slim16
Thus all is needed is adding spec.runtimeImageOverride to the function definition with the name of the custom image and applying the new definition.
Good to know:
- in order to force the image change with an existing function the source code of this function may need to be touched/edited as well as to trigger the function build process.
- unsupported base images with their Dockerfiles for either nodejs16 or nodejs14 can be looked up here.
- a more thorough sample code that demonstrates SAP HANA Cloud official nodejs driver from a function is available in this gist.
Conclusion
In the next instalment of this series I will demonstrate how to use standard sap libraries to access secrets mounted as volumes.
To help you get started there is a serverless code sample here.
Good to know:
- If you needed an easy way to create or scaffold your own kyma serverless samples (both with nodejs and python runtimes alike), please refer to SAP HANA Academy code generators, including the latest kyma serverless fass generator.
I hope you have enjoyed reading the blog post. Feel free to provide feedback in the comments section below.
SAP Community: https://community.sap.com/
SAP Community Topic Page link: https://community.sap.com/topics/kyma
SAP Community Q&A Tags:
Kyma Open Source: https://answers.sap.com/tags/2936b97d-6a90-4cd8-b635-0e51441611eb
SAP BTP, Kyma runtime: https://answers.sap.com/tags/73554900100800003012
Follow me in SAP Community: Piotr Tesny