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.
Release channels and installation sources
The first two links open the Hosted release repositories in the Smart Kubaba management interface with a format filter. Obtain the actual Docker or Go protocol endpoint used by clients from the corresponding repository details. The direct CLI module archive and repository lists may require authorized access.
- Docker release repositoryOpens the Hosted Docker release-repository list in the Smart Kubaba management interface.
- Go release repositoryOpens the Hosted Go release-repository list in the Smart Kubaba management interface.
- Kubaba CLI v1.0.61 source archiveVersioned source ZIP from the Go module proxy; it is not an executable binary and may require authorization.
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 and distribute the license-verification public key through a separate Kubernetes Secret.
- 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.
- License-verification Secret: the chart creates it when license.existingSecret is empty, or uses the named existing Secret when configured.
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
# The chart distributes the license verification public key in a dedicated
# Kubernetes Secret. Keep existingSecret empty to use the chart-managed Secret.
license:
publicKey: "MCowBQYDK2VwAyEAKj+bp9Ahv5MlaEjV/Q4I9Uo2KsHjNBmdvTgpY8Aapwk="
existingSecret: ""
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: 100GiCore, image, Service, and Secret parameters
These fields determine generated resource names, the application image, and platform connections. Do not assume that defaults are directly suitable for production.
- replicaCount (3): Deployment replica count only when autoscaling.enabled=false; with HPA enabled, minReplicas is the floor.
- revisionHistoryLimit (10): number of old ReplicaSets retained by the Deployment; balance rollback history against cluster resource use.
- fullnameOverride (empty): generates <release>-smart-kubaba when empty; pin it during adoption of existing resources to avoid selector changes.
- image.repository (kubaba.s3t.co/smart-kubaba): image source; the provided Docker release repository is the protocol root of this image channel.
- image.tag (empty): falls back to Chart.appVersion; production must explicitly pin a verified immutable tag and digest mapping.
- image.pullPolicy (Always) and image.pullSecrets: control pull behavior and names of pre-created dockerconfigjson Secrets; the chart creates no credentials.
- existingSecret (smart-kubaba-secrets): required Secret injected through envFrom; real values never belong in values.yaml.
- license.publicKey and license.existingSecret: select either the chart-managed public-key Secret or an existing Secret containing SMART_KUBABA_LICENSE_PUBLIC_KEY.
- service.type (ClusterIP) and service.port (8080): determine Service exposure and port; the container target remains the named http port on 8080.
Ingress, storage, and persistence parameters
Plan the ingress-controller contract together with the durable artifact layer; rendering YAML alone is not evidence of data durability.
- ingress.enabled (false): enables Ingress rendering; when disabled, host and TLS fields create no resource.
- ingress.className (nginx), annotations, and host: controller class, controller-specific settings, and the single canonical host; annotation keys are not portable across controllers.
- ingress.tls.enabled (true) and secretName (kubaba-tls): control the Ingress TLS block and pre-created certificate Secret; the chart issues no certificate.
- storage.type (FILESYSTEM): selects FILESYSTEM or S3 backend; S3 bucket, region, endpoint, and credential values come from existingSecret.
- storage.rootDirectory and archiveDirectory: active and archive paths inside the container; evaluate them on the mounted volume for FILESYSTEM and with application-prefix behavior for S3.
- persistence.enabled (true): mounts a PVC when true; when false, /data/smart-kubaba is emptyDir and should be only temporary workspace with S3-backed durable objects.
- persistence.existingClaim: when set, the chart creates no PVC and mounts this claim; when empty, it creates one from storageClass, accessModes, and size.
- persistence.storageClass, accessModes ([ReadWriteMany]), and size (100Gi): contract only for a chart-created PVC; independently verify that the class provides genuine multi-node RWX.
Resources, autoscaling, and placement parameters
Measure application replica count together with the PostgreSQL connection budget, storage throughput, and node and zone capacity.
- resources.requests and limits: define scheduler guarantees and container limits for CPU, memory, and ephemeral storage; monitor ephemeral storage especially for image and SBOM work.
- autoscaling.enabled (true): enables the HPA resource; Metrics Server is required and Deployment replicas is omitted.
- autoscaling.minReplicas (3), maxReplicas (10), and targetCPUUtilizationPercentage (70): replica range and CPU target; maxReplicas × DB pool must fit the connection budget.
- podDisruptionBudget.enabled (true) and minAvailable (2): minimum ready pods during voluntary disruption; it must not conflict with minReplicas.
- nodeSelector, tolerations, and affinity: eligible-node selection, taint tolerance, and advanced placement rules; empty maps or lists are omitted.
- topologySpreadConstraints: each rule carries maxSkew, topologyKey, and whenUnsatisfiable; the chart injects its selector. With hostname DoNotSchedule, pods may remain Pending without enough nodes.
JVM, database-pool, probe, and shutdown parameters
These values directly affect memory, connection, and rollout behavior; do not increase them solely from replica count without measurement.
- javaToolOptions: JAVA_TOOL_OPTIONS value; default Xms256m and Xmx1280m retain room for native memory, direct buffers, and JVM overhead under the 2Gi limit.
- terminationGracePeriodSeconds (60) and preStopDelaySeconds (10): provide the shutdown window for endpoint removal and the application's fixed 45-second shutdown timeout.
- databasePool.maximumSize (10) and minimumIdle (2): per-pod HikariCP bounds; all replicas, migrations, and administration connections must remain below PostgreSQL max_connections.
- connectionTimeoutMillis (10000) and validationTimeoutMillis (5000): connection-acquisition and validation limits; keep validation timeout below connection timeout.
- idleTimeoutMillis (600000), maxLifetimeMillis (1800000), and leakDetectionThresholdMillis (0): idle, lifetime, and optional leak-diagnostic thresholds; align them with database and network timeouts.
- probes.startup, readiness, and liveness failureThreshold and periodSeconds: control failure tolerance with a fixed three-second timeout. Readiness checks dependencies; liveness checks process health.
Values merging, inspection, and override order
Chart defaults load first; -f files merge from left to right, and --set or --set-string applies last. Keep non-secret environment differences in separate values files and use --set-string for fields such as image tags to prevent type coercion.
- Record the selected chart version's actual defaults with helm show values; do not rely on values.yaml from another branch.
- Inspect image, Secret references, PVC, securityContext, probes, HPA and PDB, and Ingress in helm template output before applying.
- Retain helm get values --all and helm get manifest as comparison evidence for effective installed values and submitted manifests.
# Inspect the exact defaults shipped by the selected chart version.
helm repo add kubaba https://kubaba.s3t.co/repository/helm/helm-release/
helm repo update kubaba
helm search repo kubaba/smart-kubaba --versions
helm show values kubaba/smart-kubaba --version "<chart-version>" > values-defaults.yaml
# Keep environment-specific overrides in a separate, secret-free file.
helm lint kubaba/smart-kubaba \
--version "<chart-version>" \
-f values-production.yaml
helm template smart-kubaba kubaba/smart-kubaba \
--version "<chart-version>" \
--namespace kubaba \
-f values-production.yaml \
--set-string image.tag="<immutable-image-tag>" \
> rendered-smart-kubaba.yaml
# After installation, compare effective values and the rendered manifest.
helm -n kubaba get values smart-kubaba --all
helm -n kubaba get manifest smart-kubaba > installed-smart-kubaba.yamlSecret and image-pull structure
The Kubernetes Secret referenced by existingSecret supplies application environment keys through envFrom; the chart does not create this credential Secret and real values never belong in values.yaml. The license-verification public key is distributed automatically through the separate license setting.
- 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.
- By default, Helm creates the smart-kubaba-license-verification Secret for the public key; no manual public-key Secret is required.
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.
- Verify that the rendered output contains the smart-kubaba-license-verification Secret and the pod reference to SMART_KUBABA_LICENSE_PUBLIC_KEY.
- 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.