Skip to main content
This chapter provides reference manifests for a single-namespace Decision Control deployment. Substitute your namespace, hostname, image reference, and secret values.

Architecture overview

Decision Control is a stateless Spring Boot application. A namespace deployment consists of: PostgreSQL is assumed to exist already, reachable from the namespace (managed service, an operator-provisioned instance, or a database in another namespace).

Namespace

ConfigMap

Secret

Secret encryption at rest must be enabled on the cluster.

Deployment

Service

Ingress (Kubernetes)

The OIDC redirect URI registered at your provider must match https://dc.example.com/auth/callback.

Database connectivity

  • Point SPRING_DATASOURCE_URL at the database’s in-cluster service DNS or external endpoint.
  • For TLS, append SSL parameters to the URL and mount the CA — see Database Configuration.
  • First rollout against an empty database: set HIBERNATE_DDL_AUTO=update, then switch to validate and re-apply.

OpenShift specifics

  • Replace the Ingress with a Route:
  • The image runs as non-root and is compatible with the default restricted-v2 SCC. Do not grant anyuid.
  • Use ImageStreams if your registry workflow relies on them; otherwise reference the image directly.

High availability

  • Decision Control is stateless — scale horizontally by raising replicas. All state lives in PostgreSQL.
  • The OIDC flow uses stateless tokens, so no session affinity is required.
  • Size the database connection pool and PostgreSQL max_connections for the total replica count.

Diagnostics

For diagnostics that require a shell, the Decision Control image is distroless and ships no shell of its own. Use kubectl debug with a container image your organization trusts (an ephemeral debug container targeting the pod), or run the diagnostic command from a separate pod in the same namespace.

Updating configuration

ConfigMap and Secret changes are not picked up by running pods. After editing either, restart the Deployment to roll the change forward:
Image-only updates (a new tag for the same Deployment) use the rolling update strategy without manual intervention — kubectl set image triggers the rollout. Provider envs, secrets, and TLS material continue to be sourced from the existing ConfigMap and Secret. For scaling decisions, see the High availability note above. kubectl scale deployment/decision-control --replicas=N works as expected once the prerequisites (stateless auth and a DB pool sized for the total replica count) are satisfied.

Monitoring and observability

Decision Control exposes the standard Spring Boot Actuator endpoints. The default exposed set is health, info, metrics, and prometheus — adjust via ACTUATOR_ENDPOINTS if your stack requires a different list.

Liveness and readiness

The Kubernetes probes consume the same /actuator/health endpoint as documented in Container Configuration. A healthy pod returns HTTP 200 with body:
The Deployment manifest already wires readinessProbe and livenessProbe against this endpoint with conservative initial-delay and failure-threshold values. Tighten them only after measuring real boot times for your image and JVM.

Prometheus

A ServiceMonitor scrapes the application directly when you run the Prometheus Operator. The example below assumes the Service is decision-control exposing the default Spring Boot port:
For non-Operator Prometheus, scrape the pod IPs directly via the standard prometheus.io/scrape: "true" pod annotation pattern; the path is the same.

Logs

Decision Control writes JSON-structured logs to stdout. Stream them with kubectl logs; pipe to your log-aggregation stack (Loki, ELK, Datadog) the same way as any other Spring Boot service in the cluster.
Increase verbosity per logger using LOGGING_LEVEL_* env variables (Spring’s standard mechanism). Set them on the ConfigMap and roll the Deployment; remove the override before normal operation to avoid log-volume cost.

Troubleshooting

Common failure modes and where to look:

Pod stuck in ImagePullBackOff

Verify the image-pull Secret in the same namespace as the Deployment is the one referenced by imagePullSecrets, and that the registry credentials are still valid. The Aletyx portal lets you reissue an API token without revoking the previous one — useful for rotating without downtime.

Pod stuck in CrashLoopBackOff

Read the pod logs — kubectl logs <pod> -n <namespace> --previous shows the last crash even after restart. The two most common causes:
  • HIBERNATE_DDL_AUTO=validate against a stale schema after a major image bump that added tables. Either run a migration manually or temporarily switch to update (then revert).
  • 401 against /actuator/health because the probe is going through the OIDC filter. The health endpoint must be unauthenticated; if the path is filtered behind auth, the probe will 401 and Kubernetes will restart the pod.

Pod stuck in Pending

The scheduler has no node that fits the pod. Inspect with kubectl describe pod — the events line at the bottom names the constraint (resource shortfall, taint, PVC binding, etc.).

Database connection failures

Test reachability from inside the namespace before suspecting application config:
If the connection from a fresh pod also fails, the issue is networking (NetworkPolicy, firewall, DNS) — not Decision Control’s config. If the pod connects but Decision Control’s logs still show HikariCP errors, double-check the SPRING_DATASOURCE_* env values match what the netcheck used.

Ingress / Route returns 404 or 503

Verify the Ingress / Route is matched by the controller (kubectl get ingress -A shows the address); then verify TLS termination:
A 503 typically means the Service has no Ready endpoints — i.e. the upstream Deployment is not Running. A 404 from the controller (rather than the application) means the host header doesn’t match a known Ingress.