From 2384c652c39b12af0af92294ee2f708c8713f2bc Mon Sep 17 00:00:00 2001 From: Doug Drechsel Date: Thu, 9 Oct 2025 15:38:04 -0400 Subject: [PATCH 1/2] Multi Framework Installation Helm Support with Comprehensive documentation --- helm/charts/obaas-sample-app/README.md | 1264 ++++++++++++++++- .../templates/deployment.yaml | 135 +- helm/charts/obaas-sample-app/values.yaml | 124 +- 3 files changed, 1450 insertions(+), 73 deletions(-) diff --git a/helm/charts/obaas-sample-app/README.md b/helm/charts/obaas-sample-app/README.md index 9403cc5e0..b3e00ccbd 100644 --- a/helm/charts/obaas-sample-app/README.md +++ b/helm/charts/obaas-sample-app/README.md @@ -1,16 +1,1262 @@ -# OBaas Sample App Chart +# OBaaS Sample Application Helm Chart -This chart provides an extensible sample for applications running on [OBaaS](https://oracle.github.io/microservices-datadriven/obaas/). +This Helm chart provides a **framework-agnostic** deployment template for microservices applications on the Oracle Backend for Microservices and AI (OBaaS) platform. It supports both **Spring Boot** and **Helidon** frameworks with automatic configuration of database integration, service discovery, and observability. -To use this chart for a given application, download the chart and update the [Chart.name](./Chart.yaml) value to your application's name. +## Table of Contents -## Customizing the chart +- [Overview](#overview) +- [Architecture](#architecture) +- [Prerequisites](#prerequisites) +- [Quick Start](#quick-start) +- [Configuration Guide](#configuration-guide) + - [Spring Boot Deployment](#spring-boot-deployment) + - [Helidon Deployment](#helidon-deployment) +- [Framework Comparison](#framework-comparison) +- [Observability and Metrics](#observability-and-metrics) +- [Secrets Management](#secrets-management) +- [Troubleshooting](#troubleshooting) +- [Examples](#examples) -The OBaaS sample app chart is meant to serve as a developer template, and is fully customizable. +## Overview -Standard parameters for Kubernetes options like node affinity, HPAs, ingress and more are provided in the [values.yaml file](./values.yaml). +This Helm chart automatically configures framework-specific settings based on a single `framework` parameter. It eliminates the need for separate charts or complex conditional logic in your application code. -## OBaaS options +### Key Features -Within the [values.yaml file](./values.yaml), the `obaas` key allows chart developers to enable or disable OBaaS integrations like database connectivity, OpenTelemetry, MicroProfile LRA, SpringBoot, and Eureka. -enabled: true +- **Single Framework Parameter**: Set `framework: SPRING_BOOT` or `framework: HELIDON` to automatically configure all framework-specific settings +- **Automatic Health Checks**: Framework-appropriate liveness and readiness probe endpoints +- **Built-in Observability**: OpenTelemetry integration with SigNoz for metrics, traces, and logs +- **Oracle Database Integration**: Autonomous Database (ADB) wallet mounting and connection configuration +- **Service Discovery**: Optional Eureka registration for microservices communication +- **Production Ready**: Includes resource management, autoscaling, and health probe configurations + +### What Gets Auto-Configured + +| Feature | Spring Boot | Helidon | +|---------|-------------|---------| +| **Health Endpoints** | `/actuator/health/liveness`
`/actuator/health/readiness` | `/health/live`
`/health/ready` | +| **Metrics Endpoint** | `/actuator/prometheus` | `/metrics` | +| **Database Config** | `SPRING_DATASOURCE_*` env vars | `javax.sql.DataSource.*` env vars | +| **Eureka Integration** | Spring Cloud Netflix | Helidon Eureka client | +| **OTEL Protocol** | HTTP/protobuf (port 4318) | HTTP/protobuf (port 4318) + auto-configure | +| **Service Name** | Auto from release name | Configurable via `otel.serviceName` | + +## Architecture + +### Deployment Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Kubernetes Cluster │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────┐ ┌──────────────────────┐ │ +│ │ Your App Pod │ │ OBaaS Platform │ │ +│ ├───────────────┤ ├──────────────────────┤ │ +│ │ │ │ │ │ +│ │ Spring Boot │◄────────┤ Eureka (Discovery) │ │ +│ │ or │ │ │ │ +│ │ Helidon MP │◄────────┤ SigNoz (Observ.) │ │ +│ │ │ │ │ │ +│ │ ┌─────────┐ │ │ APISIX (Gateway) │ │ +│ │ │ Wallet │ │ │ │ │ +│ │ │ Mount │ │ │ Config Server │ │ +│ │ └─────────┘ │ │ │ │ +│ └───────┬───────┘ └──────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────┐ │ +│ │ Oracle ADB │ │ +│ │ (Autonomous) │ │ +│ └───────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Template Structure + +``` +obaas-sample-app/ +├── Chart.yaml # Chart metadata +├── values.yaml # Default configuration (with TODOs) +├── templates/ +│ ├── deployment.yaml # Main deployment with framework conditionals +│ ├── service.yaml # Kubernetes service +│ ├── serviceaccount.yaml # Service account (optional) +│ ├── ingress.yaml # Ingress (optional) +│ ├── hpa.yaml # Horizontal Pod Autoscaler (optional) +│ └── _helpers.tpl # Template helpers +└── README.md # This file +``` + +**Key Design Point**: The `deployment.yaml` template uses Helm conditionals (`{{- if eq .Values.obaas.framework "HELIDON" }}`) to render framework-specific environment variables, eliminating the need for multiple deployment templates. + +## Prerequisites + +### Required Infrastructure + +1. **OBaaS Platform**: Installed in your Kubernetes cluster + ```bash + # Verify OBaaS installation + kubectl get configmap obaas-config -n + kubectl get configmap obaas-observability-config -n + ``` + +2. **Kubernetes Cluster**: CNCF-compliant (v1.33.1+) + ```bash + kubectl version --short + ``` + +3. **Helm**: Version 3.8+ + ```bash + helm version + ``` + +### Required Secrets + +You'll need to create these secrets before deploying: + +1. **Database Credentials Secret** - Contains Oracle DB connection info +2. **ADB Wallet Secret** - Contains Autonomous Database wallet files +3. **Image Pull Secret** - For pulling from private container registries (optional) + +See [Secrets Management](#secrets-management) section for creation commands. + +## Quick Start + +### 1. Prepare Your Application + +**For Spring Boot:** +- Add Spring Boot Actuator for health checks +- Add Spring Cloud Eureka Client for service discovery (optional) +- Add OpenTelemetry instrumentation for observability + +**For Helidon:** +- Add Helidon Health for health checks +- Configure datasource name in `microprofile-config.properties` +- Add Helidon Eureka integration for service discovery (optional) +- Ensure OTEL service name matches in application config + +### 2. Create Required Secrets + +```bash +# Database credentials +kubectl create secret generic my-app-db-secret \ + --from-literal=db.username=YOUR_USER \ + --from-literal=db.password=YOUR_PASSWORD \ + --from-literal=db.service=myatp_high \ + -n your-namespace + +# ADB wallet (download from OCI Console first) +unzip Wallet_MyATP.zip -d /tmp/wallet/ +kubectl create secret generic my-app-adb-wallet \ + --from-file=/tmp/wallet/ \ + -n your-namespace + +# Image pull secret (for OCI Registry) +kubectl create secret docker-registry ocir \ + --docker-server=us-phoenix-1.ocir.io \ + --docker-username='tenancy/username' \ + --docker-password='auth-token' \ + -n your-namespace +``` + +### 3. Configure values.yaml + +Create a custom values file for your application: + +**values-customer.yaml** (Helidon example): +```yaml +image: + repository: "us-ashburn-1.ocir.io/mytenancy/customer-helidon" + tag: "1.0.0" + +imagePullSecrets: + - name: ocir + +fullnameOverride: "customer" # Simplified deployment name + +obaas: + namespace: obaas-dev # Your OBaaS installation namespace + framework: HELIDON + + database: + credentialsSecret: customer-db-secret + walletSecret: dev-adb-wallet + + helidon: + enabled: true + datasource: + name: "customer" # Must match your application.yaml + otel: + serviceName: "customer" # Must match microprofile-config.properties + + eureka: + enabled: true + + otel: + enabled: true +``` + +### 4. Deploy + +```bash +helm install customer ./obaas-sample-app \ + -f values-customer.yaml \ + -n your-namespace \ + --create-namespace +``` + +### 5. Verify Deployment + +```bash +# Check pod status +kubectl get pods -n your-namespace + +# Check logs +kubectl logs -f deployment/customer -n your-namespace + +# Test health endpoint (port-forward first) +kubectl port-forward deployment/customer 8080:8080 -n your-namespace +curl http://localhost:8080/health/live # Helidon +# or +curl http://localhost:8080/actuator/health/liveness # Spring Boot +``` + +## Configuration Guide + +### Spring Boot Deployment + +#### Required Configuration + +```yaml +obaas: + namespace: obaas-cdd # Your OBaaS namespace + framework: SPRING_BOOT # Framework selection + + database: + credentialsSecret: app-db-secret + walletSecret: app-adb-wallet + + springboot: + enabled: true # Enable Spring Boot features + + eureka: + enabled: true # Service discovery + + otel: + enabled: true # Observability +``` + +#### What Gets Configured Automatically + +**Environment Variables:** +```yaml +SPRING_DATASOURCE_URL: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" +SPRING_DATASOURCE_USERNAME: +SPRING_DATASOURCE_PASSWORD: +SPRING_PROFILES_ACTIVE: +SPRING_CONFIG_LABEL: +EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE: +EUREKA_INSTANCE_HOSTNAME: "-" +OTEL_EXPORTER_OTLP_ENDPOINT: +``` + +**Health Probes:** +```yaml +livenessProbe: + httpGet: + path: /actuator/health/liveness + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + +readinessProbe: + httpGet: + path: /actuator/health/readiness + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 +``` + +**Metrics Scraping:** +```yaml +podAnnotations: + signoz.io/path: "/actuator/prometheus" + signoz.io/port: "8080" + signoz.io/scrape: "true" +``` + +#### Application Requirements + +**pom.xml dependencies:** +```xml + + + org.springframework.boot + spring-boot-starter-actuator + + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + + io.micrometer + micrometer-registry-prometheus + +``` + +**application.properties:** +```properties +# Health endpoints +management.endpoints.web.exposure.include=health,prometheus,info,metrics +management.endpoint.health.probes.enabled=true +management.health.livenessState.enabled=true +management.health.readinessState.enabled=true + +# Database (will be overridden by environment variables) +spring.datasource.driver-class-name=oracle.jdbc.OracleDriver + +# Eureka (will be overridden by environment variables) +eureka.client.enabled=true +``` + +### Helidon Deployment + +#### Required Configuration + +```yaml +obaas: + namespace: obaas-cdd # Your OBaaS namespace + framework: HELIDON # Framework selection + + database: + credentialsSecret: app-db-secret + walletSecret: app-adb-wallet + + helidon: + enabled: true # Enable Helidon features + + datasource: + name: "customer" # CRITICAL: Must match application config + + hibernate: + hbm2ddl_auto: create # create, update, validate, none + show_sql: true # Set false in production + format_sql: true + + server: + host: "0.0.0.0" + + metrics: + rest_request_enabled: false # Enable REST request metrics + + otel: + serviceName: "customer" # CRITICAL: Must match microprofile-config.properties + + app: + # Add custom properties here + greeting: "Hello" + + eureka: + enabled: true # Service discovery + + otel: + enabled: true # Observability +``` + +#### What Gets Configured Automatically + +**Environment Variables:** +```yaml +# Database configuration (note the datasource name substitution) +javax.sql.DataSource.customer.connectionFactoryClassName: "oracle.jdbc.pool.OracleDataSource" +javax.sql.DataSource.customer.URL: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" +javax.sql.DataSource.customer.user: +javax.sql.DataSource.customer.password: + +# Hibernate settings +hibernate.hbm2ddl.auto: "create" +hibernate.show_sql: "true" +hibernate.format_sql: "true" + +# Server configuration +server.port: "8080" +server.host: "0.0.0.0" + +# Metrics +metrics.rest-request.enabled: "false" + +# Eureka +eureka.client.service-url.defaultZone: "http://eureka-0.eureka.obaas-cdd.svc.cluster.local:8761/eureka" +eureka.instance.hostname: "-" +eureka.instance.preferIpAddress: "true" + +# OpenTelemetry (CRITICAL for metrics export) +OTEL_EXPORTER_OTLP_ENDPOINT: +OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf" # Critical: Uses HTTP not gRPC +OTEL_SERVICE_NAME: "customer" +OTEL_SDK_DISABLED: "false" +OTEL_METRICS_EXPORTER: "otlp" +JAVA_TOOL_OPTIONS: "-Dotel.java.global-autoconfigure.enabled=true" +``` + +**Health Probes:** +```yaml +livenessProbe: + httpGet: + path: /health/live + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + +readinessProbe: + httpGet: + path: /health/ready + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 +``` + +**Metrics Scraping:** +```yaml +podAnnotations: + signoz.io/path: "/metrics" + signoz.io/port: "8080" + signoz.io/scrape: "true" +``` + +#### Application Requirements + +**pom.xml dependencies:** +```xml + + + io.helidon.microprofile.health + helidon-microprofile-health + + + + + io.helidon.integrations.cdi + helidon-integrations-cdi-hikaricp + + + + + io.helidon.integrations.cdi + helidon-integrations-cdi-jpa + + + org.hibernate.orm + hibernate-core + + + + + com.oracle.database.jdbc + ojdbc11 + + + + + io.helidon.microprofile.cdi + helidon-microprofile-cdi + + + + + io.helidon.microprofile.metrics + helidon-microprofile-metrics + + + + + io.helidon.tracing + helidon-tracing + +``` + +**microprofile-config.properties:** +```properties +# Datasource name (MUST match values.yaml) +javax.sql.DataSource.customer.connectionFactoryClassName=oracle.jdbc.pool.OracleDataSource + +# Server configuration +server.port=8080 +server.host=0.0.0.0 + +# Health checks +health.enabled=true + +# Metrics +metrics.enabled=true +metrics.rest-request.enabled=true + +# OpenTelemetry (MUST match values.yaml) +otel.sdk.disabled=false +otel.service.name=customer +otel.metrics.exporter=otlp +``` + +#### CRITICAL Configuration Matching + +**These values MUST match between values.yaml and your application:** + +1. **Datasource Name** + - `values.yaml`: `obaas.helidon.datasource.name: "customer"` + - `microprofile-config.properties`: `javax.sql.DataSource.customer.*` + +2. **OTEL Service Name** + - `values.yaml`: `obaas.helidon.otel.serviceName: "customer"` + - `microprofile-config.properties`: `otel.service.name=customer` + +**Mismatch Symptoms:** +- Datasource name mismatch → "DataSource not found" error at runtime +- OTEL service name mismatch → Metrics appear under wrong service in SigNoz + +## Framework Comparison + +### When to Use Each Framework + +**Use Spring Boot when:** +- You need a large ecosystem of libraries and integrations +- Team has Spring Boot expertise +- Building enterprise applications with complex business logic +- Need mature tooling and IDE support +- Want convention-over-configuration approach + +**Use Helidon when:** +- You need lightweight microservices with smaller memory footprint +- Performance and startup time are critical +- Want MicroProfile standard compliance +- Building cloud-native, containerized applications +- Prefer explicit configuration over auto-configuration + +### Resource Comparison + +| Metric | Spring Boot | Helidon | +|--------|-------------|---------| +| **Startup Time** | ~8-15 seconds | ~3-8 seconds | +| **Memory (Idle)** | ~350-500 MB | ~200-350 MB | +| **Memory (Load)** | ~600-1000 MB | ~400-700 MB | +| **JAR Size** | ~50-80 MB | ~30-50 MB | +| **CPU (Idle)** | 50-100m | 50-80m | +| **Native Image** | Partial support | Full GraalVM support | + +### Recommended Resources + +**Spring Boot:** +```yaml +resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 1000m + memory: 1Gi +``` + +**Helidon:** +```yaml +resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi +``` + +## Observability and Metrics + +### Overview + +This chart integrates with SigNoz for comprehensive observability: + +- **Metrics**: Exported via OpenTelemetry Protocol (OTLP) or Prometheus scraping +- **Traces**: Distributed tracing across microservices +- **Logs**: Centralized log collection and correlation + +### Metrics Architecture + +``` +┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐ +│ Your App │ │ SigNoz OTEL │ │ ClickHouse │ +│ │─OTLP───▶│ Collector │────────▶│ (Storage) │ +│ /metrics │ │ │ │ │ +│ endpoint │ │ Also scrapes │ │ │ +│ │◄─scrape─│ Prometheus │ │ │ +└─────────────────┘ │ metrics │ └─────────────┘ + └──────────────────┘ + │ + ▼ + ┌──────────────────┐ + │ SigNoz UI │ + │ (Visualization) │ + └──────────────────┘ +``` + +### How Metrics Are Collected + +**Spring Boot:** +1. Micrometer collects metrics internally +2. OTEL integration pushes via OTLP to SigNoz collector (port 4318) +3. SigNoz also scrapes `/actuator/prometheus` endpoint +4. Metrics appear under the service name (derived from Helm release name) + +**Helidon:** +1. MicroProfile Metrics collects metrics +2. OTEL SDK (auto-configured) pushes via OTLP to SigNoz collector (port 4318) +3. SigNoz also scrapes `/metrics` endpoint +4. Metrics appear under configured service name (`otel.serviceName`) + +**Key Difference**: Helidon requires explicit OTLP protocol configuration (`http/protobuf`) to avoid gRPC connection errors. + +### Querying Metrics in SigNoz + +#### Finding Your Service Metrics + +Metrics are tagged with Kubernetes metadata. Use these filters: + +**Filter by Pod Name:** +``` +Metric: requests_count_total +WHERE: k8s_pod_name CONTAINS "customer" +``` + +**Filter by Namespace:** +``` +Metric: memory_usedHeap_bytes +WHERE: k8s_namespace_name = "production" AND k8s_pod_name CONTAINS "customer" +``` + +**Common Filters:** +- `k8s_pod_name` - Pod name (includes release name) +- `k8s_namespace_name` - Kubernetes namespace +- `k8s_container_name` - Container name +- `service_name` - OTEL service name (Helidon) or "signoz-scraper" (for Prometheus metrics) + +#### Available Metrics + +**Helidon Metrics:** +- `requests_count_total` - Total HTTP requests +- `memory_usedHeap_bytes` - JVM heap memory usage +- `memory_committedHeap_bytes` - JVM committed memory +- `thread_count` - Current thread count +- `cpu_systemLoadAverage` - System load average +- `jvm_uptime_seconds` - Service uptime +- `gc_time_seconds_total` - Garbage collection time +- `gc_total` - GC count + +**Spring Boot Metrics:** +- `http_server_requests_seconds` - HTTP request duration +- `jvm_memory_used_bytes` - JVM memory usage +- `jvm_gc_pause_seconds` - GC pause time +- `process_cpu_usage` - CPU usage percentage +- `tomcat_threads_current` - Active thread count (if using Tomcat) + +#### Example Queries + +**Request Rate (requests per second):** +``` +Metric: requests_count_total +Aggregation: Rate +WHERE: k8s_pod_name CONTAINS "customer" +``` + +**Memory Usage Over Time:** +``` +Metric: memory_usedHeap_bytes +Aggregation: Avg +WHERE: k8s_namespace_name = "production" +GROUP BY: k8s_pod_name +``` + +**Service Uptime:** +``` +Metric: jvm_uptime_seconds +Aggregation: Last +WHERE: k8s_pod_name CONTAINS "customer" +``` + +### Enabling/Disabling Observability + +**Disable all observability:** +```yaml +obaas: + otel: + enabled: false +``` + +**Disable only OTLP push (keep Prometheus scraping):** +```yaml +obaas: + otel: + enabled: false + +podAnnotations: + signoz.io/scrape: "true" # Keep scraping enabled + signoz.io/port: "8080" + signoz.io/path: "/metrics" # or /actuator/prometheus +``` + +### Troubleshooting Metrics + +**Metrics not appearing in SigNoz:** + +1. **Check OTEL environment variables:** + ```bash + kubectl exec deploy/customer -n your-ns -- env | grep OTEL + ``` + Should show: `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf` + +2. **Check for export errors in logs:** + ```bash + kubectl logs deploy/customer -n your-ns | grep -i "failed to export" + ``` + If you see gRPC errors, the protocol is not set correctly. + +3. **Verify metrics endpoint is working:** + ```bash + kubectl port-forward deploy/customer 8080:8080 -n your-ns + curl http://localhost:8080/metrics # Helidon + curl http://localhost:8080/actuator/prometheus # Spring Boot + ``` + +4. **Check pod annotations:** + ```bash + kubectl get pod -l app.kubernetes.io/instance=customer -o jsonpath='{.items[0].metadata.annotations}' | jq + ``` + Should have `signoz.io/scrape: "true"` + +**Helidon-specific**: If seeing "AutoConfiguredOpenTelemetrySdk found but automatic configuration is disabled": +- Verify `JAVA_TOOL_OPTIONS=-Dotel.java.global-autoconfigure.enabled=true` is set +- This is automatically configured when `obaas.otel.enabled=true` + +## Secrets Management + +### Database Credentials Secret + +**Required Keys:** +- `db.username` - Database user +- `db.password` - Database password +- `db.service` - TNS service name from tnsnames.ora + +**Creation:** +```bash +kubectl create secret generic my-app-db-secret \ + --from-literal=db.username=CUSTOMER_USER \ + --from-literal=db.password='MySecurePassword123!' \ + --from-literal=db.service=myatp_high \ + -n your-namespace +``` + +**Verification:** +```bash +kubectl get secret my-app-db-secret -n your-namespace -o jsonpath='{.data}' | jq 'keys' +# Should show: ["db.password", "db.service", "db.username"] +``` + +### ADB Wallet Secret + +**Required Files** (from OCI Console download): +- `tnsnames.ora`, `sqlnet.ora`, `cwallet.sso`, `ewallet.p12`, `keystore.jks`, `truststore.jks` + +**Creation:** +```bash +# Download wallet ZIP from OCI Console +# Unzip to temporary directory +unzip Wallet_MyATP.zip -d /tmp/wallet/ + +# Create secret from all files +kubectl create secret generic my-app-adb-wallet \ + --from-file=/tmp/wallet/ \ + -n your-namespace + +# Clean up +rm -rf /tmp/wallet +``` + +**Verification:** +```bash +kubectl get secret my-app-adb-wallet -n your-namespace -o jsonpath='{.data}' | jq 'keys' +# Should show all wallet files +``` + +**How it's used:** +- Secret is mounted as volume at `/oracle/tnsadmin` in the container +- JDBC connection string includes `TNS_ADMIN=/oracle/tnsadmin` +- Oracle drivers automatically read wallet files from this location + +### Image Pull Secret (OCI Registry) + +**For OCI Registry (OCIR):** +```bash +kubectl create secret docker-registry ocir \ + --docker-server=us-phoenix-1.ocir.io \ + --docker-username='tenancy-namespace/oracleidentitycloudservice/user@example.com' \ + --docker-password='your-auth-token' \ + -n your-namespace +``` + +**Finding your values:** +1. **Region**: Your OCI region (e.g., `us-phoenix-1`, `us-ashburn-1`) +2. **Tenancy Namespace**: OCI Console → Administration → Tenancy Details → Object Storage Namespace +3. **Username**: Your OCI username (often starts with `oracleidentitycloudservice/`) +4. **Auth Token**: Generate at OCI Console → User Settings → Auth Tokens → Generate Token + +**Configure in values.yaml:** +```yaml +imagePullSecrets: + - name: ocir +``` + +## Troubleshooting + +### Common Issues + +#### 1. Pod in CrashLoopBackOff + +**Symptom:** Pod keeps restarting + +**Check logs:** +```bash +kubectl logs pod/customer-xxx -n your-namespace --previous +``` + +**Common causes:** + +**Database connection error:** +``` +ORA-01017: invalid username/password +TNS: could not resolve the connect identifier +``` +- Verify `db.username`, `db.password`, `db.service` in credentials secret +- Check wallet secret contains all required files +- Verify `db.service` matches an entry in `tnsnames.ora` + +**Datasource not found (Helidon):** +``` +javax.sql.DataSource.customer not found +``` +- Ensure `obaas.helidon.datasource.name` in values.yaml matches your `application.yaml` +- Check environment variables: `kubectl exec deploy/customer -- env | grep javax.sql.DataSource` + +**Framework mismatch:** +``` +attempt to set an empty or null database URL +``` +- Likely deploying Helidon app with `framework: SPRING_BOOT` (or vice versa) +- Verify framework setting matches your application + +#### 2. Health Probe Failures + +**Symptom:** Pod shows "Unhealthy" or restarts frequently + +**Test health endpoints:** +```bash +kubectl port-forward deploy/customer 8080:8080 -n your-namespace + +# Helidon +curl http://localhost:8080/health/live +curl http://localhost:8080/health/ready + +# Spring Boot +curl http://localhost:8080/actuator/health/liveness +curl http://localhost:8080/actuator/health/readiness +``` + +**Fixes:** + +**Slow startup:** +```yaml +livenessProbe: + initialDelaySeconds: 60 # Increase from default 30 +``` + +**Database dependency:** +```yaml +readinessProbe: + initialDelaySeconds: 20 # Give DB time to connect + failureThreshold: 5 # More tolerance +``` + +#### 3. Metrics Not Appearing + +**See detailed troubleshooting in [Observability and Metrics](#troubleshooting-metrics) section above.** + +Quick checklist: +- [ ] `obaas.otel.enabled: true` +- [ ] OTEL_EXPORTER_OTLP_PROTOCOL set to "http/protobuf" (Helidon) +- [ ] No "failed to export" errors in logs +- [ ] Pod has signoz.io annotations +- [ ] Metrics endpoint returns data +- [ ] For Helidon: service name matches in values.yaml and microprofile-config.properties + +#### 4. Eureka Registration Failing + +**Check Eureka environment variables:** +```bash +kubectl exec deploy/customer -n your-namespace -- env | grep -i eureka +``` + +**Verify OBaaS ConfigMap exists:** +```bash +kubectl get configmap obaas-config -n -o yaml | grep eureka +``` + +**Spring Boot Eureka logs:** +```bash +kubectl logs deploy/customer -n your-namespace | grep -i eureka +``` + +Should see: "DiscoveryClient registering service" and "Registered instance" + +#### 5. Image Pull Errors + +**Symptom:** `ImagePullBackOff` or `ErrImagePull` + +**Check events:** +```bash +kubectl describe pod customer-xxx -n your-namespace +``` + +**Common causes:** + +**Wrong image path/tag:** +```yaml +image: + repository: "us-phoenix-1.ocir.io/tenancy/customer" # Verify this exists + tag: "1.0.0" # Verify tag exists +``` + +**Missing or wrong image pull secret:** +```bash +# Verify secret exists +kubectl get secret ocir -n your-namespace + +# Test secret (should show JSON with auth) +kubectl get secret ocir -n your-namespace -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d +``` + +**Recreate if needed:** +```bash +kubectl delete secret ocir -n your-namespace +kubectl create secret docker-registry ocir \ + --docker-server=us-phoenix-1.ocir.io \ + --docker-username='tenancy/user' \ + --docker-password='token' \ + -n your-namespace +``` + +### Getting More Help + +**Gather diagnostic information:** +```bash +# Pod status and events +kubectl get pods -n your-namespace +kubectl describe pod customer-xxx -n your-namespace + +# Application logs +kubectl logs deploy/customer -n your-namespace --tail=100 + +# Environment variables +kubectl exec deploy/customer -n your-namespace -- env | sort + +# Helm release +helm list -n your-namespace +helm get values customer -n your-namespace +helm get manifest customer -n your-namespace + +# OBaaS platform health +kubectl get all -n +kubectl get configmap obaas-config -n -o yaml +kubectl get configmap obaas-observability-config -n -o yaml +``` + +## Examples + +### Example 1: Production Helidon Service + +**values-customer-prod.yaml:** +```yaml +replicaCount: 3 + +image: + repository: "us-phoenix-1.ocir.io/mytenancy/customer-helidon" + tag: "2.1.0" + pullPolicy: Always + +imagePullSecrets: + - name: ocir + +fullnameOverride: "customer" + +service: + type: ClusterIP + port: 8080 + +obaas: + namespace: obaas-prod + framework: HELIDON + + database: + credentialsSecret: customer-prod-db-secret + walletSecret: prod-adb-wallet + + helidon: + enabled: true + datasource: + name: "customer" + hibernate: + hbm2ddl_auto: validate # Never modify prod schema + show_sql: false + format_sql: false + otel: + serviceName: "customer" + + eureka: + enabled: true + + otel: + enabled: true + +resources: + requests: + cpu: 200m + memory: 384Mi + limits: + cpu: 1000m + memory: 768Mi + +autoscaling: + enabled: true + minReplicas: 3 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 + +livenessProbe: + httpGet: + path: /health/live + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + +readinessProbe: + httpGet: + path: /health/ready + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 3 +``` + +**Deploy:** +```bash +helm install customer ./obaas-sample-app \ + -f values-customer-prod.yaml \ + -n production \ + --create-namespace +``` + +### Example 2: Development Spring Boot Service + +**values-order-dev.yaml:** +```yaml +replicaCount: 1 + +image: + repository: "us-ashburn-1.ocir.io/mytenancy/order-service" + tag: "latest" + +imagePullSecrets: + - name: ocir + +fullnameOverride: "order" + +obaas: + namespace: obaas-dev + framework: SPRING_BOOT + + database: + credentialsSecret: order-dev-db-secret + walletSecret: dev-adb-wallet + + springboot: + enabled: true + + eureka: + enabled: true + + otel: + enabled: true + +resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 1Gi +``` + +**Deploy:** +```bash +helm install order ./obaas-sample-app \ + -f values-order-dev.yaml \ + -n development \ + --create-namespace +``` + +### Example 3: Helidon Service Without Eureka + +**values-inventory-standalone.yaml:** +```yaml +image: + repository: "us-phoenix-1.ocir.io/mytenancy/inventory" + tag: "1.5.0" + +fullnameOverride: "inventory" + +obaas: + namespace: obaas-dev + framework: HELIDON + + database: + credentialsSecret: inventory-db-secret + walletSecret: dev-adb-wallet + + helidon: + enabled: true + datasource: + name: "inventory" + hibernate: + hbm2ddl_auto: update + otel: + serviceName: "inventory" + + eureka: + enabled: false # Standalone service + + otel: + enabled: true # Still want observability +``` + +### Example 4: Multi-Environment with Overlays + +**values.yaml** (base): +```yaml +image: + repository: "us-phoenix-1.ocir.io/mytenancy/customer" + pullPolicy: Always + +imagePullSecrets: + - name: ocir + +fullnameOverride: "customer" + +obaas: + framework: HELIDON + helidon: + enabled: true + datasource: + name: "customer" + otel: + serviceName: "customer" + eureka: + enabled: true + otel: + enabled: true +``` + +**values-dev.yaml** (development overlay): +```yaml +image: + tag: "latest" + +replicaCount: 1 + +obaas: + namespace: obaas-dev + database: + credentialsSecret: customer-dev-db + walletSecret: dev-wallet + helidon: + hibernate: + hbm2ddl_auto: create + show_sql: true + +resources: + requests: + cpu: 50m + memory: 128Mi +``` + +**values-prod.yaml** (production overlay): +```yaml +image: + tag: "2.1.0" + +replicaCount: 3 + +obaas: + namespace: obaas-prod + database: + credentialsSecret: customer-prod-db + walletSecret: prod-wallet + helidon: + hibernate: + hbm2ddl_auto: validate + show_sql: false + +resources: + requests: + cpu: 200m + memory: 384Mi + limits: + cpu: 1000m + memory: 768Mi + +autoscaling: + enabled: true + minReplicas: 3 + maxReplicas: 20 +``` + +**Deploy to environments:** +```bash +# Development +helm install customer ./obaas-sample-app \ + -f values.yaml \ + -f values-dev.yaml \ + -n development + +# Production +helm install customer ./obaas-sample-app \ + -f values.yaml \ + -f values-prod.yaml \ + -n production +``` + +--- + +## Additional Resources + +- [Oracle Backend for Microservices and AI Documentation](https://docs.oracle.com/en/database/oracle/oracle-database/) +- [Helidon Documentation](https://helidon.io/docs/latest) +- [Spring Boot Documentation](https://spring.io/projects/spring-boot) +- [Helm Documentation](https://helm.sh/docs/) +- [SigNoz Documentation](https://signoz.io/docs/) + +## License + +Copyright (c) 2025 Oracle and/or its affiliates. + +Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/helm/charts/obaas-sample-app/templates/deployment.yaml b/helm/charts/obaas-sample-app/templates/deployment.yaml index d4902a2f2..6944e9541 100644 --- a/helm/charts/obaas-sample-app/templates/deployment.yaml +++ b/helm/charts/obaas-sample-app/templates/deployment.yaml @@ -3,10 +3,9 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "obaas-app.fullname" . }} - namespace: {{ .Values.obaas.namespace }} labels: {{- include "obaas-app.labels" . | nindent 4 }} - obaas.framework: SPRING_BOOT + obaas.framework: {{ .Values.obaas.framework | upper }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} @@ -16,10 +15,15 @@ spec: {{- include "obaas-app.selectorLabels" . | nindent 6 }} template: metadata: - {{- with .Values.podAnnotations }} annotations: + {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} + {{- if eq .Values.obaas.framework "SPRING_BOOT" }} + signoz.io/path: /actuator/prometheus + {{- else if eq .Values.obaas.framework "HELIDON" }} + signoz.io/path: /metrics + {{- end }} labels: {{- include "obaas-app.labels" . | nindent 8 }} {{- with .Values.podLabels }} @@ -36,7 +40,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} containers: - - name: {{ .Chart.Name }} + - name: ku{{ .Chart.Name }} {{- with .Values.securityContext }} securityContext: {{- toYaml . | nindent 12 }} @@ -45,21 +49,29 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} env: - name: CONNECT_STRING - value: jdbc:oracle:thin:@$(SPRING_DB_SERVICE)?TNS_ADMIN=/oracle/tnsadmin + value: jdbc:oracle:thin:@$(DB_SERVICE)?TNS_ADMIN=/oracle/tnsadmin + - name: DB_SERVICE + valueFrom: + secretKeyRef: + name: {{ $.Values.obaas.database.credentialsSecret }} + key: db.service # Lookup ObaaS configuration {{- $obaas := (lookup "v1" "ConfigMap" .Values.obaas.namespace "obaas-config") }} - {{- $obaasObs := (lookup "v1" "ConfigMap" .Values.obaas.namespace "obaas-observability-config") }} + {{- $observability := (lookup "v1" "ConfigMap" .Values.obaas.namespace "obaas-observability-config") }} {{- if $.Values.obaas.mp_lra.enabled }} - name: MP_LRA_COORDINATOR_URL - value: {{ $obaas.data.otmm | quote }} + value: {{ $obaas.data.MP_LRA_COORDINATOR_URL | quote }} + - name: MP_LRA_PARTICIPANT_URL + value: {{ $obaas.data.MP_LRA_PARTICIPANT_URL | quote }} {{- end }} + {{- if eq .Values.obaas.framework "SPRING_BOOT" }} {{- if $.Values.obaas.eureka.enabled }} - name: EUREKA_INSTANCE_PREFER_IP_ADDRESS - value: "true" + value: "true" - name: EUREKA_CLIENT_REGISTER_WITH_EUREKA - value: "true" + value: "true" - name: EUREKA_CLIENT_FETCH_REGISTRY - value: "true" + value: "true" - name: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE value: {{ $obaas.data.eureka | quote }} - name: EUREKA_INSTANCE_HOSTNAME @@ -67,14 +79,15 @@ spec: {{- end }} {{- if $.Values.obaas.otel.enabled }} - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: {{ (index $obaasObs.data "signoz-otel-collector") | quote }} + value: {{ index $observability.data "signoz-otel-collector" | quote }} {{- end }} {{- if $.Values.obaas.springboot.enabled }} - name: SPRING_PROFILES_ACTIVE value: {{ $obaas.data.SPRING_PROFILES_ACTIVE | quote }} - {{- if $.Values.obaas.database.enabled }} + - name: SPRING_CONFIG_LABEL + value: {{ $obaas.data.SPRING_CONFIG_LABEL | quote }} - name: SPRING_DATASOURCE_URL - value: "jdbc:oracle:thin:@${SPRING_DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" + value: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" - name: SPRING_DATASOURCE_USERNAME valueFrom: secretKeyRef: @@ -85,6 +98,11 @@ spec: secretKeyRef: name: {{ $.Values.obaas.database.credentialsSecret }} key: db.password + # Liquibase configuration (uses separate admin credentials for migrations) + - name: LIQUIBASE_ENABLED + value: "true" + - name: LIQUIBASE_DATASOURCE_URL + value: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" - name: LIQUIBASE_DATASOURCE_USERNAME valueFrom: secretKeyRef: @@ -95,26 +113,97 @@ spec: secretKeyRef: name: {{ $.Values.obaas.database.credentialsSecret }} key: db.lb_password - - name: LIQUIBASE_DATASOURCE_URL - value: "jdbc:oracle:thin:@${SPRING_DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" - - name: SPRING_DB_SERVICE + {{- end }} + {{- else if eq .Values.obaas.framework "HELIDON" }} + {{- if $.Values.obaas.otel.enabled }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ index $observability.data "signoz-otel-collector" | quote }} + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: "http/protobuf" + - name: OTEL_SERVICE_NAME + value: {{ $.Values.obaas.helidon.otel.serviceName | quote }} + - name: OTEL_SDK_DISABLED + value: "false" + - name: OTEL_METRICS_EXPORTER + value: "otlp" + - name: JAVA_TOOL_OPTIONS + value: "-Dotel.java.global-autoconfigure.enabled=true" + {{- end }} + {{- if $.Values.obaas.eureka.enabled }} + - name: eureka.client.service-url.defaultZone + value: "http://eureka-0.eureka.{{ .Values.obaas.namespace }}.svc.cluster.local:8761/eureka" + - name: eureka.instance.hostname + value: {{ include "obaas-app.fullname" . }}-{{ $.Release.Namespace }} + - name: eureka.instance.preferIpAddress + value: "true" + {{- end }} + - name: javax.sql.DataSource.{{ $.Values.obaas.helidon.datasource.name }}.connectionFactoryClassName + value: oracle.jdbc.pool.OracleDataSource + - name: javax.sql.DataSource.{{ $.Values.obaas.helidon.datasource.name }}.URL + value: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" + - name: javax.sql.DataSource.{{ $.Values.obaas.helidon.datasource.name }}.user valueFrom: secretKeyRef: name: {{ $.Values.obaas.database.credentialsSecret }} - key: db.service - {{- end }} + key: db.username + - name: javax.sql.DataSource.{{ $.Values.obaas.helidon.datasource.name }}.password + valueFrom: + secretKeyRef: + name: {{ $.Values.obaas.database.credentialsSecret }} + key: db.password + - name: hibernate.hbm2ddl.auto + value: {{ $.Values.obaas.helidon.hibernate.hbm2ddl_auto | quote }} + - name: hibernate.show_sql + value: {{ $.Values.obaas.helidon.hibernate.show_sql | quote }} + - name: hibernate.format_sql + value: {{ $.Values.obaas.helidon.hibernate.format_sql | quote }} + - name: server.port + value: "{{ $.Values.service.port }}" + - name: server.host + value: {{ $.Values.obaas.helidon.server.host | quote }} + - name: metrics.rest-request.enabled + value: {{ $.Values.obaas.helidon.metrics.rest_request_enabled | quote }} + # Example: Add your application-specific properties here + # - name: app.greeting + # value: {{ $.Values.obaas.helidon.app.greeting | quote }} {{- end }} ports: - name: http containerPort: {{ .Values.service.port }} protocol: TCP - {{- with .Values.livenessProbe }} + {{- if .Values.livenessProbe }} livenessProbe: - {{- toYaml . | nindent 12 }} + {{- toYaml .Values.livenessProbe | nindent 12 }} + {{- else }} + livenessProbe: + httpGet: + {{- if eq .Values.obaas.framework "HELIDON" }} + path: /health/live + {{- else }} + path: /actuator/health/liveness + {{- end }} + port: {{ .Values.service.port }} + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 {{- end }} - {{- with .Values.readinessProbe }} + {{- if .Values.readinessProbe }} readinessProbe: - {{- toYaml . | nindent 12 }} + {{- toYaml .Values.readinessProbe | nindent 12 }} + {{- else }} + readinessProbe: + httpGet: + {{- if eq .Values.obaas.framework "HELIDON" }} + path: /health/ready + {{- else }} + path: /actuator/health/readiness + {{- end }} + port: {{ .Values.service.port }} + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 {{- end }} {{- with .Values.resources }} resources: diff --git a/helm/charts/obaas-sample-app/values.yaml b/helm/charts/obaas-sample-app/values.yaml index f15debd8b..2dcc53da6 100644 --- a/helm/charts/obaas-sample-app/values.yaml +++ b/helm/charts/obaas-sample-app/values.yaml @@ -7,14 +7,20 @@ replicaCount: 1 # This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ image: - repository: "" + # TODO: Set your container image repository (e.g., us-phoenix-1.ocir.io/mytenancy/my-app) + repository: "REPLACE_WITH_YOUR_IMAGE_REPOSITORY" # This sets the pull policy for images. pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. - tag: "" + # TODO: Set your image tag/version + tag: "REPLACE_WITH_YOUR_IMAGE_TAG" # This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +# TODO: Configure image pull secrets if using a private registry (uncomment and set secret name) imagePullSecrets: [] +# - name: ocir # For OCI Registry +# - name: dockerhub # For Docker Hub +# - name: ghcr # For GitHub Container Registry # This is to override the chart name. nameOverride: "" fullnameOverride: "" @@ -33,8 +39,8 @@ serviceAccount: # This is for setting Kubernetes Annotations to a Pod. # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -podAnnotations: - signoz.io/path: /actuator/prometheus +# Note: metrics path will be set automatically based on framework type +podAnnotations: signoz.io/port: "8080" signoz.io/scrape: "true" # This is for setting Kubernetes Labels to a Pod. @@ -76,37 +82,41 @@ ingress: # hosts: # - chart-example.local -resources: +resources: requests: cpu: 100m - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # Framework-specific resource recommendations: + # Spring Boot: lighter resource usage, minimal requirements + # Helidon: more explicit resource management recommended # limits: - # cpu: 100m - # memory: 128Mi + # cpu: 500m + # memory: 512Mi # requests: # cpu: 100m - # memory: 128Mi - -# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ -livenessProbe: - httpGet: - path: /actuator/health/liveness - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 2 - failureThreshold: 3 -readinessProbe: - httpGet: - path: /actuator/health/readiness - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 2 - failureThreshold: 3 + # memory: 256Mi + +# Health probes - automatically configured based on framework type +# Leave empty to use framework defaults, or override with custom configuration +livenessProbe: {} +readinessProbe: {} + +# Example custom probe configuration (uncomment to override defaults): +# livenessProbe: +# httpGet: +# path: /custom/health/live +# port: 8080 +# initialDelaySeconds: 30 +# periodSeconds: 10 +# timeoutSeconds: 2 +# failureThreshold: 3 +# readinessProbe: +# httpGet: +# path: /custom/health/ready +# port: 8080 +# initialDelaySeconds: 10 +# periodSeconds: 10 +# timeoutSeconds: 2 +# failureThreshold: 3 # This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ @@ -136,20 +146,52 @@ tolerations: [] affinity: {} -# Oracle Backend for Microservices and AI Settings. obaas: - namespace: application # Replace with your namespace + # TODO: Set to your OBaaS installation namespace + namespace: REPLACE_WITH_OBAAS_NAMESPACE # e.g., obaas-cdd, obaas-prod, etc. + + # Framework selection: SPRING_BOOT or HELIDON + # TODO: Choose your framework (SPRING_BOOT or HELIDON) + framework: REPLACE_WITH_FRAMEWORK # Options: SPRING_BOOT or HELIDON + database: - enabled: true # If true variables with DB secret content will be created - credentialsSecret: obaas-app-db-secrets # Replace with your secret name - walletSecret: obaas-adb-tns-admin-1 # Replace with your wallet secret name + # TODO: Set the name of your database credentials secret + credentialsSecret: REPLACE_WITH_DB_CREDENTIALS_SECRET # e.g., my-app-db-secrets + # TODO: Set the name of your ADB wallet secret + walletSecret: REPLACE_WITH_DB_WALLET_SECRET # e.g., my-app-adb-wallet + otel: - enabled: true # Enable OpenTelemetry - # MicroProfile LRA + enabled: true # Enable OpenTelemetry tracing and metrics + + # MicroProfile LRA (Long Running Actions) mp_lra: - enabled: false # Enable OTMM - # Spring Boot applications + enabled: false + + # Spring Boot applications (only applies when framework=SPRING_BOOT) springboot: - enabled: true # Enable Spring Boot specific variables + enabled: false # Set to true when using SPRING_BOOT framework + + # Helidon applications (only applies when framework=HELIDON) + helidon: + enabled: false # Set to true when using HELIDON framework + # Helidon-specific configurations + datasource: + # TODO: CRITICAL - Must match the datasource name in your Helidon application.yaml + name: "REPLACE_WITH_DATASOURCE_NAME" # e.g., "customer", "order", "inventory" + hibernate: + hbm2ddl_auto: create # Options: create, update, validate, none + show_sql: true # Set to false in production + format_sql: true + server: + host: "0.0.0.0" + metrics: + rest_request_enabled: false + # Application-specific properties (customize for your app) + app: + greeting: "Hello" # Example property - replace with your own + eureka: - enabled: true # Enable Eureka client + enabled: true # Enable Eureka service discovery + + configServer: + enabled: false # Enable Spring Cloud Config integration \ No newline at end of file From d7f72dd5b2985758ca3e02995e89f1d7d4c209ff Mon Sep 17 00:00:00 2001 From: Doug Drechsel Date: Tue, 14 Oct 2025 12:10:50 -0400 Subject: [PATCH 2/2] Fixes identified by reviewers --- helm/charts/obaas-sample-app/README.md | 1220 +++-------------- .../templates/deployment.yaml | 44 +- helm/charts/obaas-sample-app/values.yaml | 5 +- 3 files changed, 191 insertions(+), 1078 deletions(-) diff --git a/helm/charts/obaas-sample-app/README.md b/helm/charts/obaas-sample-app/README.md index b3e00ccbd..d925b1c6f 100644 --- a/helm/charts/obaas-sample-app/README.md +++ b/helm/charts/obaas-sample-app/README.md @@ -1,170 +1,48 @@ # OBaaS Sample Application Helm Chart -This Helm chart provides a **framework-agnostic** deployment template for microservices applications on the Oracle Backend for Microservices and AI (OBaaS) platform. It supports both **Spring Boot** and **Helidon** frameworks with automatic configuration of database integration, service discovery, and observability. +Deploying microservices to Kubernetes typically means maintaining separate Helm charts for Spring Boot and Helidon applications, or worse—writing framework-specific conditional logic throughout your application code. This chart takes a different approach: **one chart, one parameter, automatic configuration**. -## Table of Contents +Whether you're building with Spring Boot or Helidon, this chart automatically wires up database connections, service discovery, health checks, and observability—all based on a single `framework` parameter in your values file. -- [Overview](#overview) -- [Architecture](#architecture) -- [Prerequisites](#prerequisites) -- [Quick Start](#quick-start) -- [Configuration Guide](#configuration-guide) - - [Spring Boot Deployment](#spring-boot-deployment) - - [Helidon Deployment](#helidon-deployment) -- [Framework Comparison](#framework-comparison) -- [Observability and Metrics](#observability-and-metrics) -- [Secrets Management](#secrets-management) -- [Troubleshooting](#troubleshooting) -- [Examples](#examples) +## How It Works -## Overview +The chart uses Helm's templating engine to detect your framework choice and inject the appropriate environment variables, probe configurations, and metrics endpoints. When you deploy a Helidon application, you get `/health/live` probes and MicroProfile-style datasource configuration. Choose Spring Boot instead, and you automatically get `/actuator/health/liveness` endpoints and Spring-style environment variables. -This Helm chart automatically configures framework-specific settings based on a single `framework` parameter. It eliminates the need for separate charts or complex conditional logic in your application code. +Behind the scenes, the deployment template queries your OBaaS platform's ConfigMaps to retrieve Eureka URLs, SigNoz collector endpoints, and other platform-wide settings. This means you never hardcode connection strings or service endpoints—everything adapts to your environment automatically. -### Key Features +Your application pods start with their Oracle Autonomous Database wallet already mounted at `/oracle/tnsadmin`, database credentials injected from Kubernetes secrets, and OpenTelemetry configured to push metrics to SigNoz. Service discovery happens automatically if you enable Eureka, and health probes use the correct endpoints for your framework. -- **Single Framework Parameter**: Set `framework: SPRING_BOOT` or `framework: HELIDON` to automatically configure all framework-specific settings -- **Automatic Health Checks**: Framework-appropriate liveness and readiness probe endpoints -- **Built-in Observability**: OpenTelemetry integration with SigNoz for metrics, traces, and logs -- **Oracle Database Integration**: Autonomous Database (ADB) wallet mounting and connection configuration -- **Service Discovery**: Optional Eureka registration for microservices communication -- **Production Ready**: Includes resource management, autoscaling, and health probe configurations +## What You Get -### What Gets Auto-Configured +This chart eliminates configuration boilerplate by automatically setting up: -| Feature | Spring Boot | Helidon | -|---------|-------------|---------| -| **Health Endpoints** | `/actuator/health/liveness`
`/actuator/health/readiness` | `/health/live`
`/health/ready` | -| **Metrics Endpoint** | `/actuator/prometheus` | `/metrics` | -| **Database Config** | `SPRING_DATASOURCE_*` env vars | `javax.sql.DataSource.*` env vars | -| **Eureka Integration** | Spring Cloud Netflix | Helidon Eureka client | -| **OTEL Protocol** | HTTP/protobuf (port 4318) | HTTP/protobuf (port 4318) + auto-configure | -| **Service Name** | Auto from release name | Configurable via `otel.serviceName` | +- **Framework-appropriate health checks**: The right probe paths for Spring Boot (`/actuator/health/*`) or Helidon (`/health/*`) +- **Database integration**: Wallet mounting, connection string injection, and framework-specific datasource configuration +- **Service discovery**: Eureka registration with hostname and zone settings pulled from your OBaaS platform +- **Observability**: OpenTelemetry integration pushing metrics, traces, and logs to SigNoz, plus Prometheus scraping annotations +- **Production readiness**: Resource limits, horizontal pod autoscaling, and configurable probe timings -## Architecture +The deployment template includes over 150 lines of framework-specific environment variable configuration, all selected automatically based on your choice. Spring Boot applications receive `SPRING_DATASOURCE_*` variables and Spring Cloud Config integration. Helidon applications get MicroProfile Config-style `javax.sql.DataSource.*` properties and explicit OTLP protocol settings to work around Helidon's OpenTelemetry quirks. -### Deployment Architecture +## Before You Begin -``` -┌─────────────────────────────────────────────────────────────┐ -│ Kubernetes Cluster │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ ┌───────────────┐ ┌──────────────────────┐ │ -│ │ Your App Pod │ │ OBaaS Platform │ │ -│ ├───────────────┤ ├──────────────────────┤ │ -│ │ │ │ │ │ -│ │ Spring Boot │◄────────┤ Eureka (Discovery) │ │ -│ │ or │ │ │ │ -│ │ Helidon MP │◄────────┤ SigNoz (Observ.) │ │ -│ │ │ │ │ │ -│ │ ┌─────────┐ │ │ APISIX (Gateway) │ │ -│ │ │ Wallet │ │ │ │ │ -│ │ │ Mount │ │ │ Config Server │ │ -│ │ └─────────┘ │ │ │ │ -│ └───────┬───────┘ └──────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌───────────────┐ │ -│ │ Oracle ADB │ │ -│ │ (Autonomous) │ │ -│ └───────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` +Your Kubernetes cluster needs an OBaaS installation before this chart can render templates. The chart uses Helm's `lookup` function to retrieve platform configuration from ConfigMaps, which means you can't fully render templates without a live cluster connection. Verify your platform is ready: -### Template Structure - -``` -obaas-sample-app/ -├── Chart.yaml # Chart metadata -├── values.yaml # Default configuration (with TODOs) -├── templates/ -│ ├── deployment.yaml # Main deployment with framework conditionals -│ ├── service.yaml # Kubernetes service -│ ├── serviceaccount.yaml # Service account (optional) -│ ├── ingress.yaml # Ingress (optional) -│ ├── hpa.yaml # Horizontal Pod Autoscaler (optional) -│ └── _helpers.tpl # Template helpers -└── README.md # This file +```bash +kubectl get configmap obaas-config -n +kubectl get configmap obaas-observability-config -n ``` -**Key Design Point**: The `deployment.yaml` template uses Helm conditionals (`{{- if eq .Values.obaas.framework "HELIDON" }}`) to render framework-specific environment variables, eliminating the need for multiple deployment templates. - -## Prerequisites - -### Required Infrastructure - -1. **OBaaS Platform**: Installed in your Kubernetes cluster - ```bash - # Verify OBaaS installation - kubectl get configmap obaas-config -n - kubectl get configmap obaas-observability-config -n - ``` - -2. **Kubernetes Cluster**: CNCF-compliant (v1.33.1+) - ```bash - kubectl version --short - ``` - -3. **Helm**: Version 3.8+ - ```bash - helm version - ``` - -### Required Secrets - -You'll need to create these secrets before deploying: - -1. **Database Credentials Secret** - Contains Oracle DB connection info -2. **ADB Wallet Secret** - Contains Autonomous Database wallet files -3. **Image Pull Secret** - For pulling from private container registries (optional) - -See [Secrets Management](#secrets-management) section for creation commands. +You'll also need three secrets in your target namespace: database credentials (username, password, and service name), an Autonomous Database wallet (the ZIP file from OCI Console, unzipped), and optionally an image pull secret for private registries. -## Quick Start +For database credentials, create a generic secret with keys `db.username`, `db.password`, and `db.service` (the TNS service name from your wallet's `tnsnames.ora`). Spring Boot applications using Liquibase for schema migrations need two additional keys: `db.lb_username` and `db.lb_password` for the admin user. -### 1. Prepare Your Application - -**For Spring Boot:** -- Add Spring Boot Actuator for health checks -- Add Spring Cloud Eureka Client for service discovery (optional) -- Add OpenTelemetry instrumentation for observability - -**For Helidon:** -- Add Helidon Health for health checks -- Configure datasource name in `microprofile-config.properties` -- Add Helidon Eureka integration for service discovery (optional) -- Ensure OTEL service name matches in application config - -### 2. Create Required Secrets - -```bash -# Database credentials -kubectl create secret generic my-app-db-secret \ - --from-literal=db.username=YOUR_USER \ - --from-literal=db.password=YOUR_PASSWORD \ - --from-literal=db.service=myatp_high \ - -n your-namespace - -# ADB wallet (download from OCI Console first) -unzip Wallet_MyATP.zip -d /tmp/wallet/ -kubectl create secret generic my-app-adb-wallet \ - --from-file=/tmp/wallet/ \ - -n your-namespace - -# Image pull secret (for OCI Registry) -kubectl create secret docker-registry ocir \ - --docker-server=us-phoenix-1.ocir.io \ - --docker-username='tenancy/username' \ - --docker-password='auth-token' \ - -n your-namespace -``` +The wallet secret should contain all files from your ADB wallet ZIP—`tnsnames.ora`, `sqlnet.ora`, `cwallet.sso`, and the various keystore files. The chart mounts this secret as a volume at `/oracle/tnsadmin`, and the JDBC connection string references this path automatically. -### 3. Configure values.yaml +## Getting Started -Create a custom values file for your application: +Start by creating a custom values file for your application. The chart's default `values.yaml` contains placeholders with `TODO` comments marking required changes. Copy it and fill in your specifics: -**values-customer.yaml** (Helidon example): ```yaml image: repository: "us-ashburn-1.ocir.io/mytenancy/customer-helidon" @@ -173,11 +51,11 @@ image: imagePullSecrets: - name: ocir -fullnameOverride: "customer" # Simplified deployment name +fullnameOverride: "customer" obaas: - namespace: obaas-dev # Your OBaaS installation namespace - framework: HELIDON + namespace: obaas-dev + framework: HELIDON # or SPRING_BOOT database: credentialsSecret: customer-db-secret @@ -186,9 +64,9 @@ obaas: helidon: enabled: true datasource: - name: "customer" # Must match your application.yaml + name: "customer" otel: - serviceName: "customer" # Must match microprofile-config.properties + serviceName: "customer" eureka: enabled: true @@ -197,7 +75,11 @@ obaas: enabled: true ``` -### 4. Deploy +Notice the `obaas.helidon.datasource.name` and `obaas.helidon.otel.serviceName` settings. These are **critical** for Helidon deployments—the datasource name must match your application's `microprofile-config.properties`, and the OTEL service name must match your `otel.service.name` property. Mismatches cause runtime "DataSource not found" errors or metrics appearing under the wrong service in SigNoz. + +Spring Boot deployments are simpler because Spring's convention-over-configuration approach means fewer explicit mappings. Just set `framework: SPRING_BOOT`, enable `obaas.springboot.enabled: true`, and the chart handles the rest. + +Deploy with Helm: ```bash helm install customer ./obaas-sample-app \ @@ -206,595 +88,175 @@ helm install customer ./obaas-sample-app \ --create-namespace ``` -### 5. Verify Deployment +Check that your pod starts successfully: ```bash -# Check pod status kubectl get pods -n your-namespace - -# Check logs kubectl logs -f deployment/customer -n your-namespace - -# Test health endpoint (port-forward first) -kubectl port-forward deployment/customer 8080:8080 -n your-namespace -curl http://localhost:8080/health/live # Helidon -# or -curl http://localhost:8080/actuator/health/liveness # Spring Boot ``` -## Configuration Guide - -### Spring Boot Deployment - -#### Required Configuration +If you see connection errors, verify your secrets exist and contain the correct keys. Database authentication failures usually mean typos in `db.username` or `db.password`. TNS resolution errors mean `db.service` doesn't match an entry in your wallet's `tnsnames.ora`. -```yaml -obaas: - namespace: obaas-cdd # Your OBaaS namespace - framework: SPRING_BOOT # Framework selection +## Framework Differences That Matter - database: - credentialsSecret: app-db-secret - walletSecret: app-adb-wallet +Spring Boot and Helidon have different conventions for database configuration, health checks, and metrics. The chart handles these differences automatically, but understanding them helps when troubleshooting. - springboot: - enabled: true # Enable Spring Boot features +**Spring Boot** uses Spring Data JPA and Spring Boot Actuator. Database settings go in `SPRING_DATASOURCE_*` environment variables, and Spring automatically configures connection pooling. Health endpoints appear under `/actuator/health/`, and metrics use Micrometer with Prometheus export at `/actuator/prometheus`. Eureka integration happens through Spring Cloud Netflix, with service registration managed by Spring's `@EnableDiscoveryClient` annotation. - eureka: - enabled: true # Service discovery +**Helidon** follows the MicroProfile specification. Database configuration uses `javax.sql.DataSource..*` properties where the name maps to your application's datasource bean. Helidon doesn't auto-configure datasources like Spring does—you must explicitly match the datasource name between your `microprofile-config.properties` and your Helm values. Health endpoints are simpler paths: `/health/live` and `/health/ready`. Metrics follow MicroProfile Metrics at `/metrics`, and OpenTelemetry requires explicit protocol configuration (`http/protobuf` instead of gRPC) to work with SigNoz. - otel: - enabled: true # Observability -``` +Resource-wise, Helidon is lighter. A typical Helidon microservice idles around 200-350 MB of memory and starts in 3-8 seconds, compared to Spring Boot's 350-500 MB and 8-15 second startup. Production Helidon deployments can run comfortably with 100m CPU and 256 Mi memory requests, while Spring Boot typically needs 250m CPU and 512 Mi to avoid throttling under load. -#### What Gets Configured Automatically +## Observability and Debugging -**Environment Variables:** -```yaml -SPRING_DATASOURCE_URL: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" -SPRING_DATASOURCE_USERNAME: -SPRING_DATASOURCE_PASSWORD: -SPRING_PROFILES_ACTIVE: -SPRING_CONFIG_LABEL: -EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE: -EUREKA_INSTANCE_HOSTNAME: "-" -OTEL_EXPORTER_OTLP_ENDPOINT: -``` +Every pod deployed by this chart includes OpenTelemetry integration pushing metrics to your OBaaS platform's SigNoz installation. Metrics flow two ways: OTLP push (the pod actively sends metrics via HTTP) and Prometheus scraping (SigNoz pulls from your `/metrics` endpoint). The chart sets pod annotations (`signoz.io/scrape: "true"`) to enable scraping and injects OTEL environment variables for push. -**Health Probes:** -```yaml -livenessProbe: - httpGet: - path: /actuator/health/liveness - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 10 - -readinessProbe: - httpGet: - path: /actuator/health/readiness - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 10 -``` +Helidon has a quirk: it defaults to gRPC for OTLP, which doesn't work with many SigNoz installations. The chart works around this by explicitly setting `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf` and enabling Java's global OpenTelemetry auto-configuration via `JAVA_TOOL_OPTIONS`. Without these settings, you'll see "failed to export" errors in your logs and metrics won't appear in SigNoz. -**Metrics Scraping:** -```yaml -podAnnotations: - signoz.io/path: "/actuator/prometheus" - signoz.io/port: "8080" - signoz.io/scrape: "true" -``` +When metrics don't show up in SigNoz, the debugging process is straightforward. Port-forward to your pod and curl the metrics endpoint directly—if it returns data, the problem is with OTEL export or scraping configuration. If it returns a 404, your application isn't exposing metrics correctly. Check that Spring Boot Actuator is enabled or Helidon Metrics is in your dependencies. -#### Application Requirements - -**pom.xml dependencies:** -```xml - - - org.springframework.boot - spring-boot-starter-actuator - - - - - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client - - - - - io.micrometer - micrometer-registry-prometheus - -``` +Query SigNoz metrics using Kubernetes metadata filters. Metrics are tagged with `k8s_pod_name` (includes your Helm release name), `k8s_namespace_name`, and `service_name`. The service name comes from your OTEL configuration for Helidon applications, or defaults to "signoz-scraper" for Prometheus-scraped metrics from Spring Boot. -**application.properties:** -```properties -# Health endpoints -management.endpoints.web.exposure.include=health,prometheus,info,metrics -management.endpoint.health.probes.enabled=true -management.health.livenessState.enabled=true -management.health.readinessState.enabled=true +Health probe failures usually mean one of two things: slow startup or failed dependencies. Increase `livenessProbe.initialDelaySeconds` to 60 seconds if your application takes time to initialize. If your readiness probe fails immediately after startup, it's often because the database connection hasn't established—increase `readinessProbe.initialDelaySeconds` and `failureThreshold` to give the pod more time. -# Database (will be overridden by environment variables) -spring.datasource.driver-class-name=oracle.jdbc.OracleDriver +## Configuration Patterns -# Eureka (will be overridden by environment variables) -eureka.client.enabled=true -``` +Most teams deploy the same application to multiple environments with different settings. Use value overlays to keep environment-specific config separate from base settings: -### Helidon Deployment - -#### Required Configuration +Create a base `values.yaml` with common settings: ```yaml -obaas: - namespace: obaas-cdd # Your OBaaS namespace - framework: HELIDON # Framework selection - - database: - credentialsSecret: app-db-secret - walletSecret: app-adb-wallet +image: + repository: "us-phoenix-1.ocir.io/mytenancy/customer" + pullPolicy: Always +obaas: + framework: HELIDON helidon: - enabled: true # Enable Helidon features - + enabled: true datasource: - name: "customer" # CRITICAL: Must match application config - - hibernate: - hbm2ddl_auto: create # create, update, validate, none - show_sql: true # Set false in production - format_sql: true - - server: - host: "0.0.0.0" - - metrics: - rest_request_enabled: false # Enable REST request metrics - + name: "customer" otel: - serviceName: "customer" # CRITICAL: Must match microprofile-config.properties - - app: - # Add custom properties here - greeting: "Hello" - + serviceName: "customer" eureka: - enabled: true # Service discovery - + enabled: true otel: - enabled: true # Observability + enabled: true ``` -#### What Gets Configured Automatically +Then create environment overlays like `values-dev.yaml`: -**Environment Variables:** ```yaml -# Database configuration (note the datasource name substitution) -javax.sql.DataSource.customer.connectionFactoryClassName: "oracle.jdbc.pool.OracleDataSource" -javax.sql.DataSource.customer.URL: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" -javax.sql.DataSource.customer.user: -javax.sql.DataSource.customer.password: - -# Hibernate settings -hibernate.hbm2ddl.auto: "create" -hibernate.show_sql: "true" -hibernate.format_sql: "true" - -# Server configuration -server.port: "8080" -server.host: "0.0.0.0" - -# Metrics -metrics.rest-request.enabled: "false" - -# Eureka -eureka.client.service-url.defaultZone: "http://eureka-0.eureka.obaas-cdd.svc.cluster.local:8761/eureka" -eureka.instance.hostname: "-" -eureka.instance.preferIpAddress: "true" - -# OpenTelemetry (CRITICAL for metrics export) -OTEL_EXPORTER_OTLP_ENDPOINT: -OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf" # Critical: Uses HTTP not gRPC -OTEL_SERVICE_NAME: "customer" -OTEL_SDK_DISABLED: "false" -OTEL_METRICS_EXPORTER: "otlp" -JAVA_TOOL_OPTIONS: "-Dotel.java.global-autoconfigure.enabled=true" -``` - -**Health Probes:** -```yaml -livenessProbe: - httpGet: - path: /health/live - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 10 - -readinessProbe: - httpGet: - path: /health/ready - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 10 -``` - -**Metrics Scraping:** -```yaml -podAnnotations: - signoz.io/path: "/metrics" - signoz.io/port: "8080" - signoz.io/scrape: "true" -``` - -#### Application Requirements - -**pom.xml dependencies:** -```xml - - - io.helidon.microprofile.health - helidon-microprofile-health - - - - - io.helidon.integrations.cdi - helidon-integrations-cdi-hikaricp - - - - - io.helidon.integrations.cdi - helidon-integrations-cdi-jpa - - - org.hibernate.orm - hibernate-core - - - - - com.oracle.database.jdbc - ojdbc11 - - - - - io.helidon.microprofile.cdi - helidon-microprofile-cdi - - - - - io.helidon.microprofile.metrics - helidon-microprofile-metrics - - - - - io.helidon.tracing - helidon-tracing - -``` - -**microprofile-config.properties:** -```properties -# Datasource name (MUST match values.yaml) -javax.sql.DataSource.customer.connectionFactoryClassName=oracle.jdbc.pool.OracleDataSource - -# Server configuration -server.port=8080 -server.host=0.0.0.0 - -# Health checks -health.enabled=true +image: + tag: "latest" -# Metrics -metrics.enabled=true -metrics.rest-request.enabled=true +replicaCount: 1 -# OpenTelemetry (MUST match values.yaml) -otel.sdk.disabled=false -otel.service.name=customer -otel.metrics.exporter=otlp +obaas: + namespace: obaas-dev + database: + credentialsSecret: customer-dev-db + walletSecret: dev-wallet + helidon: + hibernate: + hbm2ddl_auto: create # Auto-create schema in dev + show_sql: true # Show SQL for debugging ``` -#### CRITICAL Configuration Matching - -**These values MUST match between values.yaml and your application:** - -1. **Datasource Name** - - `values.yaml`: `obaas.helidon.datasource.name: "customer"` - - `microprofile-config.properties`: `javax.sql.DataSource.customer.*` - -2. **OTEL Service Name** - - `values.yaml`: `obaas.helidon.otel.serviceName: "customer"` - - `microprofile-config.properties`: `otel.service.name=customer` - -**Mismatch Symptoms:** -- Datasource name mismatch → "DataSource not found" error at runtime -- OTEL service name mismatch → Metrics appear under wrong service in SigNoz +And `values-prod.yaml` with production settings: -## Framework Comparison - -### When to Use Each Framework - -**Use Spring Boot when:** -- You need a large ecosystem of libraries and integrations -- Team has Spring Boot expertise -- Building enterprise applications with complex business logic -- Need mature tooling and IDE support -- Want convention-over-configuration approach - -**Use Helidon when:** -- You need lightweight microservices with smaller memory footprint -- Performance and startup time are critical -- Want MicroProfile standard compliance -- Building cloud-native, containerized applications -- Prefer explicit configuration over auto-configuration - -### Resource Comparison +```yaml +image: + tag: "2.1.0" # Pinned version -| Metric | Spring Boot | Helidon | -|--------|-------------|---------| -| **Startup Time** | ~8-15 seconds | ~3-8 seconds | -| **Memory (Idle)** | ~350-500 MB | ~200-350 MB | -| **Memory (Load)** | ~600-1000 MB | ~400-700 MB | -| **JAR Size** | ~50-80 MB | ~30-50 MB | -| **CPU (Idle)** | 50-100m | 50-80m | -| **Native Image** | Partial support | Full GraalVM support | +replicaCount: 3 -### Recommended Resources +obaas: + namespace: obaas-prod + database: + credentialsSecret: customer-prod-db + walletSecret: prod-wallet + helidon: + hibernate: + hbm2ddl_auto: validate # Never modify prod schema + show_sql: false # No debug output -**Spring Boot:** -```yaml resources: requests: - cpu: 250m - memory: 512Mi + cpu: 200m + memory: 384Mi limits: cpu: 1000m - memory: 1Gi -``` - -**Helidon:** -```yaml -resources: - requests: - cpu: 100m - memory: 256Mi - limits: - cpu: 500m - memory: 512Mi -``` - -## Observability and Metrics - -### Overview - -This chart integrates with SigNoz for comprehensive observability: - -- **Metrics**: Exported via OpenTelemetry Protocol (OTLP) or Prometheus scraping -- **Traces**: Distributed tracing across microservices -- **Logs**: Centralized log collection and correlation - -### Metrics Architecture - -``` -┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐ -│ Your App │ │ SigNoz OTEL │ │ ClickHouse │ -│ │─OTLP───▶│ Collector │────────▶│ (Storage) │ -│ /metrics │ │ │ │ │ -│ endpoint │ │ Also scrapes │ │ │ -│ │◄─scrape─│ Prometheus │ │ │ -└─────────────────┘ │ metrics │ └─────────────┘ - └──────────────────┘ - │ - ▼ - ┌──────────────────┐ - │ SigNoz UI │ - │ (Visualization) │ - └──────────────────┘ -``` - -### How Metrics Are Collected - -**Spring Boot:** -1. Micrometer collects metrics internally -2. OTEL integration pushes via OTLP to SigNoz collector (port 4318) -3. SigNoz also scrapes `/actuator/prometheus` endpoint -4. Metrics appear under the service name (derived from Helm release name) - -**Helidon:** -1. MicroProfile Metrics collects metrics -2. OTEL SDK (auto-configured) pushes via OTLP to SigNoz collector (port 4318) -3. SigNoz also scrapes `/metrics` endpoint -4. Metrics appear under configured service name (`otel.serviceName`) - -**Key Difference**: Helidon requires explicit OTLP protocol configuration (`http/protobuf`) to avoid gRPC connection errors. - -### Querying Metrics in SigNoz - -#### Finding Your Service Metrics - -Metrics are tagged with Kubernetes metadata. Use these filters: - -**Filter by Pod Name:** -``` -Metric: requests_count_total -WHERE: k8s_pod_name CONTAINS "customer" -``` - -**Filter by Namespace:** -``` -Metric: memory_usedHeap_bytes -WHERE: k8s_namespace_name = "production" AND k8s_pod_name CONTAINS "customer" -``` - -**Common Filters:** -- `k8s_pod_name` - Pod name (includes release name) -- `k8s_namespace_name` - Kubernetes namespace -- `k8s_container_name` - Container name -- `service_name` - OTEL service name (Helidon) or "signoz-scraper" (for Prometheus metrics) - -#### Available Metrics - -**Helidon Metrics:** -- `requests_count_total` - Total HTTP requests -- `memory_usedHeap_bytes` - JVM heap memory usage -- `memory_committedHeap_bytes` - JVM committed memory -- `thread_count` - Current thread count -- `cpu_systemLoadAverage` - System load average -- `jvm_uptime_seconds` - Service uptime -- `gc_time_seconds_total` - Garbage collection time -- `gc_total` - GC count - -**Spring Boot Metrics:** -- `http_server_requests_seconds` - HTTP request duration -- `jvm_memory_used_bytes` - JVM memory usage -- `jvm_gc_pause_seconds` - GC pause time -- `process_cpu_usage` - CPU usage percentage -- `tomcat_threads_current` - Active thread count (if using Tomcat) - -#### Example Queries - -**Request Rate (requests per second):** -``` -Metric: requests_count_total -Aggregation: Rate -WHERE: k8s_pod_name CONTAINS "customer" -``` - -**Memory Usage Over Time:** -``` -Metric: memory_usedHeap_bytes -Aggregation: Avg -WHERE: k8s_namespace_name = "production" -GROUP BY: k8s_pod_name -``` + memory: 768Mi -**Service Uptime:** -``` -Metric: jvm_uptime_seconds -Aggregation: Last -WHERE: k8s_pod_name CONTAINS "customer" +autoscaling: + enabled: true + minReplicas: 3 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 ``` -### Enabling/Disabling Observability - -**Disable all observability:** -```yaml -obaas: - otel: - enabled: false -``` +Deploy by layering multiple value files: -**Disable only OTLP push (keep Prometheus scraping):** -```yaml -obaas: - otel: - enabled: false +```bash +# Development +helm install customer ./obaas-sample-app \ + -f values.yaml \ + -f values-dev.yaml \ + -n development -podAnnotations: - signoz.io/scrape: "true" # Keep scraping enabled - signoz.io/port: "8080" - signoz.io/path: "/metrics" # or /actuator/prometheus +# Production +helm install customer ./obaas-sample-app \ + -f values.yaml \ + -f values-prod.yaml \ + -n production ``` -### Troubleshooting Metrics - -**Metrics not appearing in SigNoz:** - -1. **Check OTEL environment variables:** - ```bash - kubectl exec deploy/customer -n your-ns -- env | grep OTEL - ``` - Should show: `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf` - -2. **Check for export errors in logs:** - ```bash - kubectl logs deploy/customer -n your-ns | grep -i "failed to export" - ``` - If you see gRPC errors, the protocol is not set correctly. - -3. **Verify metrics endpoint is working:** - ```bash - kubectl port-forward deploy/customer 8080:8080 -n your-ns - curl http://localhost:8080/metrics # Helidon - curl http://localhost:8080/actuator/prometheus # Spring Boot - ``` +Later values files override earlier ones, so environment-specific settings replace base defaults. -4. **Check pod annotations:** - ```bash - kubectl get pod -l app.kubernetes.io/instance=customer -o jsonpath='{.items[0].metadata.annotations}' | jq - ``` - Should have `signoz.io/scrape: "true"` +## Managing Secrets -**Helidon-specific**: If seeing "AutoConfiguredOpenTelemetrySdk found but automatic configuration is disabled": -- Verify `JAVA_TOOL_OPTIONS=-Dotel.java.global-autoconfigure.enabled=true` is set -- This is automatically configured when `obaas.otel.enabled=true` +Database credentials and wallet files are sensitive—never commit them to version control. Create secrets imperatively from local files or secure storage: -## Secrets Management - -### Database Credentials Secret - -**Required Keys:** -- `db.username` - Database user -- `db.password` - Database password -- `db.service` - TNS service name from tnsnames.ora - -**Creation:** ```bash -kubectl create secret generic my-app-db-secret \ +# Database credentials +kubectl create secret generic customer-db-secret \ --from-literal=db.username=CUSTOMER_USER \ - --from-literal=db.password='MySecurePassword123!' \ + --from-literal=db.password='SecurePassword123!' \ --from-literal=db.service=myatp_high \ -n your-namespace ``` -**Verification:** +For Spring Boot with Liquibase: + ```bash -kubectl get secret my-app-db-secret -n your-namespace -o jsonpath='{.data}' | jq 'keys' -# Should show: ["db.password", "db.service", "db.username"] +kubectl create secret generic customer-db-secret \ + --from-literal=db.username=CUSTOMER_USER \ + --from-literal=db.password='SecurePassword123!' \ + --from-literal=db.service=myatp_high \ + --from-literal=db.lb_username=ADMIN \ + --from-literal=db.lb_password='AdminPassword456!' \ + -n your-namespace ``` -### ADB Wallet Secret - -**Required Files** (from OCI Console download): -- `tnsnames.ora`, `sqlnet.ora`, `cwallet.sso`, `ewallet.p12`, `keystore.jks`, `truststore.jks` +ADB wallet secrets need all files from the wallet ZIP: -**Creation:** ```bash -# Download wallet ZIP from OCI Console -# Unzip to temporary directory unzip Wallet_MyATP.zip -d /tmp/wallet/ - -# Create secret from all files -kubectl create secret generic my-app-adb-wallet \ +kubectl create secret generic customer-adb-wallet \ --from-file=/tmp/wallet/ \ -n your-namespace - -# Clean up -rm -rf /tmp/wallet +rm -rf /tmp/wallet # Clean up ``` -**Verification:** +Verify secrets contain the expected keys: + ```bash -kubectl get secret my-app-adb-wallet -n your-namespace -o jsonpath='{.data}' | jq 'keys' -# Should show all wallet files +kubectl get secret customer-db-secret -n your-namespace -o jsonpath='{.data}' | jq 'keys' ``` -**How it's used:** -- Secret is mounted as volume at `/oracle/tnsadmin` in the container -- JDBC connection string includes `TNS_ADMIN=/oracle/tnsadmin` -- Oracle drivers automatically read wallet files from this location - -### Image Pull Secret (OCI Registry) +Image pull secrets for private registries follow Kubernetes' standard format: -**For OCI Registry (OCIR):** ```bash kubectl create secret docker-registry ocir \ --docker-server=us-phoenix-1.ocir.io \ @@ -803,61 +265,43 @@ kubectl create secret docker-registry ocir \ -n your-namespace ``` -**Finding your values:** -1. **Region**: Your OCI region (e.g., `us-phoenix-1`, `us-ashburn-1`) -2. **Tenancy Namespace**: OCI Console → Administration → Tenancy Details → Object Storage Namespace -3. **Username**: Your OCI username (often starts with `oracleidentitycloudservice/`) -4. **Auth Token**: Generate at OCI Console → User Settings → Auth Tokens → Generate Token +Reference the secret in your values file: -**Configure in values.yaml:** ```yaml imagePullSecrets: - name: ocir ``` -## Troubleshooting - -### Common Issues +## Common Problems -#### 1. Pod in CrashLoopBackOff +**Pods in CrashLoopBackOff** with database connection errors mean your credentials secret is missing, has wrong keys, or contains incorrect values. Check that `db.service` matches a service name in your `tnsnames.ora`. Oracle returns "TNS: could not resolve the connect identifier" when the service name doesn't exist in your wallet. -**Symptom:** Pod keeps restarting +**Helidon "DataSource not found" errors** happen when `obaas.helidon.datasource.name` in your values file doesn't match your application's datasource bean name. Check environment variables in the running pod: -**Check logs:** ```bash -kubectl logs pod/customer-xxx -n your-namespace --previous +kubectl exec deploy/customer -n your-namespace -- env | grep javax.sql.DataSource ``` -**Common causes:** +The datasource name appears in the middle of the variable names. It must match your `microprofile-config.properties` exactly. -**Database connection error:** -``` -ORA-01017: invalid username/password -TNS: could not resolve the connect identifier -``` -- Verify `db.username`, `db.password`, `db.service` in credentials secret -- Check wallet secret contains all required files -- Verify `db.service` matches an entry in `tnsnames.ora` +**Metrics not appearing in SigNoz** usually means OTEL configuration issues. For Helidon, verify the protocol is set correctly: -**Datasource not found (Helidon):** -``` -javax.sql.DataSource.customer not found +```bash +kubectl exec deploy/customer -n your-namespace -- env | grep OTEL ``` -- Ensure `obaas.helidon.datasource.name` in values.yaml matches your `application.yaml` -- Check environment variables: `kubectl exec deploy/customer -- env | grep javax.sql.DataSource` -**Framework mismatch:** -``` -attempt to set an empty or null database URL +You should see `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`. If it's missing or set to `grpc`, metrics won't export. Check your application logs for "failed to export" errors. + +**ImagePullBackOff errors** mean Kubernetes can't pull your container image. Verify the image path and tag are correct, and that your image pull secret exists and has valid credentials: + +```bash +kubectl get secret ocir -n your-namespace -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d ``` -- Likely deploying Helidon app with `framework: SPRING_BOOT` (or vice versa) -- Verify framework setting matches your application -#### 2. Health Probe Failures +The decoded JSON should contain your registry credentials. -**Symptom:** Pod shows "Unhealthy" or restarts frequently +**Health probe failures** show as pods that never become Ready or that restart frequently. Port-forward to the pod and manually test the health endpoints: -**Test health endpoints:** ```bash kubectl port-forward deploy/customer 8080:8080 -n your-namespace @@ -870,383 +314,53 @@ curl http://localhost:8080/actuator/health/liveness curl http://localhost:8080/actuator/health/readiness ``` -**Fixes:** +If endpoints return errors or don't exist, check that you've included the correct dependencies (Spring Boot Actuator or Helidon Health) and that your application framework matches the chart's `framework` setting. -**Slow startup:** -```yaml -livenessProbe: - initialDelaySeconds: 60 # Increase from default 30 -``` - -**Database dependency:** -```yaml -readinessProbe: - initialDelaySeconds: 20 # Give DB time to connect - failureThreshold: 5 # More tolerance -``` +## Helm Operations -#### 3. Metrics Not Appearing +Beyond basic installation, you'll need to update deployments, debug template rendering, and inspect running releases. -**See detailed troubleshooting in [Observability and Metrics](#troubleshooting-metrics) section above.** +Upgrade a deployed release with new values: -Quick checklist: -- [ ] `obaas.otel.enabled: true` -- [ ] OTEL_EXPORTER_OTLP_PROTOCOL set to "http/protobuf" (Helidon) -- [ ] No "failed to export" errors in logs -- [ ] Pod has signoz.io annotations -- [ ] Metrics endpoint returns data -- [ ] For Helidon: service name matches in values.yaml and microprofile-config.properties - -#### 4. Eureka Registration Failing - -**Check Eureka environment variables:** -```bash -kubectl exec deploy/customer -n your-namespace -- env | grep -i eureka -``` - -**Verify OBaaS ConfigMap exists:** ```bash -kubectl get configmap obaas-config -n -o yaml | grep eureka -``` - -**Spring Boot Eureka logs:** -```bash -kubectl logs deploy/customer -n your-namespace | grep -i eureka -``` - -Should see: "DiscoveryClient registering service" and "Registered instance" - -#### 5. Image Pull Errors - -**Symptom:** `ImagePullBackOff` or `ErrImagePull` - -**Check events:** -```bash -kubectl describe pod customer-xxx -n your-namespace -``` - -**Common causes:** - -**Wrong image path/tag:** -```yaml -image: - repository: "us-phoenix-1.ocir.io/tenancy/customer" # Verify this exists - tag: "1.0.0" # Verify tag exists +helm upgrade customer ./obaas-sample-app \ + -f values-customer.yaml \ + -n your-namespace ``` -**Missing or wrong image pull secret:** -```bash -# Verify secret exists -kubectl get secret ocir -n your-namespace +Render templates locally without installing (requires cluster access to query ConfigMaps): -# Test secret (should show JSON with auth) -kubectl get secret ocir -n your-namespace -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d -``` - -**Recreate if needed:** ```bash -kubectl delete secret ocir -n your-namespace -kubectl create secret docker-registry ocir \ - --docker-server=us-phoenix-1.ocir.io \ - --docker-username='tenancy/user' \ - --docker-password='token' \ - -n your-namespace +helm template customer ./obaas-sample-app \ + -f values-customer.yaml \ + --debug ``` -### Getting More Help +Inspect what's actually deployed: -**Gather diagnostic information:** ```bash -# Pod status and events -kubectl get pods -n your-namespace -kubectl describe pod customer-xxx -n your-namespace - -# Application logs -kubectl logs deploy/customer -n your-namespace --tail=100 - -# Environment variables -kubectl exec deploy/customer -n your-namespace -- env | sort - -# Helm release -helm list -n your-namespace +# Show current values helm get values customer -n your-namespace -helm get manifest customer -n your-namespace - -# OBaaS platform health -kubectl get all -n -kubectl get configmap obaas-config -n -o yaml -kubectl get configmap obaas-observability-config -n -o yaml -``` - -## Examples - -### Example 1: Production Helidon Service - -**values-customer-prod.yaml:** -```yaml -replicaCount: 3 - -image: - repository: "us-phoenix-1.ocir.io/mytenancy/customer-helidon" - tag: "2.1.0" - pullPolicy: Always - -imagePullSecrets: - - name: ocir - -fullnameOverride: "customer" - -service: - type: ClusterIP - port: 8080 - -obaas: - namespace: obaas-prod - framework: HELIDON - - database: - credentialsSecret: customer-prod-db-secret - walletSecret: prod-adb-wallet - - helidon: - enabled: true - datasource: - name: "customer" - hibernate: - hbm2ddl_auto: validate # Never modify prod schema - show_sql: false - format_sql: false - otel: - serviceName: "customer" - - eureka: - enabled: true - - otel: - enabled: true - -resources: - requests: - cpu: 200m - memory: 384Mi - limits: - cpu: 1000m - memory: 768Mi - -autoscaling: - enabled: true - minReplicas: 3 - maxReplicas: 20 - targetCPUUtilizationPercentage: 70 -livenessProbe: - httpGet: - path: /health/live - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /health/ready - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 5 - timeoutSeconds: 2 - failureThreshold: 3 -``` +# Show rendered Kubernetes manifests +helm get manifest customer -n your-namespace -**Deploy:** -```bash -helm install customer ./obaas-sample-app \ - -f values-customer-prod.yaml \ - -n production \ - --create-namespace +# List all releases +helm list -n your-namespace ``` -### Example 2: Development Spring Boot Service - -**values-order-dev.yaml:** -```yaml -replicaCount: 1 - -image: - repository: "us-ashburn-1.ocir.io/mytenancy/order-service" - tag: "latest" - -imagePullSecrets: - - name: ocir - -fullnameOverride: "order" - -obaas: - namespace: obaas-dev - framework: SPRING_BOOT - - database: - credentialsSecret: order-dev-db-secret - walletSecret: dev-adb-wallet - - springboot: - enabled: true - - eureka: - enabled: true - - otel: - enabled: true - -resources: - requests: - cpu: 100m - memory: 256Mi - limits: - cpu: 500m - memory: 1Gi -``` +Validate your chart before deploying: -**Deploy:** ```bash -helm install order ./obaas-sample-app \ - -f values-order-dev.yaml \ - -n development \ - --create-namespace -``` - -### Example 3: Helidon Service Without Eureka - -**values-inventory-standalone.yaml:** -```yaml -image: - repository: "us-phoenix-1.ocir.io/mytenancy/inventory" - tag: "1.5.0" - -fullnameOverride: "inventory" - -obaas: - namespace: obaas-dev - framework: HELIDON - - database: - credentialsSecret: inventory-db-secret - walletSecret: dev-adb-wallet - - helidon: - enabled: true - datasource: - name: "inventory" - hibernate: - hbm2ddl_auto: update - otel: - serviceName: "inventory" - - eureka: - enabled: false # Standalone service - - otel: - enabled: true # Still want observability -``` - -### Example 4: Multi-Environment with Overlays - -**values.yaml** (base): -```yaml -image: - repository: "us-phoenix-1.ocir.io/mytenancy/customer" - pullPolicy: Always - -imagePullSecrets: - - name: ocir - -fullnameOverride: "customer" - -obaas: - framework: HELIDON - helidon: - enabled: true - datasource: - name: "customer" - otel: - serviceName: "customer" - eureka: - enabled: true - otel: - enabled: true -``` - -**values-dev.yaml** (development overlay): -```yaml -image: - tag: "latest" - -replicaCount: 1 - -obaas: - namespace: obaas-dev - database: - credentialsSecret: customer-dev-db - walletSecret: dev-wallet - helidon: - hibernate: - hbm2ddl_auto: create - show_sql: true - -resources: - requests: - cpu: 50m - memory: 128Mi +helm lint ./obaas-sample-app -f values-customer.yaml ``` -**values-prod.yaml** (production overlay): -```yaml -image: - tag: "2.1.0" - -replicaCount: 3 +Uninstall a release (keeps namespace): -obaas: - namespace: obaas-prod - database: - credentialsSecret: customer-prod-db - walletSecret: prod-wallet - helidon: - hibernate: - hbm2ddl_auto: validate - show_sql: false - -resources: - requests: - cpu: 200m - memory: 384Mi - limits: - cpu: 1000m - memory: 768Mi - -autoscaling: - enabled: true - minReplicas: 3 - maxReplicas: 20 -``` - -**Deploy to environments:** ```bash -# Development -helm install customer ./obaas-sample-app \ - -f values.yaml \ - -f values-dev.yaml \ - -n development - -# Production -helm install customer ./obaas-sample-app \ - -f values.yaml \ - -f values-prod.yaml \ - -n production +helm uninstall customer -n your-namespace ``` ---- - ## Additional Resources - [Oracle Backend for Microservices and AI Documentation](https://docs.oracle.com/en/database/oracle/oracle-database/) diff --git a/helm/charts/obaas-sample-app/templates/deployment.yaml b/helm/charts/obaas-sample-app/templates/deployment.yaml index 6944e9541..955a06af1 100644 --- a/helm/charts/obaas-sample-app/templates/deployment.yaml +++ b/helm/charts/obaas-sample-app/templates/deployment.yaml @@ -19,9 +19,9 @@ spec: {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} - {{- if eq .Values.obaas.framework "SPRING_BOOT" }} + {{- if eq (.Values.obaas.framework | upper) "SPRING_BOOT" }} signoz.io/path: /actuator/prometheus - {{- else if eq .Values.obaas.framework "HELIDON" }} + {{- else if eq (.Values.obaas.framework | upper) "HELIDON" }} signoz.io/path: /metrics {{- end }} labels: @@ -40,7 +40,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} containers: - - name: ku{{ .Chart.Name }} + - name: {{ .Chart.Name }} {{- with .Values.securityContext }} securityContext: {{- toYaml . | nindent 12 }} @@ -48,6 +48,7 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} env: + {{- if $.Values.obaas.database.enabled }} - name: CONNECT_STRING value: jdbc:oracle:thin:@$(DB_SERVICE)?TNS_ADMIN=/oracle/tnsadmin - name: DB_SERVICE @@ -55,16 +56,17 @@ spec: secretKeyRef: name: {{ $.Values.obaas.database.credentialsSecret }} key: db.service + {{- end }} # Lookup ObaaS configuration {{- $obaas := (lookup "v1" "ConfigMap" .Values.obaas.namespace "obaas-config") }} {{- $observability := (lookup "v1" "ConfigMap" .Values.obaas.namespace "obaas-observability-config") }} {{- if $.Values.obaas.mp_lra.enabled }} - name: MP_LRA_COORDINATOR_URL - value: {{ $obaas.data.MP_LRA_COORDINATOR_URL | quote }} + value: {{ $obaas.data.otmm | quote }} - name: MP_LRA_PARTICIPANT_URL - value: {{ $obaas.data.MP_LRA_PARTICIPANT_URL | quote }} + value: {{ $obaas.data.otmm | quote }} {{- end }} - {{- if eq .Values.obaas.framework "SPRING_BOOT" }} + {{- if eq (.Values.obaas.framework | upper) "SPRING_BOOT" }} {{- if $.Values.obaas.eureka.enabled }} - name: EUREKA_INSTANCE_PREFER_IP_ADDRESS value: "true" @@ -75,17 +77,18 @@ spec: - name: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE value: {{ $obaas.data.eureka | quote }} - name: EUREKA_INSTANCE_HOSTNAME - value: {{ include "obaas-app.fullname" . }}-{{ $.Release.Namespace }} + value: {{ include "obaas-app.fullname" . }} {{- end }} {{- if $.Values.obaas.otel.enabled }} - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: {{ index $observability.data "signoz-otel-collector" | quote }} + value: {{ (index $observability.data "signoz-otel-collector") | quote }} {{- end }} {{- if $.Values.obaas.springboot.enabled }} - name: SPRING_PROFILES_ACTIVE value: {{ $obaas.data.SPRING_PROFILES_ACTIVE | quote }} - name: SPRING_CONFIG_LABEL value: {{ $obaas.data.SPRING_CONFIG_LABEL | quote }} + {{- if $.Values.obaas.database.enabled }} - name: SPRING_DATASOURCE_URL value: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" - name: SPRING_DATASOURCE_USERNAME @@ -99,8 +102,6 @@ spec: name: {{ $.Values.obaas.database.credentialsSecret }} key: db.password # Liquibase configuration (uses separate admin credentials for migrations) - - name: LIQUIBASE_ENABLED - value: "true" - name: LIQUIBASE_DATASOURCE_URL value: "jdbc:oracle:thin:@${DB_SERVICE}?TNS_ADMIN=/oracle/tnsadmin" - name: LIQUIBASE_DATASOURCE_USERNAME @@ -114,10 +115,11 @@ spec: name: {{ $.Values.obaas.database.credentialsSecret }} key: db.lb_password {{- end }} - {{- else if eq .Values.obaas.framework "HELIDON" }} + {{- end }} + {{- else if eq (.Values.obaas.framework | upper) "HELIDON" }} {{- if $.Values.obaas.otel.enabled }} - name: OTEL_EXPORTER_OTLP_ENDPOINT - value: {{ index $observability.data "signoz-otel-collector" | quote }} + value: {{ (index $observability.data "signoz-otel-collector") | quote }} - name: OTEL_EXPORTER_OTLP_PROTOCOL value: "http/protobuf" - name: OTEL_SERVICE_NAME @@ -133,10 +135,11 @@ spec: - name: eureka.client.service-url.defaultZone value: "http://eureka-0.eureka.{{ .Values.obaas.namespace }}.svc.cluster.local:8761/eureka" - name: eureka.instance.hostname - value: {{ include "obaas-app.fullname" . }}-{{ $.Release.Namespace }} + value: {{ include "obaas-app.fullname" . }} - name: eureka.instance.preferIpAddress value: "true" {{- end }} + {{- if $.Values.obaas.database.enabled }} - name: javax.sql.DataSource.{{ $.Values.obaas.helidon.datasource.name }}.connectionFactoryClassName value: oracle.jdbc.pool.OracleDataSource - name: javax.sql.DataSource.{{ $.Values.obaas.helidon.datasource.name }}.URL @@ -151,12 +154,7 @@ spec: secretKeyRef: name: {{ $.Values.obaas.database.credentialsSecret }} key: db.password - - name: hibernate.hbm2ddl.auto - value: {{ $.Values.obaas.helidon.hibernate.hbm2ddl_auto | quote }} - - name: hibernate.show_sql - value: {{ $.Values.obaas.helidon.hibernate.show_sql | quote }} - - name: hibernate.format_sql - value: {{ $.Values.obaas.helidon.hibernate.format_sql | quote }} + {{- end }} - name: server.port value: "{{ $.Values.service.port }}" - name: server.host @@ -177,7 +175,7 @@ spec: {{- else }} livenessProbe: httpGet: - {{- if eq .Values.obaas.framework "HELIDON" }} + {{- if eq (.Values.obaas.framework | upper) "HELIDON" }} path: /health/live {{- else }} path: /actuator/health/liveness @@ -194,7 +192,7 @@ spec: {{- else }} readinessProbe: httpGet: - {{- if eq .Values.obaas.framework "HELIDON" }} + {{- if eq (.Values.obaas.framework | upper) "HELIDON" }} path: /health/ready {{- else }} path: /actuator/health/readiness @@ -210,15 +208,19 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} volumeMounts: + {{- if $.Values.obaas.database.enabled }} - name: {{ $.Values.obaas.database.walletSecret }} mountPath: /oracle/tnsadmin + {{- end }} {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} volumes: + {{- if $.Values.obaas.database.enabled }} - name: {{ $.Values.obaas.database.walletSecret }} secret: secretName: {{ $.Values.obaas.database.walletSecret }} + {{- end }} {{- with .Values.volumes }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/helm/charts/obaas-sample-app/values.yaml b/helm/charts/obaas-sample-app/values.yaml index 2dcc53da6..bc1ab9437 100644 --- a/helm/charts/obaas-sample-app/values.yaml +++ b/helm/charts/obaas-sample-app/values.yaml @@ -155,6 +155,7 @@ obaas: framework: REPLACE_WITH_FRAMEWORK # Options: SPRING_BOOT or HELIDON database: + enabled: true # If true, database configuration will be injected # TODO: Set the name of your database credentials secret credentialsSecret: REPLACE_WITH_DB_CREDENTIALS_SECRET # e.g., my-app-db-secrets # TODO: Set the name of your ADB wallet secret @@ -178,10 +179,6 @@ obaas: datasource: # TODO: CRITICAL - Must match the datasource name in your Helidon application.yaml name: "REPLACE_WITH_DATASOURCE_NAME" # e.g., "customer", "order", "inventory" - hibernate: - hbm2ddl_auto: create # Options: create, update, validate, none - show_sql: true # Set to false in production - format_sql: true server: host: "0.0.0.0" metrics: