Skip to main content

Deploying an Application to OBaaS

This guide walks through deploying an application to Oracle Backend for Microservices and AI (OBaaS). It covers each step from creating container repositories through exposing services via the API gateway.

The steps below are generic — replace placeholder values like my-app, my-service, and mydb with values appropriate to your application.

Prerequisites

Before you begin, ensure the following tools are installed and configured:

ToolPurposeVerify
JavaBuild application JARsjava -version
MavenBuild and packagemvn --version
DockerBuild and push container imagesdocker ps
kubectlInteract with Kubernetes clusterkubectl cluster-info
HelmDeploy applications to Kuberneteshelm version
OCI CLIManage OCI resources (if using OCIR)oci --version

Additional requirements:

  • JAVA_HOME must be set and point to your Java installation
  • Docker daemon must be running
  • kubectl must be connected to the target cluster (kubectl config current-context)
  • OBaaS platform must already be installed in your target namespace
tip

If you are using OCI Container Registry (OCIR), configure the OCI CLI first:

oci setup config

The registry URL is derived from your OCI region and namespace: <region>.ocir.io/<namespace>.

Step 1: Create Container Repositories

Each microservice needs a container repository to store its image. Create one repository per service in your container registry of choice — OCI Container Registry (OCIR), Amazon ECR, Azure Container Registry, Google Artifact Registry, Docker Hub, GitHub Container Registry, or any Docker V2-compatible registry. Use your provider's CLI or console to create the repositories, then authenticate Docker with docker login. The registry URL format varies by provider; consult your provider's documentation for the correct path. The rest of this guide works the same regardless of which registry you use.

The example below shows how to create repositories in OCI Container Registry. Adapt to your registry as needed.

# Set your variables
COMPARTMENT="my-compartment"
PREFIX="my-app"

# Get your compartment OCID
COMPARTMENT_OCID=$(oci iam compartment list --all \
--compartment-id-in-subtree true \
--query "data[?name=='${COMPARTMENT}'].id | [0]" \
--raw-output)

# Create a repository for each service
for SERVICE in service1 service2 service3; do
oci artifacts container repository create \
--compartment-id "$COMPARTMENT_OCID" \
--display-name "${PREFIX}/${SERVICE}" \
--is-public true
done

After creating the repositories, authenticate Docker to your registry:

docker login <registry-host>

Step 2: Build and Push Container Images

Configure JKube in Your pom.xml

The obaas-sample-app Helm chart expects a standard container image. Use Eclipse JKube to build and push images with Maven.

Add the JKube plugin to each service's pom.xml:

<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<version>1.18.2</version>
<configuration>
<images>
<image>
<name>${image.registry}/${project.artifactId}:${project.version}</name>
<build>
<from>ghcr.io/oracle/openjdk-image-obaas:21</from>
<assembly>
<mode>dir</mode>
<targetDir>/deployments</targetDir>
</assembly>
<cmd>java -jar /deployments/${project.artifactId}-${project.version}.jar</cmd>
</build>
</image>
</images>
</configuration>
</plugin>

Replace the <name> value with your registry path. The ${image.registry} property can be passed on the command line with -Dimage.registry=....

Build Dependencies

If your project has shared modules (parent POM, common libraries, build tools), install them to your local Maven repository first:

# Install parent POM
mvn clean install -N

# Install shared modules (adjust module names to your project)
mvn clean install -pl common

Build and Push

# Set your registry path
REGISTRY="<region>.ocir.io/<namespace>/my-app"

# Build the JAR
mvn clean package -DskipTests -pl my-service

# Build the container image
mvn org.eclipse.jkube:kubernetes-maven-plugin:build \
-pl my-service \
-Dimage.registry=$REGISTRY

# Push to registry
mvn org.eclipse.jkube:kubernetes-maven-plugin:push \
-pl my-service \
-Dimage.registry=$REGISTRY

Or combine build and push in a single command:

mvn clean package k8s:build k8s:push \
-DskipTests \
-pl my-service \
-Dimage.registry=$REGISTRY
tip

To build and push all services at once, pass a comma-separated list to -pl:

mvn clean package k8s:build k8s:push \
-DskipTests \
-pl service1,service2,service3 \
-Dimage.registry=$REGISTRY

