Kyma/Kubernetes mit ABAP Cloud: Cloud-Native Extensions entwickeln

kategorie
Integration
Veröffentlicht
autor
Johannes

SAP BTP Kyma Runtime bringt Kubernetes in die SAP-Welt und ermöglicht Cloud-native Entwicklung mit Containern, Microservices und serverless Functions. In Kombination mit ABAP Cloud entstehen leistungsfähige hybride Architekturen, bei denen Kubernetes-Workloads nahtlos mit ABAP-Backend-Services kommunizieren.

Was ist Kyma/Kubernetes im SAP-Kontext?

Kyma ist SAPs managed Kubernetes-Distribution auf der Business Technology Platform. Es basiert auf dem Open-Source-Projekt Kyma (github.com/kyma-project) und bietet eine vollständig verwaltete Kubernetes-Umgebung mit SAP-spezifischen Erweiterungen.

Kernkomponenten von Kyma

KomponenteBeschreibungSAP-Integration
Kubernetes ClusterContainer-OrchestrierungManaged by SAP
Istio Service MeshTraffic Management, SecurityAutomatische mTLS
Serverless FunctionsEvent-getriebene LogikNode.js, Python
EventingEvent-basierte IntegrationSAP Event Mesh kompatibel
API GatewayExterne API-ExpositionOAuth2/JWT-Schutz
Service CatalogBTP-Service-AnbindungXSUAA, Destination, etc.

Kubernetes-Grundlagen für SAP-Entwickler

Kubernetes organisiert Anwendungen in mehreren Abstraktionsebenen:

┌─────────────────────────────────────────────────────────────────────┐
│ Kyma Cluster │
├─────────────────────────────────────────────────────────────────────┤
│ Namespace: my-extension-app │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Deployment: backend-service │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ Pod (Replica 1) Pod (Replica 2) │ │ │
│ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │
│ │ │ │ Container: │ │ Container: │ │ │ │
│ │ │ │ node:18-alpine │ │ node:18-alpine │ │ │ │
│ │ │ └─────────────────┘ └─────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Service: backend-service (ClusterIP) │ │
│ │ Port: 8080 → TargetPort: 8080 │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ API Rule: backend-api (External Access via Istio Gateway) │ │
│ │ Host: backend.c-abc123.kyma.ondemand.com │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

Cloud Foundry vs Kyma Runtime: Vergleich

SAP BTP bietet zwei Runtime-Umgebungen für Custom Development. Die Wahl hängt von Architekturanforderungen und Team-Expertise ab.

AspektCloud FoundryKyma Runtime
AbstraktionsebenePaaS (Platform as a Service)CaaS (Container as a Service)
Deployment-EinheitBuildpacks (App wird gepackt)Container Images (volle Kontrolle)
SkalierungApp-InstanzenPod-Replicas, HPA
Konfigurationmanifest.yml, mta.yamlKubernetes YAML, Helm Charts
NetworkingCF RouterIstio Service Mesh
ServerlessNein (nur Apps)Ja (Kyma Functions)
Service BindingCF Service BrokerKubernetes Secrets
EinstiegshürdeNiedrigMittel bis hoch
FlexibilitätEingeschränktSehr hoch
SAP CAPNative UnterstützungUnterstützt
Typischer EinsatzKlassische Web-AppsMicroservices, Event-Handler

Wann Kyma wählen?

Kyma ist die richtige Wahl, wenn:

  • Container-Expertise im Team vorhanden ist
  • Microservice-Architektur mit vielen kleinen Services angestrebt wird
  • Event-getriebene Szenarien mit Functions umgesetzt werden
  • Bestehende Container-Images deployed werden sollen
  • Feinkörnige Kontrolle über Ressourcen und Networking erforderlich ist

Architektur: Kyma Extension mit ABAP Cloud Backend

Das folgende Diagramm zeigt eine typische Side-by-Side Extension, bei der eine Kyma-Anwendung ABAP Cloud als Backend nutzt:

┌─────────────────────────────────────────────────────────────────────────────┐
│ SAP Business Technology Platform │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ ┌─────────────────────────────────┐ │
│ │ ABAP Cloud (Steampunk) │ │ Kyma Runtime │ │
│ │ │ │ │ │
│ │ ┌───────────────────────────┐ │ │ ┌────────────────────────────┐ │ │
│ │ │ RAP Business Object │ │ │ │ Frontend (React/Vue) │ │ │
│ │ │ │ │ │ │ Container: nginx │ │ │
│ │ │ ┌─────────────────────┐ │ │ │ └────────────────────────────┘ │ │
│ │ │ │ CDS View Entity │ │ │ │ │ │ │
│ │ │ │ ZI_SalesOrder │ │ │ │ ▼ │ │
│ │ │ └─────────────────────┘ │ │ │ ┌────────────────────────────┐ │ │
│ │ │ ┌─────────────────────┐ │ │ │ │ Backend Service │ │ │
│ │ │ │ Behavior Definition │ │ │ │ │ Container: node:18 │ │ │
│ │ │ │ (Validations, etc.) │ │ │ │ │ │ │ │
│ │ │ └─────────────────────┘ │ │ │ │ - Business Logic │ │ │
│ │ └───────────────────────────┘ │ │ │ - Data Transformation │ │ │
│ │ │ │ │ - Caching │ │ │
│ │ ┌───────────────────────────┐ │ │ └────────────────────────────┘ │ │
│ │ │ OData V4 Service │ │ │ │ │ │
│ │ │ /sap/opu/odata4/... │◄─┼────┼──────────────┘ │ │
│ │ └───────────────────────────┘ │ │ HTTP/OData │ │
│ │ │ │ │ │
│ │ ┌───────────────────────────┐ │ │ ┌────────────────────────────┐ │ │
│ │ │ RAP Business Events │──┼────┼─>│ Kyma Function │ │ │
│ │ │ (Event Mesh) │ │ │ │ (Event Handler) │ │ │
│ │ └───────────────────────────┘ │ │ └────────────────────────────┘ │ │
│ │ │ │ │ │
│ └─────────────────────────────────┘ └─────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Shared BTP Services │ │
│ │ ┌──────────┐ ┌──────────────┐ ┌─────────────┐ ┌───────────────┐ │ │
│ │ │ XSUAA │ │ Destination │ │ Event Mesh │ │ Connectivity │ │ │
│ │ │ (Auth) │ │ Service │ │ │ │ (SCC) │ │ │
│ │ └──────────┘ └──────────────┘ └─────────────┘ └───────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Deployment-Konfiguration: Kubernetes YAML

1. Deployment für Backend-Service

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sales-extension-backend
namespace: sales-extension
labels:
app: sales-extension
component: backend
spec:
replicas: 2
selector:
matchLabels:
app: sales-extension
component: backend
template:
metadata:
labels:
app: sales-extension
component: backend
spec:
containers:
- name: backend
image: myregistry.io/sales-extension:1.0.0
ports:
- containerPort: 8080
env:
- name: ABAP_CLOUD_URL
valueFrom:
secretKeyRef:
name: abap-destination
key: url
- name: NODE_ENV
value: "production"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5

2. Service und API Rule

service.yaml
apiVersion: v1
kind: Service
metadata:
name: sales-extension-backend
namespace: sales-extension
spec:
selector:
app: sales-extension
component: backend
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
---
# api-rule.yaml
apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
name: sales-extension-api
namespace: sales-extension
spec:
gateway: kyma-gateway.kyma-system.svc.cluster.local
host: sales-extension.c-abc123.kyma.ondemand.com
service:
name: sales-extension-backend
port: 8080
rules:
- path: /.*
methods: ["GET", "POST", "PUT", "DELETE"]
accessStrategies:
- handler: jwt
config:
jwks_urls:
- https://mysubaccount.authentication.eu10.hana.ondemand.com/token_keys
trusted_issuers:
- https://mysubaccount.authentication.eu10.hana.ondemand.com/oauth/token

Service Binding: ABAP Cloud mit Kyma verbinden

Die Anbindung an ABAP Cloud erfolgt über den SAP Destination Service. Die Destination-Credentials werden als Kubernetes Secret gemounted.

Service Binding erstellen

service-binding.yaml
apiVersion: services.cloud.sap.com/v1
kind: ServiceBinding
metadata:
name: abap-destination-binding
namespace: sales-extension
spec:
serviceInstanceName: destination-instance
secretName: abap-destination
parameters:
# Destination im BTP Cockpit muss existieren
destinationName: "ABAP_CLOUD_BACKEND"

Destination im Code verwenden (Node.js)

src/abap-client.js
const axios = require('axios');
class AbapCloudClient {
constructor() {
// Credentials aus Kubernetes Secret (Environment Variables)
this.baseUrl = process.env.ABAP_CLOUD_URL;
this.clientId = process.env.ABAP_CLIENT_ID;
this.clientSecret = process.env.ABAP_CLIENT_SECRET;
this.tokenUrl = process.env.ABAP_TOKEN_URL;
this.accessToken = null;
this.tokenExpiry = null;
}
async getAccessToken() {
// Token cachen bis kurz vor Ablauf
if (this.accessToken && this.tokenExpiry > Date.now() + 60000) {
return this.accessToken;
}
const response = await axios.post(this.tokenUrl,
'grant_type=client_credentials', {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
auth: {
username: this.clientId,
password: this.clientSecret
}
});
this.accessToken = response.data.access_token;
this.tokenExpiry = Date.now() + (response.data.expires_in * 1000);
return this.accessToken;
}
async getSalesOrders(filter = '') {
const token = await this.getAccessToken();
const url = `${this.baseUrl}/sap/opu/odata4/sap/zsalesorder/srvd/sap/zsalesorder/0001/SalesOrder`;
const response = await axios.get(url, {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
},
params: { '$filter': filter }
});
return response.data.value;
}
async createSalesOrder(orderData) {
const token = await this.getAccessToken();
const url = `${this.baseUrl}/sap/opu/odata4/sap/zsalesorder/srvd/sap/zsalesorder/0001/SalesOrder`;
const response = await axios.post(url, orderData, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return response.data;
}
}
module.exports = AbapCloudClient;

