Skip to main content

Installation on Kubernetes

DBmarlin Server can run on Kubernetes as a single-replica StatefulSet. The installation uses Kustomize overlays for storage providers and keeps the server installation, PostgreSQL data, and configuration on a persistent volume.

Important

This installation is stateful and is intended for one server replica. Back up the database and configuration before changing the image, storage, or workload.

Prerequisites​

  • Kubernetes with kubectl and Kustomize support (kubectl apply -k).
  • A container registry reachable by the cluster.
  • A StorageClass that can provision a ReadWriteOnce volume for persistent installs.
  • Network connectivity from the server pod to every database target it monitors.
  • A namespace and context selected in kubectl before deploying.

DBmarlin's recommended disk size is approximately 20GB per monitored database instance. See the server hardware requirements for the profile recommendations.

Container image​

The public image is available at Docker Hub. The Kubernetes overlays select a version with the images.newTag field. Edit that field before a new installation or upgrade.

To build your own image, use the server Dockerfile and build scripts from the DBmarlin Docker repository, then push the image to a registry visible from the cluster.

Kubernetes layout​

The server manifests are in the dbmarlin-docker repository:

k8s/server-k8s/
├── k8s/base/ # PVC and LoadBalancer Service
├── k8s/components/ # StatefulSet, size, security, and Service components
├── k8s/overlays/ # Platform-specific Kustomize overlays
└── storage/ # Optional StorageClass/PV examples

The available overlays are:

OverlayStorageClassUse
stateful-localpathlocal-pathLocal-path provisioner and lab clusters
stateful-eksgp3AWS EKS with the EBS CSI driver
stateful-aksmanaged-csiAzure AKS
stateful-gkestandard-rwoGoogle GKE
stateful-civocivo-volumeCivo
stateful-openshiftibmc-vpc-block-10iops-tierIBM Cloud ROKS/OpenShift; edit for other OpenShift storage
devemptyDirEvaluation only; data is lost when the pod is replaced

The example StorageClass and PersistentVolume files are examples only. Review and adapt them to your cluster before applying them.

Platform-specific guidance​

Local-path Kubernetes​

Use stateful-localpath when the cluster has the Rancher local-path provisioner or another provisioner that provides a local-path StorageClass:

./server-k8s-deploy.sh stateful-localpath

This is suitable for kubeadm, Rancher Desktop, and lab clusters. Local-path storage is tied to a worker node by the provisioner; it is not a replacement for replicated cloud block storage. If you create a static local PersistentVolume, adapt the example files in storage/ to your node name and filesystem path.

Amazon EKS​

Use stateful-eks with the EBS CSI driver and a gp3 StorageClass:

./server-k8s-deploy.sh stateful-eks

The repository includes example gp3 StorageClasses for standard EKS and EKS Auto Mode. Use the provisioner that matches the cluster, and apply only one of those examples. The standard EKS example uses ebs.csi.aws.com; EKS Auto Mode uses ebs.csi.eks.amazonaws.com.

The EKS Service defaults to an internal Network Load Balancer. Private subnets must be tagged kubernetes.io/role/internal-elb, and the AWS Load Balancer Controller must be installed. To avoid a load balancer, use DBMARLIN_SERVICE=nodeport. To expose a public NLB, replace the internal Service component with service-aws-nlb-internet only after configuring authentication, HTTPS, and the required public-subnet tags.

Azure AKS​

Use stateful-aks with AKS's built-in managed-csi StorageClass:

./server-k8s-deploy.sh stateful-aks

Confirm that the cluster has a suitable Azure disk quota and that the selected node pool can attach the requested volume. The base Service is a LoadBalancer; use NodePort or port forwarding for a test installation.

Google GKE​

Use stateful-gke with the standard-rwo StorageClass:

./server-k8s-deploy.sh stateful-gke

Confirm that the Compute Engine Persistent Disk CSI driver and the requested disk quota are available. If the cluster spans zones, let the StorageClass choose the volume zone and keep the single StatefulSet replica with its attached disk.

Civo Kubernetes​

Use stateful-civo with Civo's civo-volume StorageClass:

./server-k8s-deploy.sh stateful-civo

Confirm that the account has enough block-volume capacity for the PVC and that the cluster can attach a volume to the selected worker node. The Service defaults to a LoadBalancer; NodePort is available for lower-cost testing.

