Deploying Your First CAP Application on SAP BTP Kyma Runtime

In this post, we will guide you through the process of deploying your first CAP (Cloud Application Programming) application on SAP BTP Kyma Runtime. The application will be a simple service that exposes a REST API, without consuming any BTP services, which will be covered in the next blog posts of this series.

This post is part of a series on SAP BTP Kyma Runtime development:

Series — SAP BTP Kyma Runtime:

  1. Preparing Your Environment For SAP BTP Development on Kyma Runtime
  2. Deploying Your First CAP Application on SAP BTP Kyma Runtime (this post)
  3. Creating BTP Service Instances on SAP BTP Kyma Runtime with the Service Operator
  4. Binding BTP Service Instances to your CAP Application with Kyma Runtime
  5. The Chart Templates Behind Your CAP Kyma Deployment
  6. Creating roles for your CAP Application on SAP BTP Kyma Runtime
  7. Using Istio Gateway as Entry Point in SAP BTP Kyma Runtime

Creating a CAP Application

Let's start by creating a simple CAP application. If you haven't already, make sure you have the necessary tools installed, such as Node.js, npm, and the SAP Cloud Application Programming Model (CAP) CLI.

Copy
cds init my-cap-app
cd my-cap-app
cds add nodejs
npm install

### Creating a Service

Create a new file called srv/greetings-service.cds with the following content:

Copy
service GreetingsService {
    function greet(name: String) returns String;
}

Now, implement the service in srv/greetings-service.js:

Copy
import cds from '@sap/cds';

export default class GreetingsService extends cds.ApplicationService {
    async greet(req) {
        const name = req || 'World';
        return `Hello, ${name}!`;
    }
}

Adding the Kyma files

Use the cds add kyma command to add the necessary Kyma files to your project. This will create a kyma folder with the required configuration files.

Copy
cds add kyma

This command asks for the image registry server URL:

Image showing the prompt for the image registry server URL

It also adds several files to the project, including:

  1. A containerize.yaml file in the root folder, which is used to build the container image for your application.
Copy
_schema-version: '1.0'
repository: <your-container-image-repository-url>
tag: latest
modules:
  - name: my-cap-app-srv
    build-parameters:
      buildpack:
        type: nodejs
        builder: builder-jammy-base
        path: gen/srv
        env:
          BP_NODE_RUN_SCRIPTS: ""

A good practice is to specify the Node version to use in the env section of the server module using the BP_NODE_VERSION variable:

Copy
_schema-version: '1.0'
repository: <your-container-image-repository-url> # Replace this with your container image repository URL
tag: latest # Replace this with your desired image tag
modules:
  - name: my-cap-app-srv # The module name for your CAP application.
    build-parameters:
      buildpack:
        type: nodejs
        builder: builder-jammy-base # The buildpack builder to use for building the container image. It specifies the base image and build environment for Node.js applications.
        path: gen/srv
        env:
          BP_NODE_RUN_SCRIPTS: "" # This environment variable is used to control the execution of npm scripts during the build process. Setting it to an empty string disables the execution of npm scripts, which can be useful for certain build scenarios.
          BP_NODE_VERSION: "22" # The Node.js version to use for building the application. You can specify a specific version or a range of versions.
  1. A chart/ folder with the Helm chart for your application, which is used to deploy your application to the Kyma runtime. Within this folder 3 main files will be generated: Chart.yaml, values.yaml and values.schema.json. The first 2 are described below. The values.schema.json file contains the JSON schema for the values.yaml file, which we will not describe in this post. Read more about Helm charts here.
Copy
# /chart/Chart.yaml
# This is a Helm chart for my-cap-app
apiVersion: v2
name: my-cap-app # The name of the Helm chart.
description: A simple CAP project.
type: application # The type of the Helm chart. In this case, it's an application chart.
version: 1.0.0
appVersion: 1.0.0
annotations:
  app.kubernetes.io/managed-by: cds-dk/helm # This annotation indicates that the Helm chart is managed by the CDS Development Kit (cds-dk).
dependencies:
  - name: web-application # The name of the dependent Helm chart. In this case, it's a web application chart template. Chart templates will be available in the `gen/` folder after the build process.
    alias: srv # The alias for the dependent chart. This allows you to refer to the dependent chart using a different name within your Helm chart. This alias is used in the `values.yaml` file to set the configuration variables of the dependent chart.
    version: ">0.0.0"
Copy
# /chart/values.yaml
# This file contains the default values for the Helm chart.
# yaml-language-server: $schema=./values.schema.json

global:
  domain: <your-kyma-subdomain>.kyma.ondemand.com # This is usually prepopulated from the `kubeconfig.yaml` file. Replace it if needed.
  imagePullSecret:
    name: docker-registry
  image:
    registry: cpit-cp-a2c-csid-support.common.repositories.cloud.sap
    tag: latest
srv: # This section contains the configuration for the server module of the CAP application. The `srv` matches the alias defined in the `Chart.yaml` file. The parameters below will fill the chart template of the dependency (in this case, a web-application chart template).
  bindings:
    {}
  image:
    repository: my-cap-app-srv
  resources:
    limits:
      ephemeral-storage: 1G
      memory: 500M
    requests:
      ephemeral-storage: 1G
      cpu: 500m
      memory: 500M
  health: # This section defines the kubernetes probes for the server module of the CAP application. The `liveness` and `readiness` probes are used to determine the health and availability of the application.
    liveness: 
      path: /health
    readiness:
      path: /health

Deploying the Application

Now we can deploy the application to the Kyma runtime. To do so we need to create first a namespace in the cluster, so all the resources of our application will be created under the same namespace. To create it use the following command:

Copy
kubectl create namespace my-namespace

And also label it to enable Istio injection:

Copy
kubectl label namespace my-namespace istio-injection=enabled

Now everything is prepared to push the application. Execute the command:

Copy
cds up -2 k8s --namespace my-namespace

This command will build the container image, push it to the registry we configured in the containerize.yaml file, and just after, the Kubernetes release will pull the image from the registry to deploy it in the specified namespace in the Kubernetes cluster of our Kyma runtime.

The first time we run this command for this namespace, it will ask for the image registry credentials, which will be stored in a Kubernetes secret called docker-registry in the namespace we specified. This secret will be used by the Kubernetes release to pull the image from the registry.

console prompt for docker registry secret

Use your Docker registry credentials to create the secret. After that, the deployment will continue and you will see the output of the deployment process.

Checking the Deployment

There are many ways to check the deployment of your application. The most common is to use the kubectl command to check the status of the pods in the namespace we deployed our application:

Copy
kubectl get all --namespace my-namespace

And then describe the pod, replicaSet, or other resources to check the logs:

Copy
kubectl describe pod <pod-name> --namespace my-namespace