https://github.com/stackitcloud/stackit-cmf-replatform-springboot-k8s
STACKIT Cloud Framework Replatform Springboot Example for Kubernetes
https://github.com/stackitcloud/stackit-cmf-replatform-springboot-k8s
Last synced: about 1 month ago
JSON representation
STACKIT Cloud Framework Replatform Springboot Example for Kubernetes
- Host: GitHub
- URL: https://github.com/stackitcloud/stackit-cmf-replatform-springboot-k8s
- Owner: stackitcloud
- License: mit
- Created: 2026-05-07T15:17:39.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-05-08T14:43:04.000Z (3 months ago)
- Last Synced: 2026-05-08T16:39:47.920Z (3 months ago)
- Language: HCL
- Size: 14.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# stackit-cmf-replatform-springboot-k8s
Runnable replatform example for STACKIT: migrate a Spring Boot workload to SKE with DNS and Observability.
## What this example creates
- Optional target project creation
- SKE cluster (small default node pool)
- DNS zone and external-dns integration
- STACKIT Observability instance
- Spring Boot Deployment + Service (LoadBalancer)
- Optional Horizontal Pod Autoscaler (HPA) for Spring Boot
- Optional STACKIT PostgreSQL Flex target database
- Metrics exporter sidecar on port 9090
- Observability scrape config for Spring Boot metrics
- Grafana dashboard import
- Optional load-generator pod
- Optional Kubernetes migration job for VM PostgreSQL -> PostgreSQL Flex
## Prerequisites
- Terraform >= 1.5
- Service account key file
- Required permissions for SKE, DNS, Observability, and optional project creation
## 1) Configure variables
Copy the example file:
```bash
cp env.tfvars.example env.tfvars
```
Then edit `env.tfvars`.
### Common flag wrapper
To use the common CMF flags, copy and adjust:
```bash
cp flags.env.example flags.env
```
Then run:
```bash
./scripts/apply_with_common_flags.sh flags.env env.tfvars
```
Common flags:
- `setup_project`
- `setup_observability`
- `setup_database`
- `setup_workload`
- `setup_loadgen`
- `setup_dns`
### Values you must replace (currently `xxxx`)
- `target_project_owner_email`
- `parent_container_id`
- `ske_cluster_name`
- `observability_instance_name`
- `dns_zone_name`
- `dns_zone_display_name`
### Notes for these required values
- `target_project_owner_email`: service account or owner email used for project creation
- `parent_container_id`: folder/container ID (for `create_project = true`)
- `ske_cluster_name`: max 11 characters
- `observability_instance_name`: unique readable instance name
- `dns_zone_name`: delegated DNS zone (for example `cmf-1234.runs.onstackit.cloud`)
- `dns_zone_display_name`: display name for the DNS zone resource
### Commonly adjusted values
- `service_account_key_path`
- `target_project_name`
- `region`, `availability_zone`
- `node_pool_machine_type`
- `springboot_image`
- `enable_postgres_flex`
- `enable_springboot_hpa`, `springboot_hpa_*`
- `enable_load_generator`, `load_profile`
## Kubernetes rightsizing options
For replatformed workloads on SKE, rightsizing can be applied at multiple layers:
- Pod layer: adjust requests/limits and optionally enable HPA.
- Node pool layer: tune node pool min/max and machine type.
- Storage layer: choose suitable storage classes for persistence characteristics.
### Enable HPA (optional)
Set in `env.tfvars`:
```hcl
enable_springboot_hpa = true
springboot_hpa_min_replicas = 1
springboot_hpa_max_replicas = 5
springboot_hpa_target_cpu_utilization_percentage = 70
```
Then apply:
```bash
terraform apply -var-file=env.tfvars
```
## PostgreSQL Flex target option
Set the following values in `env.tfvars` to enable a managed database target:
```hcl
enable_postgres_flex = true
postgres_flex_instance_name = "cmf-rpltf-postgres"
postgres_flex_app_username = "springmusic"
postgres_flex_target_database = "postgres"
postgres_flex_target_app_acl_cidrs = ["203.0.113.10/32"]
```
When enabled, Terraform creates PostgreSQL Flex (`stackit_postgresflex_instance` and `stackit_postgresflex_user`) and injects datasource settings into the Spring Boot deployment.
ACL is intentionally strict by default: only CIDRs in `postgres_flex_target_app_acl_cidrs` (or legacy `postgres_flex_acl`) are allowed.
If `enable_observability_alerts = true` and PostgreSQL Flex metrics scraping is enabled,
the baseline alert group also includes PostgreSQL-focused alerts for exporter availability,
connection saturation, cache-hit ratio, and temp file usage.
## VM PostgreSQL to PostgreSQL Flex migration job
To migrate source data from the VM-based PostgreSQL (for example from the Rehost setup), enable:
```hcl
enable_postgres_flex = true
deploy_postgres_migration_job = true
source_postgres_host = ""
source_postgres_port = 5432
source_postgres_database = "springmusic"
source_postgres_username = "springmusic"
source_postgres_password = ""
include_source_postgres_host_in_temp_acl = true
```
The migration job runs a `pg_dump` from source and restores the dump into PostgreSQL Flex using `pg_restore`.
If migration is executed from a source-side client that must connect directly to PostgreSQL Flex,
temporarily add its CIDR via `postgres_flex_temp_migration_acl_cidrs`.
Terraform output `postgres_flex_source_host_acl_suggestion` provides `source_postgres_host/32` when source host is an IPv4 address.
After migration, remove temporary migration CIDRs and apply again.
## 2) Deploy
```bash
terraform init
terraform validate
terraform plan -var-file=env.tfvars
terraform apply -var-file=env.tfvars
```
## 3) Verify workload
```bash
mkdir -p .tmp
terraform output -raw kubeconfig > .tmp/replatform.kubeconfig
export KUBECONFIG=$PWD/.tmp/replatform.kubeconfig
kubectl get ns
kubectl get deploy,svc -n springboot
kubectl get pods -n springboot
```
## 4) Verify metrics path
```bash
HOST=$(terraform output -raw springboot_hostname)
curl -sS "http://$HOST:9090/metrics" | head -n 30
```
Expected: lines beginning with `springboot_legacy_counter`, `springboot_legacy_gauge`, `springboot_legacy_metric`.
## 5) Verify outputs
```bash
terraform output
```
Important outputs:
- `springboot_url`
- `springboot_hostname`
- `observability_grafana_url`
- `project_id`
- `postgres_flex_host`
- `postgres_flex_jdbc_url`
- `postgres_flex_effective_acl_cidrs`
- `postgres_flex_source_host_acl_suggestion`
## Troubleshooting
- If `metrics-exporter` restarts, inspect logs:
```bash
POD=$(kubectl get pod -n springboot -l app=springboot -o jsonpath='{.items[0].metadata.name}')
kubectl logs -n springboot "$POD" -c metrics-exporter --tail=200
kubectl logs -n springboot "$POD" -c metrics-exporter --previous --tail=200
```
- If scrape exists but no data arrives, check target health in Prometheus/Grafana datasource (`up{job=""}`).
- Scrape interval must be greater than `60s` for this environment (`61s` is set by default).
## Destroy
```bash
terraform destroy -var-file=env.tfvars
```