⚙️ Kubernetes Setup
This guide explains how to deploy a small GermainUX environment on an existing Kubernetes cluster.
Testing environments only
The configuration provided with the Kubernetes distribution is intended for development, evaluation, and testing. It is not a production reference architecture. Production deployments require environment-specific sizing, persistent storage, security, availability, backup, monitoring, and disaster-recovery planning.
🏗️ Architecture
The deployment package generates Kubernetes manifests for three groups of resources:
|
Resource group |
Purpose |
|---|---|
|
|
GermainUX and infrastructure configuration |
|
|
Required infrastructure services and datastores |
|
|
Germain Enterprise and related GermainUX services |
Apply these groups in that order because GermainUX depends on the configuration and infrastructure resources.
📋 Requirements
🤖 Kubernetes cluster
You need:
|
Requirement |
|---|
|
A functioning Kubernetes cluster |
|
Administrative or appropriately scoped cluster permissions |
|
|
|
A default or explicitly configured StorageClass |
|
A container registry accessible from every cluster node |
|
Network connectivity between all required GermainUX components |
|
External access through an Ingress, LoadBalancer, or another approved method |
📊 Example lab capacity
The original test environment used the following cluster settings:
|
Resource |
Example value |
|---|---|
|
Minimum node-group size |
8 |
|
Maximum node-group size |
16 |
|
Desired node-group size |
8 |
|
Node volume type |
GP3 |
|
Minimum CPU |
2 cores |
|
Minimum memory |
4 GB |
|
Minimum disk |
20 GB |
These values reflect a sample lab environment, not guaranteed requirements. Confirm whether CPU, memory, and disk values apply per node in your Kubernetes platform and resize the cluster according to the number of deployed components and expected data volume.
For production sizing, account for:
|
Factor |
|---|
|
Number of monitored users and applications |
|
Incoming telemetry volume |
|
Retention period |
|
Elasticsearch indexing and query workload |
|
Kafka throughput and retention |
|
High-availability requirements |
|
JVM heap requirements |
|
Replication and backup overhead |
|
Expected growth |
📦 Obtain the deployment package
Download the Kubernetes distribution provided for your licensed GermainUX release:
wget <germainux-kubernetes-package-url>
tar xzf germainux-kubernetes-<version>-binary.tar.gz
cd germainux-kubernetes-<version>
Obtain the current package URL and supported component-version matrix from GermainUX Support.
Do not reuse manifests generated by a different GermainUX release without reviewing their compatibility.
🔑 Configure the license
Locate:
<EXTRACTED_FILES>/templates/config/license/
germain.apm.monitoringConfig.systemConfig.license.json
Update the encrypted license value with the license content supplied by Germain Software.
Do not:
-
Commit the license to a public source-code repository.
-
Include it in an unprotected container image.
-
Share it in logs or support material.
-
Store an unencrypted copy in a ConfigMap.
For production deployments, use your organization’s approved Kubernetes secret-management solution whenever the deployment package supports it.
🔧 Configure the deployment
Open:
deploy-germain.sh
Update the deployment variables for the target environment.
A package may contain variables similar to:
elasticSearchVersion="<approved-version>"
mysqlVersion="<approved-version>"
kibanaVersion="<approved-version>"
zookeeperVersion="<approved-version>"
hazelcastVersion="<approved-version>"
kafkaVersion="<approved-version>"
germainVersion="<germainux-version>"
germainApmBuildRegistry="<registry>"
germainEnvName="<environment-name>"
Use only the infrastructure versions approved for the installed GermainUX release.
📪 Messaging compatibility
GermainUX 2024.2 and later uses Kafka. Apache ActiveMQ applies only to earlier releases.
For GermainUX 2024.2 or later:
-
Configure the approved Kafka version.
-
Do not deploy ActiveMQ unless specifically required by Germain Support for an upgrade or compatibility scenario.
For an older GermainUX release, follow that release’s ActiveMQ requirements.
🏷️ Environment name
Set a unique, descriptive environment name:
germainEnvName="germain-qa"
Use different names for development, QA, staging, and production environments. The name may be used to generate directories, resource names, configuration roots, or namespaces.
Avoid changing it after the deployment has been initialized unless you intend to create a separate environment.
🗄️ Configure the database
The deployment can use its packaged database resources or an external database for the GermainUX configuration store.
📦 Packaged database
Retain the database deployment settings supplied with the package and verify that:
-
Persistent storage is configured.
-
The database credentials are protected.
-
The database pod has sufficient memory and storage.
-
Backup and recovery are configured when the environment must be retained.
🌐 External database
When using an external configuration database:
-
Set the packaged MySQL replica count to
0.Older distributions may name this variable:
mysqlReplicase=0Use the exact variable name present in your
deploy-germain.shfile. -
Configure the external database hostname:
germainDbHostname="<database-hostname>" -
Update
common.propertieswith the correct connection details.
Example:
germain.config.url=jdbc:mysql://<database-host>:3306/APMCFG?rewriteBatchedStatements=true
germain.config.username=<database-user>
germain.config.password=<database-password>
Before deployment, confirm that:
-
Kubernetes workloads can resolve and reach the database hostname.
-
The database and schema exist.
-
The configured user has the required permissions.
-
TLS is enabled when required.
-
Firewalls permit the connection.
-
Credentials are stored using the approved secret-management mechanism.
Do not retain the example APMCFG password in a shared or production environment.
📧 Configure email
To enable email alerts and reports, update the SMTP settings in the included common.properties file.
Configure:
|
Setting |
|---|
|
SMTP hostname |
|
SMTP port |
|
Authentication method |
|
Username and password |
|
Sender address |
|
TLS or STARTTLS requirements |
Store SMTP credentials as Kubernetes Secrets whenever supported. Email configuration is optional and can be completed after the initial deployment.
👀 Verify Kubernetes access
Confirm that kubectl targets the correct cluster:
kubectl config current-context
kubectl get nodes
Verify that all required nodes report:
Ready
Also confirm the target namespace:
kubectl get namespaces
Create or select the intended namespace according to the deployment package’s instructions.
Be especially careful when your workstation can access multiple development and production clusters.
📁 Generate the manifests
Run:
chmod +x deploy-germain.sh
./deploy-germain.sh
The script generates Kubernetes YAML files under a directory named after germainEnvName.
Before applying them, review the generated resources for:
|
Resource |
|---|
|
Namespace |
|
Image names and tags |
|
Image-pull secrets |
|
Resource requests and limits |
|
Persistent-volume claims |
|
StorageClass |
|
Services and ports |
|
Ingress or LoadBalancer configuration |
|
ConfigMaps and Secrets |
|
Health checks |
|
Replica counts |
|
Node selectors, tolerations, and affinity |
|
Security contexts |
|
Database and messaging settings |
Do not assume that generated manifests are appropriate for production without review.
🚀 Deploy GermainUX
Apply the generated manifests in the required order.
1️⃣ Configuration
kubectl apply -f <germainEnvName>/configmap/
2️⃣ Infrastructure
kubectl apply -f <germainEnvName>/infra/
Wait for the infrastructure components to become ready before continuing:
kubectl get pods
kubectl get services
kubectl get persistentvolumeclaims
3️⃣ GermainUX components
kubectl apply -f <germainEnvName>/germain/
Monitor the rollout:
kubectl get pods -w
If the manifests use a dedicated namespace, add:
-n <namespace>
to the relevant kubectl commands.
✅ Validate the deployment
👁️ Check pods
kubectl get pods
All required pods should eventually report Running or Completed, as appropriate.
Investigate pods reporting:
Pending
CrashLoopBackOff
ImagePullBackOff
Error
⚙️ Check services
kubectl get services
Confirm that the expected ClusterIP, LoadBalancer, or NodePort services exist.
💾 Check persistent storage
kubectl get persistentvolumeclaims
All required claims should report:
Bound
🐛 Review a failing pod
kubectl describe pod <pod-name>
kubectl logs <pod-name>
For a pod containing multiple containers:
kubectl logs <pod-name> -c <container-name>
For a container that restarted:
kubectl logs <pod-name> --previous
🖥️ Open the GermainUX Workspace
At the end of a successful deployment, the script displays the URL used to access the GermainUX Workspace.
The default path is:
http://<germain-host>:8080/germainapm/workspace/
The actual hostname, protocol, and port depend on the generated Service or Ingress configuration.
An initial test deployment may use:
Username: admin
Password: admin
Change the default password immediately after the first successful sign-in. Do not expose an environment using default credentials to an untrusted network.
🛡️ Production requirements
Before using Kubernetes-hosted GermainUX in production, implement:
|
Requirement |
|---|
|
Appropriately sized resource requests and limits |
|
Multiple replicas for supported stateless components |
|
Pod anti-affinity and topology-spread constraints |
|
Pod disruption budgets |
|
Persistent storage with suitable performance |
|
Database and datastore backups |
|
TLS for external and internal connections |
|
Kubernetes Secrets or an external secret manager |
|
NetworkPolicies |
|
Restricted service accounts and RBAC |
|
Non-root containers where supported |
|
Image vulnerability scanning |
|
Controlled image registries and immutable tags |
|
Readiness, liveness, and startup probes |
|
Centralized logs and metrics |
|
Capacity and disk-usage alerts |
|
Documented upgrade and rollback procedures |
|
Disaster-recovery testing |
The small-cluster configuration described on this page is not sufficient by itself for those requirements.
🔧 Troubleshooting
Pods remain pending
Check:
kubectl describe pod <pod-name>
kubectl get nodes
kubectl get persistentvolumeclaims
Common causes include:
-
Insufficient CPU or memory
-
Unbound persistent-volume claims
-
Node selectors that match no node
-
Missing tolerations
-
Namespace quotas
-
Image-pull secret errors
📦 Image cannot be pulled
Verify:
-
The image name and tag
-
Registry connectivity
-
Registry credentials
-
Image-pull secrets
-
Service-account configuration
-
Node access to the registry
🔗 GermainUX cannot reach an infrastructure service
Confirm:
-
The dependent pod is ready.
-
The Kubernetes Service exists.
-
The configured service hostname is correct.
-
The ports match.
-
NetworkPolicies allow the connection.
-
Authentication and TLS settings match.
-
The components are deployed in the expected namespace.
🚫 Workspace is inaccessible
Check:
kubectl get services
kubectl get ingress
kubectl describe ingress <ingress-name>
Also verify:
-
DNS resolution
-
Load balancer status
-
Ingress controller health
-
Firewall rules
-
TLS certificate configuration
-
Tomcat and Germain Enterprise logs
🔁 Configuration changes are not applied
After changing a source configuration file:
-
Regenerate or update the relevant manifest.
-
Apply it with
kubectl apply. -
Confirm that the ConfigMap or Secret changed.
-
Restart or roll out the affected deployment if it does not reload configuration dynamically.
-
Verify the effective configuration in the application logs.
Source: Kubernetes Setup.
Component: Enterprise
Feature Availability: 2024.1