CAPApplicationVersion
CAPApplicationVersion resource10 minute read
The CAPApplicationVersion has the following high level structure:
apiVersion: sme.sap.com/v1alpha1
kind: CAPApplicationVersion
metadata:
name: cav-cap-app-v1
namespace: cap-ns
spec:
version: 3.2.1 # <-- semantic version (must be unique within the versions of a CAP application)
capApplicationInstance: cap-app
registrySecrets: # <-- image pull secrets to be used in the workloads
- regcred
workloads: # <-- define deployments and jobs used for this application version
- name: "cap-backend"
deploymentDefinition: # ...
consumedBTPServices: # ...
- name: "app-router"
deploymentDefinition: # ...
consumedBTPServices: # ...
- name: "service-content"
jobDefinition: # ...
consumedBTPServices: # ...
- name: "tenant-operation"
jobDefinition: # ...
consumedBTPServices: # ...
tenantOperations: # ... <-- (optional)
- An instance of
CAPApplicationVersionis always related to an instance ofCAPApplicationin the same namespace. This reference is established using the attributecapApplicationInstance. - An array of workloads (
workloads) must be defined that include the various software components of the SAP Cloud Application Programming Model application. A deployment representing the CAP application server or a job that which is used for tenant operations are examples of such workloads. A workload must have either adeploymentDefinitionor ajobDefinition. See the next section for more details. - An optional attribute
tenantOperationscan be used to define a sequence of steps (jobs) to be executed during tenant operations (provisioning / upgrade / deprovisioning).
The
CAPApplicationVersionresource is meant to be immutable - it’s spec should not be modified once it is deployed. This is also prevented by our web-hooks which we recommend to always keep active (default).
Workloads with deploymentDefinition
name: cap-backend
consumedBTPServices: # <-- an array of service instance names referencing the SAP BTP services defined in the CAPApplication resource
- cap-uaa
- cap-saas-reg
deploymentDefinition:
type: CAP # <-- possible values are CAP / Router / Additional / Service
image: some.repo.example.com/cap-app/server:3.22.11 # <-- container image
env: # <-- (optional) same as in core v1 pod.spec.containers.env
- name: SAY
value: "I'm GROOT"
replicas: 3 # <-- (optional) replicas for scaling
ports:
- name: app-port
port: 4004
routerDestinationName: cap-server-url
- name: tech-port
port: 4005
monitoring:
scrapeConfig:
port: tech--port
deletionRules:
expression: scalar(sum(avg_over_time(current_sessions{job="cav-cap-app-v1-cap-backend-svc",namespace="cap-ns"}[2h]))) <= bool 5
The type of the deployment is important to indicate how the operator handles this workload (for example, injection of destinations to be used by the approuter). Valid values are:
CAPto indicate a CAP application server. Only one workload of this type can be used at present.Routerto indicate a version of AppRouter. Only one workload of this type can be used.Additionalto indicate supporting components that can be deployed along with the CAP application server.
You can define optional attributes such as replicas, env, resources, probes, securityContext, initContainers and ports to configure the deployment.
Port configuration
It’s possible to define which (and how many) ports exposed by a deployment container are exposed inside the cluster (via services of type ClusterIP). The port definition includes a name in addition to the port number being exposed.
For deploymentDefinition, other than type Router it would be possible to specify a routerDestinationName which would be used as a named destination injected into the approuter.
The port configurations aren’t mandatory and can be omitted. This would mean that the operator will configure services using defaults. The following defaults are applied if port configuration is omitted:
- For workload of type
CAP, the default port used by CAP,4004, will be added to the service and a destination with namesrv-apiwill be added to the approuter referring to this service port (any existingdestinationsenvironment configuration for this workload will be taken over by overwriting theURL). - For workload of type
Router, the port5000will be exposed in the service. This service will be used as the target for HTTP traffic reaching the application domain (domains are specified within theCAPApplicationresource).
NOTE: If multiple ports are configured for a workload of type
Router, the first available port will be used to target external traffic to the application domain.
Monitoring configuration
For each workload of type deployment in a CAPApplicationVersion, it is possible to define:
- Deletion rules: A criteria based on metrics which when satisfied signifies that the workload can be removed
- Scrape configuration: Configuration which defines how metrics are scraped from the workload service.
Details of how to configure workload monitoring can be found here.
Workloads with jobDefinition
workloads:
# ... deployment workloads have been omitted in this example
- name: "content-deployer"
consumedServices: # ...
jobDefinition:
type: Content
image: some.repo.example.com/cap-app/content:1.0.1
- name: "tenant-operation"
consumedServices: # ...
jobDefinition:
type: TenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
backoffLimit: 2 # <-- determines retry attempts for the job on failure (default is 6)
ttlSecondsAfterFinished: 300 # <-- the job will be cleaned up after this duration
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
- name: "notify-upgrade"
consumedServices: # ...
jobDefinition:
type: CustomTenantOperation
image: # ...
command: ["npm", "run", "notify:upgrade"] # <-- custom entry point for the container allows reuse of a container image with multiple entry points
backoffLimit: 1
- name: "create-test-data"
consumedServices: # ...
jobDefinition:
type: CustomTenantOperation
image: # ...
command: ["npm", "run ", "deploy:testdata"]
Workloads with a jobDefinition represent a job execution at a particular point in the lifecycle of the application or tenant. The following values are allowed for type in such workloads:
Content: A content deployer job that can be used to deploy (SAP BTP) service specific content from the application version. This job is executed as soon as a newCAPApplicationVersionresource is created in the cluster. Multiple workloads of this type may be defined in theCAPApplicationVersionand the order in which they are executed can be specified viaContentJobs.TenantOperation: A job executed during provisioning, upgrade, or deprovisioning of a tenant (CAPTenant). These jobs are controlled by the operator and use thecds/mtxsAPIs to perform HDI content deployment by default. If a workload of typeTenantOperationisn’t provided as part of theCAPApplicationVersion, the workload withdeploymentDefinitionof typeCAPwill be used to determine thejobDefinition(image,env, etc.). Also, ifcds/mtxsAPIs are used,commandcan be used by applications to trigger tenant operations with custom command.CustomTenantOperation: An optional job which runs before or after theTenantOperationwhere the application can perform tenant-specific tasks (for example, create test data).
Sequencing tenant operations
A tenant operation refers to provisioning, upgrade or deprovisioning which are executed in the context of a CAP application for individual tenants (i.e. using the cds/mtxs or similar modules provided by CAP). Within the workloads, we have already defined two types of jobs that are valid for such operations, namely TenantOperation and CustomTenantOperation.
The TenantOperation is mandatory for all tenant operations.
In addition, you can choose which CustomTenantOperation jobs run for a specific operation and in which order. For example, a CustomTenantOperation deploying test data to the tenant database schema would need to run during provisioning, but must not run during deprovisioning.
The field tenantOperations specifies which jobs are executed during the different tenant operations and the order they are executed in.
spec:
workloads: # ...
tenantOperations:
provisioning:
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
upgrade:
- workloadName: "notify-upgrade"
continueOnFailure: true # <-- indicates the overall operation may proceed even if this step fails
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
# <-- as the deprovisioning steps are not specified, only the `TenantOperation` workload (first available) will be executed
In the example above, for each tenant operation, not only are the valid jobs (steps) specified, but also the order in which they are to be executed. Each step in an operation is defined with:
workloadNamerefers to the job workload executed in this operation stepcontinueOnFailureis valid only forCustomTenantOperationsteps and indicates whether the overall tenant operation can proceed when this operation step fails.
NOTE:
- Specifying
tenantOperationsis required only ifCustomTenantOperationsare to be used. If not specified, each operation will comprise of only theTenantOperationstep (the first one available fromworkloads).- The
tenantOperationsand specified sequencing are valid only for tenants provisioned (or deprovisioned) on the correspondingCAPApplicationVersionand for tenants being upgraded to thisCAPApplicationVersion.
Sequencing content jobs
When you create a CAPApplicationVersion workload, you can define multiple content jobs. The order in which these jobs are executed is important, as some jobs may depend on the output of others. The ContentJobs property allows you to specify the order in which content jobs are executed.
spec:
workloads: # ...
tenantOperations: # ...
contentJobs:
- content-deployer-service
- content-deployer-ui
Services / Tenant independent workloads
spec:
workloads:
- name: cap-backend-service
consumedBTPServices: # <-- an array of service instance names referencing the SAP BTP services defined in the CAPApplication resource
- cap-uaa
- cap-saas-reg
deploymentDefinition:
type: Service # <-- possible values are CAP / Router / Additional / Service
image: some.repo.example.com/cap-app/server:3.22.11 # <-- container image
env: # <-- (optional) same as in core v1 pod.spec.containers.env
- name: SAY
value: "I'm GROOT"
replicas: 3 # <-- (optional) replicas for scaling
ports: # Some configs like routerDestinationName are not relevant for ServicesOnly scenario
- name: app-port
port: 4004
- name: tech-port
port: 4005
- name: api
port: 8000
appProtocol: http
- name: service-content
consumedBTPServices:
- app-uaa
- app-html5-repo-host
- app-portal
jobDefinition:
type: Content
image: app.some.repo.example.com/approuter/content:0.0.1
backoffLimit: 1
serviceExposures:
- subDomain: service
routes:
- workloadName: cap-backend-service
port: 4004
- subDomain: api
routes:
- workloadName: cap-backend-service
port: 8000
path: /api
Here too the type of the deployment is important to indicate how the operator handles this workload. For Services Only scenario only Service type is valid. You can also have jobs of type Content to deploy application content related to UI, DB as needed.
Other attributes can be configured as documented.
Port configuration
It’s possible to define which (and how many) ports exposed by a deployment container are exposed inside the cluster (via services of type ClusterIP). The port definition includes a name in addition to the port number being exposed.
For service only workloads the routerDestinationName is not relevant.
The port configurations are mandatory and cannot be omitted.
Full Example
apiVersion: sme.sap.com/v1alpha1
kind: CAPApplicationVersion
metadata:
name: cav-cap-app-v1
namespace: cap-ns
spec:
version: 3.2.1
capApplicationInstance: cap-app
registrySecrets:
- regcred
workloads:
- name: cap-backend
consumedBTPServices:
- cap-uaa
- cap-service-manager
- cap-saas-reg
deploymentDefinition:
type: CAP
image: some.repo.example.com/cap-app/server:3.22.11
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
replicas: 3
ports:
- name: app-port
port: 4004
routerDestinationName: cap-server-url
- name: tech-port
port: 4005
appProtocol: grpc
monitoring:
scrapeConfig:
port: tech--port
deletionRules:
expression: scalar(sum(avg_over_time(current_sessions{job="cav-cap-app-v1-cap-backend-svc",namespace="cap-ns"}[2h]))) <= bool 5
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4005
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 4005
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 20m
memory: 50Mi
securityContext:
runAsUser: 1000
runAsGroup: 2000
- name: "app-router"
consumedBTPServices:
- cap-uaa
- cap-saas-reg
- cap-html5-repo-rt
deploymentDefinition:
type: Router
image: some.repo.example.com/cap-app/router:4.0.1
env:
- name: PORT
value: "3000"
ports:
- name: router-port
port: 3000
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 3000
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: 3000
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 2
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 20m
memory: 50Mi
podSecurityContext:
runAsUser: 2000
fsGroup: 2000
- name: "service-content"
consumedServices:
- cap-uaa
- cap-portal
- cap-html5-repo-host
jobDefinition:
type: Content
image: some.repo.example.com/cap-app/content:1.0.1
securityContext:
runAsUser: 1000
runAsGroup: 2000
- name: "ui-content"
consumedServices:
- cap-uaa
- cap-portal
- cap-html5-repo-host
jobDefinition:
type: Content
image: some.repo.example.com/cap-app/ui-content:1.0.1
securityContext:
runAsUser: 1000
runAsGroup: 2000
- name: "tenant-operation"
consumedServices: # ...
jobDefinition:
type: TenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
backoffLimit: 2
ttlSecondsAfterFinished: 300
env:
- name: CDS_ENV
value: production
- name: CDS_CONFIG
value: '{ "requires":{"cds.xt.DeploymentService":{"hdi": { "create":{ "database_id": "16e25c51-5455-4b17-a4d7-43545345345" } } } } }'
- name: "notify-upgrade"
consumedServices: []
jobDefinition:
type: CustomTenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
command: ["npm", "run", "notify:upgrade"]
backoffLimit: 1
- name: "create-test-data"
consumedServices:
- cap-service-manager
jobDefinition:
type: CustomTenantOperation
image: some.repo.example.com/cap-app/server:3.22.11
command: ["npm", "run ", "deploy:testdata"]
tenantOperations:
provisioning:
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
upgrade:
- workloadName: "notify-upgrade"
continueOnFailure: true
- workloadName: "tenant-operation"
- workloadName: "create-test-data"
contentJobs:
- service-content
- ui-content
NOTE: The CAP Operator workloads supports several configurations (present in the kubernetes API), which can be configured by looking into our API reference:
- Container API reference for generic container-specific configuration
- Deployment API reference for deployment-specific configuration
- Job API reference for job-specific configuration
The supported configurations is kept minimal intentionally to keep the overall API simple by considering commonly used configurations.
Note: For
initContainersnearly the same environment variables as the main container are made available including VCAP_SERVICES environment.