OpenShift and IBM Cloud ROKS​

Use stateful-openshift for IBM Cloud ROKS/OpenShift. The example selects ibmc-vpc-block-10iops-tier; edit storageclass-patch.yaml if your cluster uses a different StorageClass, such as a classic IBM Cloud block-storage class:

./server-k8s-deploy.sh stateful-openshift

The overlay is compatible with OpenShift's restricted Security Context Constraint and arbitrary namespace UID. It does not request the fixed UID used by the optional Kubernetes nonroot component. Apply the generated file with oc, or paste it into the OpenShift console as described in Deploy without Kustomize. You can expose the UI with an OpenShift Route instead of a cloud LoadBalancer:

oc create route edge dbmarlin --service=dbmarlin-service --port=9090

Development and evaluation​

Use dev only for evaluation:

./server-k8s-deploy.sh dev

The overlay uses the local registry image localhost:5000/dbmarlin-server:latest, imagePullPolicy: Always, an emptyDir volume, and reduced CPU requests. The local registry must be reachable from the cluster. Replacing the pod deletes the server data, so do not use this overlay for monitoring that must survive a restart.

Choose a profile size​

The default profile is Small. You can select a profile with DBMARLIN_SIZE when using the deployment wrapper:

ProfileMonitored instancesCPUMemoryRecommended disk
XSmall11 vCPU2Gi20Gi
Small<51 vCPU4Gi100Gi
Medium<202 vCPU8Gi400Gi
Large<504 vCPU16Gi1Ti
XLarge<1008 vCPU32Gi2Ti

The size component changes the configure.sh profile and the pod CPU/memory requests and limits together. Disk is not resized automatically. The wrapper warns when the rendered PVC or an existing PVC is smaller than the selected profile's recommendation.

DBMARLIN_SIZE=Medium ./server-k8s-deploy.sh stateful-eks

For a lasting configuration, add the matching component to the overlay's kustomization.yaml:

components:
- ../../components/statefulset
- ../../components/size-medium

Deploy the server​

Choose the overlay for your cluster and render it first:

kubectl kustomize k8s/overlays/stateful-localpath

Make sure the rendered image tag, storage class, PVC size, and Service exposure are correct. Then use the wrapper, which checks the current context and namespace and asks for confirmation:

./server-k8s-deploy.sh stateful-localpath

Or apply directly:

kubectl apply -k k8s/overlays/stateful-localpath

Check the StatefulSet, pod, claim, and Service:

kubectl get statefulset,pod,pvc,service
kubectl logs statefulset/dbmarlin-server -c dbmarlin-copy
kubectl logs statefulset/dbmarlin-server -c dbmarlin-server

The application Service listens on port 9090. Tomcat and PostgreSQL use ports 9080 and 9070 inside the pod. A headless Service is created for the StatefulSet and is not the public UI endpoint.

Deploy without Kustomize​

Kustomize is only needed to assemble the platform-specific files. You can generate one standalone, multi-document YAML file and then deploy that file with any normal Kubernetes tool. kubectl kustomize renders locally; it does not contact the cluster or apply anything.

From the root of the cloned dbmarlin-docker repository, render the overlay for your platform:

kubectl kustomize k8s/server-k8s/k8s/overlays/stateful-eks > dbmarlin-server-eks.yaml

Review dbmarlin-server-eks.yaml before applying it. Check the image tag, PVC storage class and size, Service type, and any security settings. To choose a different profile or Service type, add the corresponding component to the overlay first, then render again. For example, add these entries under components: for a Medium profile and NodePort Service:

- ../../components/statefulset
- ../../components/size-medium
- ../../components/service-nodeport

Apply the generated file with the command-line client:

kubectl apply -f dbmarlin-server-eks.yaml

The same file can be applied with the OpenShift CLI:

oc apply -f dbmarlin-server-eks.yaml