Kyma Function für Event-Handling

RAP Business Events können über SAP Event Mesh an Kyma Functions weitergeleitet werden:

function.yaml
apiVersion: serverless.kyma-project.io/v1alpha2
kind: Function
metadata:
name: order-created-handler
namespace: sales-extension
spec:
runtime: nodejs18
source:
inline:
source: |
const axios = require('axios');
module.exports = {
main: async function (event, context) {
console.log('Received event:', JSON.stringify(event.data));
// Event-Daten aus CloudEvents-Format extrahieren
const orderData = event.data;
const orderId = orderData.SalesOrderId;
const customerId = orderData.CustomerId;
// Externe API benachrichtigen (z.B. CRM-System)
try {
await axios.post('https://crm-api.example.com/orders', {
sapOrderId: orderId,
customerId: customerId,
status: 'CREATED'
});
return { statusCode: 200, body: 'Notification sent' };
} catch (error) {
console.error('CRM notification failed:', error.message);
return { statusCode: 500, body: error.message };
}
}
};
dependencies: |
{
"dependencies": {
"axios": "^1.6.0"
}
}
subscriptions:
- name: order-events
source: sap.s4.beh.salesorder.v1.SalesOrder.Created.v1
typeMatching: exact

Praktischer Use Case: Side-by-Side Extension

Szenario: Kundenspezifische Rabattberechnung

Ein Unternehmen möchte eine kundenspezifische Rabattlogik implementieren, die:

  • Kundendaten aus ABAP Cloud (CRM-Stammdaten) liest
  • Machine-Learning-Modell für Rabattvorhersage nutzt
  • Ergebnisse in Echtzeit an die Fiori-App zurückgibt

Implementierungsschritte

1. ABAP Cloud: OData Service für Kundendaten

" CDS View für Kundeninformationen
@EndUserText.label: 'Customer for Discount Calculation'
@AccessControl.authorizationCheck: #CHECK
define view entity ZI_CustomerDiscount
as select from zcustomer_db
{
key customer_id as CustomerId,
customer_name as CustomerName,
customer_tier as CustomerTier,
total_revenue as TotalRevenue,
orders_count as OrdersCount,
last_order_date as LastOrderDate
}

2. Kyma: Discount-Service mit ML-Integration

discount-service/src/index.js
const express = require('express');
const AbapCloudClient = require('./abap-client');
const MLPredictor = require('./ml-predictor');
const app = express();
const abapClient = new AbapCloudClient();
const mlPredictor = new MLPredictor();
app.get('/api/discount/:customerId', async (req, res) => {
try {
const { customerId } = req.params;
const { orderValue } = req.query;
// 1. Kundendaten aus ABAP Cloud abrufen
const customer = await abapClient.getCustomer(customerId);
// 2. ML-Modell für Rabattvorhersage aufrufen
const predictedDiscount = await mlPredictor.predict({
customerTier: customer.CustomerTier,
totalRevenue: customer.TotalRevenue,
ordersCount: customer.OrdersCount,
orderValue: parseFloat(orderValue)
});
// 3. Ergebnis zurückgeben
res.json({
customerId: customerId,
customerName: customer.CustomerName,
suggestedDiscount: predictedDiscount,
maxDiscount: getMaxDiscount(customer.CustomerTier)
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
function getMaxDiscount(tier) {
const limits = { 'GOLD': 25, 'SILVER': 15, 'BRONZE': 10 };
return limits[tier] || 5;
}
app.listen(8080);

3. Integration in Fiori Elements

Die Kyma-Extension kann über einen Custom Controller in der Fiori-App aufgerufen werden, um den empfohlenen Rabatt anzuzeigen.

Best Practices für Kyma mit ABAP Cloud

Sicherheit

  • JWT-Validierung in APIRules aktivieren
  • XSUAA-Integration für konsistente Authentifizierung
  • Network Policies für Pod-zu-Pod-Kommunikation

Performance

  • Connection Pooling für ABAP-Verbindungen
  • Caching von Token und häufig abgerufenen Daten
  • Horizontal Pod Autoscaler für lastabhängige Skalierung

Monitoring

  • Prometheus/Grafana für Metriken (in Kyma integriert)
  • Application Logging korreliert mit ABAP-Logs
  • Distributed Tracing für Request-Verfolgung

Fazit

Die Kombination von Kyma/Kubernetes mit ABAP Cloud ermöglicht moderne Cloud-native Architekturen, ohne auf die Stärken des ABAP-Backends verzichten zu müssen. Während Cloud Foundry den einfacheren Einstieg bietet, liefert Kyma maximale Flexibilität für komplexe Microservice-Szenarien.

Typische Anwendungsfälle:

  • Event-Handler für RAP Business Events
  • API-Gateways mit zusätzlicher Logik
  • ML-Integration und externe Services
  • Custom UIs als Container-Anwendungen

Die Entscheidung zwischen Cloud Foundry und Kyma sollte basierend auf Team-Expertise, Architekturanforderungen und langfristiger Strategie getroffen werden. Für Teams mit Kubernetes-Erfahrung und Microservice-Architekturen ist Kyma die natürliche Wahl.