Installation
Production installation with Helm
Use the source chart to prepare secrets, PostgreSQL, S3 or RWX storage, ingress/TLS, HPA, PDB, probes, rollout, and rollback end to end.
Installation topology and prerequisites
The chart deploys Smart Kubaba as a stateless, horizontally scalable application tier. Durable correctness state lives in external or shared services.
- A Kubernetes 1.24-compatible cluster, Helm 3, and kubectl access; Metrics Server when HPA is enabled.
- External PostgreSQL reachable from application pods with sufficient max_connections budget.
- For production, S3-compatible shared object storage or a ReadWriteMany filesystem that every replica genuinely sees as the same content.
- A pre-created application Secret, imagePullSecret, ingress controller, DNS record, and TLS Secret.
- At least three eligible worker nodes when hostname spread uses DoNotSchedule; verify zone-spread behavior separately when zone labels are absent.
What resources does the chart create?
Chart templates never generate application credentials; they connect deployment resources to existing platform services.
- Deployment: non-root UID/GID 999, RollingUpdate with maxUnavailable=0 and maxSurge=1, 10-second minReady, and 600-second progress deadline.
- Service: ClusterIP with sessionAffinity=None and default port 8080.
- Ingress: one host, a / Prefix route, selectable ingressClass, and TLS Secret reference.
- HPA: CPU utilization with 30-second scale-up and 300-second scale-down stabilization; PDB defaults to minAvailable=2.
- Startup, readiness, and liveness probes; readiness includes PostgreSQL and shared storage, while liveness covers process health only.
- When persistence is enabled, an existing or chart-created PVC; when disabled, a temporary /data/smart-kubaba emptyDir.
Complete production values.yaml
The example below contains every chart value and uses safe placeholders for an S3-backed HA production profile. image.tag must be replaced with an immutable release.
- Ingress annotation keys match the source production profile's F5 NGINX Controller; use controller-specific equivalents for ingress-nginx or another controller.
- When autoscaling.enabled=true, Deployment does not use replicaCount; HPA minReplicas controls the initial replica floor.
- The 20 GiB ingress limit must align with backend upload bounds; unlimited body size must not be used.
replicaCount: 3
revisionHistoryLimit: 10
fullnameOverride: smart-kubaba
image:
repository: kubaba.s3t.co/smart-kubaba
tag: "REPLACE_WITH_IMMUTABLE_RELEASE"
pullPolicy: Always
pullSecrets:
- kubaba-s3t-co-docker-config
# This Secret must already exist. The chart never creates credentials.
existingSecret: smart-kubaba-secrets
service:
type: ClusterIP
port: 8080
ingress:
enabled: true
className: nginx
annotations:
# F5 NGINX Ingress annotations used by the source production profile.
# Replace these keys when the cluster uses ingress-nginx or another controller.
nginx.org/client-max-body-size: "20g"
nginx.org/proxy-read-timeout: "3600s"
nginx.org/proxy-send-timeout: "3600s"
host: kubaba.example.com
tls:
enabled: true
secretName: kubaba-tls
# Recommended production profile: shared S3-compatible object storage.
# Bucket, region, endpoint and optional credentials come from existingSecret.
storage:
type: S3
rootDirectory: /data/smart-kubaba/storage
archiveDirectory: /data/smart-kubaba/archive
# S3 keeps durable application objects outside the pod. The chart still mounts
# an emptyDir at /data/smart-kubaba for bounded temporary OSV work files.
persistence:
enabled: false
existingClaim: ""
storageClass: ""
accessModes:
- ReadWriteMany
size: 100Gi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 4
targetCPUUtilizationPercentage: 70
podDisruptionBudget:
enabled: true
minAvailable: 2
resources:
requests:
cpu: 500m
memory: 768Mi
ephemeral-storage: 1Gi
limits:
cpu: "2"
memory: 2Gi
ephemeral-storage: 10Gi
javaToolOptions: "-Xms256m -Xmx1280m -XX:+ExitOnOutOfMemoryError"
terminationGracePeriodSeconds: 60
preStopDelaySeconds: 10
# Pool sizes are per pod. Reserve PostgreSQL headroom for migrations,
# administration, monitoring and non-application clients.
databasePool:
maximumSize: 10
minimumIdle: 2
connectionTimeoutMillis: 10000
validationTimeoutMillis: 5000
idleTimeoutMillis: 600000
maxLifetimeMillis: 1800000
leakDetectionThresholdMillis: 0
probes:
startup:
failureThreshold: 24
periodSeconds: 5
readiness:
failureThreshold: 6
periodSeconds: 10
liveness:
failureThreshold: 3
periodSeconds: 20
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnywayFilesystem/RWX alternative
When filesystem storage is used instead of S3, the same PVC must mount concurrently on every replica. Node-local disk or a ReadWriteOnce volume is not valid for multi-replica production.
- When existingClaim is empty, the chart creates a PVC from accessModes and size; a pre-tested existing claim is preferred in production.
- For Longhorn, use a standard non-migratable RWX StorageClass; migratable=true is for block-mode live migration and does not provide the NFS share manager.
# Use this override only with storage shared by every replica.
storage:
type: FILESYSTEM
rootDirectory: /data/smart-kubaba/storage
archiveDirectory: /data/smart-kubaba/archive
persistence:
enabled: true
# Prefer a pre-created, tested RWX claim for production.
existingClaim: smart-kubaba-data-rwx
storageClass: ""
accessModes:
- ReadWriteMany
size: 100GiSecret and image-pull structure
The Kubernetes Secret referenced by existingSecret supplies application environment keys through envFrom. The chart does not create the Secret and real values never belong in values.yaml.
- PostgreSQL URL, username, and password plus bootstrap-admin username and password must exist in the secret manager before first installation.
- When S3 access keys are omitted, the backend can use the AWS default credential-provider chain; workload identity or instance role may be preferred.
- image.pullSecrets references a separate kubernetes.io/dockerconfigjson Secret; Docker config does not belong in the application Secret.
- The bootstrap-admin initial password is used only when the user does not yet exist; secret rotation and the administrator password policy must be operated separately after installation.
Required for first installation:
SMART_KUBABA_DB_URL
SMART_KUBABA_DB_USERNAME
SMART_KUBABA_DB_PASSWORD
SMART_KUBABA_ADMIN_USERNAME
SMART_KUBABA_ADMIN_INITIAL_PASSWORD
Required when storage.type is S3:
SMART_KUBABA_STORAGE_S3_BUCKET
SMART_KUBABA_STORAGE_S3_REGION
Provider-dependent S3 keys:
SMART_KUBABA_STORAGE_S3_ENDPOINT_URL
SMART_KUBABA_STORAGE_S3_PATH_STYLE_ACCESS
SMART_KUBABA_STORAGE_S3_ACCESS_KEY_ID
SMART_KUBABA_STORAGE_S3_SECRET_ACCESS_KEY
Optional OIDC redirect keys:
SMART_KUBABA_OIDC_SUCCESS_REDIRECT
SMART_KUBABA_OIDC_FAILURE_REDIRECT
The image pull credential is a separate kubernetes.io/dockerconfigjson
Secret named by image.pullSecrets.Installation steps
The commands are written to run from the D:/workspace/smart-kubaba repository root.
- Update image tag, host, TLS Secret, ingress class, storage, and capacity values in values-production.yaml for the target environment.
- Create the kubaba namespace, smart-kubaba-secrets, and registry pull Secret through the platform secret manager.
- Use helm lint for schema or template errors, then inspect rendered manifests and secret references with helm template.
- For the first installation, run helm upgrade --install with an immutable image tag and retain wait and timeout boundaries.
- Verify Deployment rollout, pod readiness, Service and Ingress, HPA and PDB, and the readiness endpoint.
# Run from the Smart Kubaba source repository.
kubectl create namespace kubaba --dry-run=client -o yaml | kubectl apply -f -
# Create smart-kubaba-secrets and the registry pull Secret through the
# platform secret manager before continuing. Do not commit plaintext values.
helm lint ./helm/smart-kubaba -f values-production.yaml
helm template smart-kubaba ./helm/smart-kubaba --namespace kubaba -f values-production.yaml --set-string image.tag="<release>" > rendered-smart-kubaba.yaml
helm upgrade --install smart-kubaba ./helm/smart-kubaba --namespace kubaba --create-namespace -f values-production.yaml --set-string image.tag="<release>" --wait --timeout 15mInstallation verification
A successful Helm result is not acceptance by itself. Verify the application, database, storage, package traffic, and operational evidence together.
- All pods must be Ready, Deployment Available, HPA and PDB in the expected state, and the Ingress TLS certificate valid.
- Readiness must be UP with healthy PostgreSQL, Flyway, and global shared storage. Liveness must not restart the process unnecessarily during an external dependency outage.
- Exercise management login, Hosted publish and download, Proxy fetch and cache, Group resolution, and Package Usage, Audit, and Outbound evidence as acceptance scenarios.
- S3 or RWX storage must serve the same artifact checksum through multiple replicas.
kubectl -n kubaba get deployment,service,ingress,pods,hpa,pdb,pvc
kubectl -n kubaba rollout status deployment/smart-kubaba --timeout=10m
kubectl -n kubaba wait --for=condition=Ready pod -l app=smart-kubaba --timeout=10m
helm -n kubaba status smart-kubaba
helm -n kubaba get values smart-kubaba --all
helm -n kubaba get manifest smart-kubaba > installed-smart-kubaba.yaml
# Readiness includes PostgreSQL and shared-storage availability.
kubectl -n kubaba port-forward service/smart-kubaba 8080:8080
curl --fail --silent --show-error http://127.0.0.1:8080/actuator/health/readinessUpgrade, rollback, and removal
For established releases, later upgrades can use --atomic to roll back failed rollouts automatically. When adopting existing raw-manifest resources into Helm for the first time, use a waited adoption without automatic cleanup or atomic behavior.
- Before every upgrade, record the PostgreSQL migration chain, chart appVersion and image tag, and previous Helm revision.
- Rollback is not only a pod or image rollback; compare Flyway history with the migration set present in the selected code version.
- helm uninstall does not delete PostgreSQL, the S3 bucket, or external PVC backups; data retention and recovery remain separate operator decisions.
# Later upgrades: pin an immutable chart/image release and enable atomic rollback.
helm upgrade smart-kubaba ./helm/smart-kubaba --namespace kubaba -f values-production.yaml --set-string image.tag="<new-release>" --atomic --wait --timeout 15m
helm -n kubaba history smart-kubaba
# Select a known-good revision from helm history.
helm -n kubaba rollback smart-kubaba <revision> --wait --timeout 15m
# Removal does not replace PostgreSQL/object-storage recovery planning.
helm -n kubaba uninstall smart-kubabaCapacity and security boundaries
- databasePool.maximumSize is per pod. autoscaling.maxReplicas × maximumSize plus migration, administration, monitoring, and other-client headroom must remain below PostgreSQL max_connections.
- Measure javaToolOptions together with resource limits; setting heap equal to the container memory limit leaves no room for native memory, direct buffers, or JVM overhead.
- The chart forces SMART_KUBABA_COOKIE_SECURE=true; production management traffic must not be exposed without TLS.
- Secret values must not be written to Helm command lines, values files, rendered manifests, Git, or CI logs.
- This chart does not provide backup and restore, RTO/RPO, certificate issuance, PostgreSQL HA, or object-storage durability guarantees; platform runbooks must cover them.