Paste the generated YAML into the OpenShift console​

  1. Render the OpenShift overlay and save the output:

    kubectl kustomize k8s/server-k8s/k8s/overlays/stateful-openshift > dbmarlin-server-openshift.yaml
  2. Open the OpenShift project where DBmarlin should run and choose Import YAML (or +Add → Import YAML, depending on the console version).

  3. Paste the complete contents of dbmarlin-server-openshift.yaml into the editor. The file contains several YAML documents separated by ---; the console can create them together. If the console accepts only one document at a time, paste each document separately and create them in this order: Services and PVC first, then the StatefulSet.

  4. Review the namespace, image, storage class, PVC size, and Service exposure, then choose Create or Apply.

  5. Check the resulting pod, PVC, and Service from the console or with:

    oc get statefulset,pod,pvc,service
    oc logs pod/dbmarlin-server-0 -c dbmarlin-copy

The generated YAML is a snapshot. If you change the source overlay later, render a new file and apply it again. Keep the source overlay and the generated file under version control when using a Git-based deployment process; do not commit real credentials or private certificates.

Service exposure and security​

The base UI Service is a LoadBalancer on port 9090. The EKS overlay explicitly uses an internal NLB. Private subnets need the kubernetes.io/role/internal-elb tag and the AWS Load Balancer Controller must be installed and configured.

A new DBmarlin installation has authentication disabled. Keep the Service private while configuring authentication and HTTPS. To opt in to an internet-facing EKS NLB, replace the service-aws-nlb-internal component with service-aws-nlb-internet after reviewing subnet tags and access controls.

For test clusters, avoid a cloud load balancer with the NodePort component:

DBMARLIN_SERVICE=nodeport ./server-k8s-deploy.sh stateful-eks

Alternatively, use port forwarding without exposing a node port:

kubectl port-forward service/dbmarlin-service 9090:9090

On clusters enforcing the restricted Pod Security Standard, add the nonroot component after the StatefulSet component. The OpenShift overlay has its own arbitrary-UID-compatible patch; do not combine it with nonroot.

Upgrades​

The StatefulSet uses OnDelete, so changing an image tag does not restart the pod automatically. For a normal upgrade:

  1. Back up the database and configuration and check the release upgrade notes.

  2. Change images.newTag in the selected overlay.

  3. Re-apply with the same profile and Service settings used by the installation. Environment overrides are temporary and must be supplied on every apply.

  4. Delete the pod only after the apply succeeds:

    kubectl delete pod dbmarlin-server-0
  5. Check the init-container logs, pod readiness, and monitoring data.

Migrating from the old Deployment layout​

Older versions used k8s/prod and k8s/dev Deployments. Before migrating a persistent installation:

  1. Back up and verify the backup.

  2. Inspect the existing PVC's storage class, requested size, and capacity.

  3. Preserve the existing storage class in the selected overlay. A bound PVC's storage class cannot be changed in place; the old production example used gp2, while the current EKS example uses gp3.

  4. Set the base PVC request to the existing claim's size. Do not apply a smaller request over an expanded claim.

  5. Set the overlay image tag to the currently running version and render the result.

  6. Delete only the old Deployment and wait for its pod to terminate:

    kubectl delete deployment dbmarlin-server --cascade=foreground --wait=true
  7. Apply the prepared StatefulSet overlay. Do not use the removal script during migration because it deletes the PVC and its data.

The old dev Deployment used emptyDir; export anything needed before replacing it because its data is ephemeral.

Remove the server​

Data loss

The removal script deletes the PVC and all DBmarlin data. Back up first.

./server-k8s-remove-all.sh stateful-localpath

For a non-destructive workload removal, delete the StatefulSet while retaining the PVC and specify the appropriate retention behavior for your storage provider:

kubectl delete statefulset dbmarlin-server

Troubleshooting​

  • PVC Pending: check that the selected StorageClass exists, supports the requested access mode and size, and has a provisioner. For local volumes, check node affinity and the local path.
  • Pod stuck in Init: inspect kubectl logs pod/dbmarlin-server-0 -c dbmarlin-copy. Check image access, volume permissions, and available disk space.
  • Service has no endpoint: check that the pod is Ready and that the Service selector is app: dbmarlin-server.
  • LoadBalancer Pending: inspect Service events and cloud-controller logs. For EKS, check subnet tags and the AWS Load Balancer Controller.
  • Upgrade did not happen: the StatefulSet is OnDelete; delete dbmarlin-server-0 after applying the new image tag.
  • Data is missing: confirm that the pod still mounts dbmarlin-pvc and that the PVC was not deleted or replaced during migration.