Step 3: Create Database Secrets

If your application connects to an Oracle database, you need to create Kubernetes secrets containing the database credentials. The Helm chart uses these secrets to configure datasource environment variables and to run a database initialization job.

Secret Naming Convention

The Helm chart expects secrets following this naming pattern:

SecretPurposeKeys
{dbname}-db-priv-authnPrivileged credentials (for creating users, Liquibase)username, password, service
{dbname}-{service}-db-authnApplication credentials (per service)username, password, service

Create the Privileged Secret

The privileged secret must exist before deploying. It is typically created during OBaaS platform setup. If it does not exist, create it manually:

kubectl -n <namespace> create secret generic <dbname>-db-priv-authn \
--from-literal=username=ADMIN \
--from-literal=password='<admin-password>' \
--from-literal=service=<dbname>_tp

The service value is the TNS service name for your database (for example, mydb_tp).

Create Application Secrets

Create a secret for each distinct database user your application needs. Services that share a schema can share a secret.

kubectl -n <namespace> create secret generic <dbname>-<service>-db-authn \
--from-literal=username=<SERVICE_USERNAME> \
--from-literal=password='<service-password>' \
--from-literal=service=<dbname>_tp
Oracle Password Requirements

Oracle database passwords must meet the following rules:

  • 12–30 characters
  • At least two uppercase letters, two lowercase letters, two digits, and two special characters (# or _)
  • Cannot start with a digit or special character
  • Cannot contain the username

Oracle usernames are stored as uppercase by default.

Verify Secrets

# List all database secrets
kubectl get secrets -n <namespace> | grep db-authn

# View a secret's keys (not values)
kubectl describe secret <dbname>-<service>-db-authn -n <namespace>

# Decode a specific value
kubectl get secret <dbname>-<service>-db-authn -n <namespace> \
-o jsonpath='{.data.password}' | base64 -d

Step 4: Deploy with Helm

Add the Helm Repository

The obaas-sample-app Helm chart is published in the OBaaS Helm repository:

helm repo add obaas https://oracle.github.io/microservices-datadriven/helm
helm repo update

Verify the chart is available:

helm search repo obaas/obaas-sample-app

Identify the OBaaS Release Name

The Helm chart needs to know the OBaaS platform release name to derive service endpoints (Eureka, OTEL collector, APISIX, etc.). Find it with:

helm list -n <namespace>

Look for the release that is not an application deployment (i.e., not using the obaas-sample-app chart). This is your OBaaS platform release name.

Create a values.yaml

Create a values.yaml for each service you want to deploy. Here is a minimal example for a Spring Boot service:

fullnameOverride: "my-service"

image:
repository: "<region>.ocir.io/<namespace>/my-app/my-service"
tag: "0.0.1-SNAPSHOT"

obaas:
releaseName: "<obaas-release-name>"
framework: "SPRING_BOOT"

database:
name: "<dbname>"

eureka:
enabled: true

otel:
enabled: true

otmm:
enabled: false

For a Helidon service, set framework: "HELIDON" and add the required Helidon values:

obaas:
framework: "HELIDON"

helidon:
datasource:
name: "myDatasource" # Must match application.yaml
otel:
serviceName: "my-service"

Helm Values Reference

ValueRequiredDescription
image.repositoryYesFull image path (without tag)
image.tagYesImage tag
obaas.releaseNameYesOBaaS platform Helm release name
obaas.frameworkYesSPRING_BOOT or HELIDON
database.nameIf using DBDatabase name (derives secret names and wallet)
database.authN.secretNameNoOverride derived secret name {dbname}-{release}-db-authn
database.aq.enabledNoGrant Advanced Queuing (AQ/JMS) permissions (default: false)
eureka.enabledNoRegister with Eureka service discovery (default: true)
otel.enabledNoEnable OpenTelemetry integration (default: true)
otmm.enabledNoEnable MicroTx LRA distributed transactions (default: false)
service.portNoContainer and service port (default: 8080)
replicaCountNoNumber of pod replicas (default: 1)

Deploy a Service

helm upgrade --install my-service obaas/obaas-sample-app \
-f values.yaml \
--namespace <namespace> \
--set image.repository=<registry>/my-service \
--set image.tag=0.0.1-SNAPSHOT \
--set obaas.releaseName=<obaas-release> \
--set database.name=<dbname> \
--wait --timeout 5m

Values passed via --set override those in values.yaml. This is useful for CI/CD pipelines where the registry and tag vary per build.

What Gets Deployed

For each helm install, the chart creates:

  1. Deployment — your application pod with framework-aware environment variables (datasource, Eureka, OTEL, LRA)
  2. Service — a ClusterIP service on port 8080 (default)
  3. DB Init Job — a Kubernetes Job that runs SQLcl to create the database user if it doesn't already exist. It uses the privileged secret to connect and creates a user matching the application secret credentials. The job retries up to 60 times (10-second intervals) and auto-cleans after 5 minutes.
  4. DB Init ConfigMap — the SQL script used by the init job. If database.aq.enabled is true, AQ permissions (DBMS_AQ, DBMS_AQADM, etc.) are included.

The database wallet (TLS certificates for Oracle Autonomous Database) is automatically mounted at /oracle/tnsadmin from the OBaaS platform's wallet secret.

Verify the Deployment

# Check pod status
kubectl get pods -n <namespace>

# Check service
kubectl get svc -n <namespace>

# View pod logs
kubectl logs -n <namespace> -l app.kubernetes.io/name=my-service

# Check the db-init job
kubectl get jobs -n <namespace>

# Test connectivity via port-forward
kubectl port-forward -n <namespace> svc/my-service 8080:8080
curl http://localhost:8080/actuator/health

Upgrade and Uninstall

# Upgrade (after pushing a new image)
helm upgrade my-service obaas/obaas-sample-app \
-f values.yaml \
--namespace <namespace> \
--set image.tag=0.0.2-SNAPSHOT \
--wait --timeout 5m

# Uninstall
helm uninstall my-service -n <namespace>

Step 5: Create API Gateway Routes

The OBaaS platform uses Apache APISIX as its API gateway. To expose your services externally, create routes that map URI patterns to Eureka service names.

Get the APISIX Admin Key

The admin API key is stored in the APISIX ConfigMap:

# Replace <obaas-release> with your release name
kubectl get configmap <obaas-release>-apisix -n <namespace> \
-o jsonpath='{.data.config\.yaml}' | grep -A2 '"admin"'

Look for the key: value under the admin user.

Port-Forward to the Admin API

kubectl port-forward -n <namespace> svc/<obaas-release>-apisix-admin 9180:9180 &

Create a Route

ADMIN_KEY="<your-admin-key>"

curl http://localhost:9180/apisix/admin/routes/1 \
-H "X-API-KEY: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-X PUT \
-d '{
"name": "my-service",
"desc": "My Service",
"uri": "/api/v1/my-service*",
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"],
"upstream": {
"service_name": "MY-SERVICE",
"type": "roundrobin",
"discovery_type": "eureka"
},
"plugins": {
"opentelemetry": {
"sampler": {
"name": "always_on"
}
},
"prometheus": {
"prefer_name": true
}
}
}'

Key fields:

FieldDescription
uriThe URL pattern to match. Use a wildcard suffix (e.g., /api/v1/my-service*).
upstream.service_nameThe Eureka-registered service name (uppercase by default for Spring Boot).
upstream.discovery_typeSet to eureka so APISIX resolves service instances from the Eureka registry.
plugins.opentelemetryEnables distributed tracing through the gateway.
plugins.prometheusEnables Prometheus metrics collection for the route.

Verify the Route

# Test through the gateway
curl http://<apisix-gateway>/api/v1/my-service/health

# List all routes
curl http://localhost:9180/apisix/admin/routes \
-H "X-API-KEY: $ADMIN_KEY" | jq '.list[].value.name'

Stop Port-Forward

When done configuring routes, stop the port-forward:

kill %1

Summary

The full deployment flow:

StepWhatHow
1Create container repositoriesOCI CLI or registry UI
2Build and push imagesMaven + JKube (k8s:build + k8s:push)
3Create database secretskubectl create secret
4Deploy with Helmhelm upgrade --install with obaas-sample-app chart
5Create API gateway routesAPISIX Admin API via curl

After all steps are complete, your application is accessible through the APISIX gateway at the URI patterns you configured.