Deploying Container Observability frontend and backend
The frontend and backend components work together to provide visibility into your Kubernetes clusters within the Virtana Platform.
You can use the virtana-co-controller Helm chart for this deployment. The process involves gathering your tenant information, configuring shared settings, and selecting a deployment method such as the Helm CLI, Argo CD, or Terraform.
Get your organization ID and create a DNS record
Before you can define the dataplane frontend DNS name, you need your tenant's organization ID ORG_ID. You'll find it in the keycloakorgsecret secret in the controlplane namespace.
Run the following command to retrieve it:
echo $(kubectl get secret keycloakorgsecret -o jsonpath='{.data.ORG_ID}' -n controlplane | base64 --decode)The command reads the ORG_ID from the Kubernetes secret keycloakorgsecret in namespace controlplane. Base64-decodes it to output the plain-text value of the ORG_ID.
Using that value, create a DNS record in the following format and point it to your ingress-nginx controller's LoadBalancer DNS name or IP address:
<ORG_ID>-oc-<GLOBAL_VIEW_HOSTNAME>
This gives the CO frontend a hostname derived from your organization ID and Global View hostname, making it reachable through your ingress.
Frontend namespace configuration
Configure the FRONTEND_NAMESPACE variable for each backend deployment. This variable identifies the Kubernetes namespace that contains the CO frontend components.
global: frontend: FRONTEND_NAMESPACE: ""
Set this value to the Kubernetes namespace that contains the CO frontend components.
Application monitoring common input file
Create a new file <ORG_ID>-common-values.yaml. This file contains values shared by Frontend and Backend deployments, such as deployment mode, storage class, TLS behavior, registry credentials, frontend settings, Keycloak settings, control plane endpoints, and shared services endpoints.
Self-signed TLS toggles and Docker credentials
Enter the following command to generate self-signed certs when you don’t have valid certs provided by your ingress/LB. Docker registry credentials are used to pull images. It is typically needed for private registries or authenticated Docker Hub access.
create_tls_selfsigned_certs:
kafka: "true"
nodeapp: "true"
dockerRegistryCredentials:
DOCKER_SERVER: "https://index.docker.io/v2/"
DOCKER_USERNAME: "username"
DOCKER_PASSWORD: "password"Field | Description | Default value |
|---|---|---|
| Enables or disables self-signed TLS cert creation for Kafka endpoints. | "true" or "false" |
| Enables or disables self-signed TLS cert creation for Nodeapp endpoints. | "true" or "false" |
DOCKER_SERVER | URL of the Docker registry server. | "https://index.docker.io/v2/" |
DOCKER_USERNAME | Username for authenticating to the Docker registry. | "username" |
DOCKER_PASSWORD | Password or access token used with | "password" |
Container Observability Dataplane Frontend parameters
Configuration specific to the CO Dataplane Frontend to define how it is addressed and how it integrates with Global View.
frontend:
FRONTEND_DNS: <DATAPLANE_FRONTEND_HOSTNAME>
TENANT_NAME: <ORG_ID>
IFRAME: "true"
UI_PARENT_APP_URL: "https://<GLOBAL_VIEW_HOSTNAME>/ui/container/monitoring"
Field | Description | Default value |
|---|---|---|
FRONTEND_DNS | DNS name where the CO Frontend will be reachable. | <DATAPLANE_FRONTEND_HOSTNAME> |
TENANT_NAME | Tenant identifier, set this to your | <ORG_ID> |
IFRAME | Controls iframe-related behavior. | "true" or "false" |
UI_PARENT_APP_URL | Parent UI URL used for navigation. | "https://<GLOBAL_VIEW_HOSTNAME>/ui/container/monitoring" |
Auth provider and control plane endpoints parameters
Keycloak configuration is required for authentication and tenant mapping. Control plane parameters define the response action of the dataplane to the Global View control plane and its Kafka.
keycloak:
HOSTNAME: <KEYCLOAK_HOSTNAME>
ADMIN_USER: "vpadmin"
ADMIN_PASSWORD: "P@ssW0rd@123"
controlplane:
endpoint: "<GLOBAL_VIEW_HOSTNAME>"
kafka_server: "controlplane-infra-kafka.controlplane.svc.cluster.local:9092"Field | Description | Default value |
|---|---|---|
| Keycloak hostname/FQDN. | <KEYCLOAK_HOSTNAME> |
| Keycloak admin username. | "vpadmin" |
| Keycloak admin password. | "P@ssW0rd@123" |
| Global View hostname. | <GLOBAL_VIEW_HOSTNAME> |
| Kafka bootstrap server address for the control plane Kafka. | "controlplane-infra-kafka.controlplane.svc.cluster.local:9092" |
Deploy Frontend
You can deploy the components using your preferred tool. Regardless of the tool, you will deploy the Frontend once and a Backend for every cluster you wish to observe. The Frontend serves as the bridge between your monitored clusters and the Virtana Global View.
Check the latest chart version
Update the Helm repository in your terminal and list available versions of the controller chart:
helm repo update helm search repo virtana-repo/virtana-co-controller
Use this method when you want to deploy the frontend by running Helm commands manually from the command line. You control the chart version, values file, and release lifecycle yourself, which is useful for ad‑hoc installs, troubleshooting, or simple environments without GitOps.
helm upgrade --install opscruise-frontend virtana-repo/virtana-co-controller \ --namespace <first_8_chars_of_org_ID>-frontend --create-namespace \ --set tags.frontend=true \ -f <ORG_ID>-common-values.yaml \ --version <LATEST_VERSION>
Field | Description |
|---|---|
| Namespace uses the first 8 chars of |
| It enables only the frontend parts of the chart. |
Use this approach to manage frontend deployment declaratively through GitOps with Argo CD Applications. Argo CD continuously reconciles the desired state from your Git repository, automatically handling upgrades, rollbacks, drift correction, and namespace creation for the frontend stack. Create a file named virtana-dp-frontend-argo.yaml and apply it to your Argo CD controller. Ensure you set the tags.frontend parameter to true.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: virtana-dp-frontend
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
server: https://kubernetes.default.svc
namespace: <first_8_chars_of_org_ID>-frontend
source:
chart: virtana-co-controller
repoURL: https://virtana.gitlab.io/helm-charts
targetRevision: <LATEST_VERSION>
helm:
releaseName: opscruise-frontend
parameters:
- name: "tags.frontend"
value: "true"
values: |
<contents of ORG_ID-common-values.yaml>
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueField | Description | Default value |
|---|---|---|
| The name of the Argo CD Application object inside the | virtana-dp-frontend |
| The Kubernetes namespace where the Argo CD Application CR itself is created. | argocd |
| Ensures Argo CD deletes the resources it created when you delete this Argo CD Application. | resources-finalizer.argocd.argoproj.io |
| The target Kubernetes API server Argo CD should deploy to the same cluster where Argo CD is running. | https://kubernetes.default.svc |
| The target namespace where Helm resources will be installed. Copy the first 8 characters of the org ID you obtain. | <first_8_chars_of_org_ID>-frontend |
| The Helm chart name to install. | virtana-co-controller |
| The Helm repository URL hosting the chart. | https://virtana.gitlab.io/helm-charts |
| The Helm chart version that Argo CD should install. Provide the latest version. | <LATEST_VERSION> |
| The Helm release name Argo CD will use when installing the chart. | opscruise-frontend |
| Enables the frontend portion of the chart using Helm’s tags mechanism. | |
| Inline Helm values YAML that Argo CD passes to Helm. | Paste the full content of that common input file <ORG_ID>-common-values.yaml. |
| Prevents orphaned resources when chart outputs change. | true |
| For manual changes in a deployed resource in the cluster, Argo CD will revert it to the desired state from Helm. | true |
| If the destination namespace does not exist, Argo CD will create it automatically during sync. | - CreateNamespace=true |
Use this option when you want to provision and manage the frontend as part of a broader, infrastructure‑as‑code workflow. Terraform drives the Helm release, enabling you to version, parameterize, and automate frontend deployments alongside other platform resources in a single, repeatable pipeline. Define a helm_release resource in your Terraform configuration (for example, virtana-dp-frontend.tf). Set the tags.frontend value to true.
resource "helm_release" "frontend" {
create_namespace = true
chart = "virtana-co-controller"
name = "opscruise-frontend"
namespace = "${substr(var.org_id, 0, min(length(var.org_id), 8))}-frontend"
repository = "https://virtana.gitlab.io/helm-charts"
version = var.helm_version
timeout = 600
wait = true
values = [
templatefile("${path.module}/../values/ORG_ID-common-values.yaml", {
deployment_mode = "VP_ONPREM"
storage_class = var.storage_class
docker_password = var.docker_password
docker_username = var.docker_username
frontend_dns = "${var.org_id}-oc-${var.cp_endpoint}"
tenant_name = var.tenant_name
ui_parent_app_url = var.ui_parent_app_url
keycloak_hostname = var.keycloak_hostname
keycloak_password = var.keycloak_password
keycloak_username = var.keycloak_username
global_view_hostname = var.global_view_hostname
})
]
set {
name = "tags.frontend"
value = "true"
}
}Field | Description | Default value |
|---|---|---|
| Instructs Terraform to create the target namespace if it does not already exist. | true |
| The Helm chart name to deploy. | "virtana-co-controller" |
| Helm release name. | "opscruise-frontend" |
| The Kubernetes namespace where the frontend components will be deployed. | "${substr(var.org_id, 0, min(length(var.org_id), 8))}-frontend" |
| URL of the Virtana Helm chart repository. | "https://virtana.gitlab.io/helm-charts" |
| The chart version to install is equivalent to the Helm-based examples. | var.helm_version |
| Maximum time (in seconds) Terraform or Helm will wait for all resources to become ready | 600 |
| Instructs Terraform/Helm to block until all resources are ready before finishing. | true |
| List of values files/content passed to Helm. | |
| Virtana’s charts gate component(s) deploy only frontend modules. |
Cluster values files
Create a per-cluster values file <ORG_ID>-<CLUSTER_NAME>-values.yaml to define cluster-specific parameters.
Run the following command in your values file:
global:
machine_type: small
frontend:
CLUSTER_NAME: "<CLUSTER_NAME>"Field | Description | Default value |
|---|---|---|
| Sizing preset for this backend deployment. It supports small, medium, and large. | small |
| Cluster name used for this backend. | "<CLUSTER_NAME>" |
For OpenShift environments, add:
global:
backend:
BACKEND_PORT: "9093"Field | Description | Default value |
|---|---|---|
global.backend.BACKEND_PORT | Backend service port override. | "9093" |
Deploy Backend
The Deploy Backend step installs a CO backend instance for each monitored Kubernetes cluster. Each backend is deployed into its own namespace using two values files: the shared <ORG_ID>-common-values.yaml for global settings and a per-cluster <ORG_ID>-<CLUSTER_NAME>-values.yaml for cluster-specific configuration, such as machine type and cluster name. The chart tag tags.backend=true ensures only backend components are available. You can deploy via Helm CLI, Argo CD, or Terraform, and repeat the process for each additional cluster by creating a new per-cluster values file and deploying another release into a new namespace.
Enter the following command to deploy a CO backend instance. This approach is well-suited for quick, ad-hoc deployments or environments where a full GitOps or IaC pipeline is not yet in place.
helm upgrade --install opscruise-backend virtana-repo/virtana-co-controller \ --namespace <CLUSTER_NAME> --create-namespace \ --set tags.backend=true \ -f <ORG_ID>-common-values.yaml \ -f <ORG_ID>-<CLUSTER_NAME>-values.yaml \ --version <LATEST_VERSION>
Each backend is deployed into a namespace equal to <CLUSTER_NAME>.
You pass two values files, they are common and per-cluster.
tags.backend=trueenables only backend components.
You can use this approach to manage each backend instance declaratively through an Argo CD Application custom resource. The manifest points to the virtana-co-controller Helm chart, sets tags.backend=true, and inlines the merged contents of both the common and per-cluster values files. Create a file named virtana-dp-CLUSTER_NAME-argo.yaml and apply it to your Argo CD controller. Ensure you set the tags.backend parameter to true.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: virtana-dp-CLUSTER_NAME
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
server: "https://kubernetes.default.svc"
namespace: <CLUSTER_NAME>
source:
chart: virtana-co-controller
repoURL: "https://virtana.gitlab.io/helm-charts"
targetRevision: <LATEST_VERSION>
helm:
releaseName: opscruise-backend
parameters:
- name: "tags.backend"
value: "true"
values: |
<contents of ORG_ID-common-values.yaml + ORG_ID-CLUSTER_NAME-values.yaml>
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueField | Description | Default value |
|---|---|---|
| Unique name of the Argo CD Application. | virtana-dp-CLUSTER_NAME |
| Namespace where the Argo CD Application resource itself is created. | argocd |
| Ensures that when this Argo CD Application is deleted, all Kubernetes resources it manages are also cleaned up. | resources-finalizer.argocd.argoproj.io |
| Target Kubernetes API server. | https://kubernetes.default.svc |
| Target namespace for the backend release. | <CLUSTER_NAME> |
| Name of the Helm chart to deploy from the repository. | virtana-co-controller |
| URL of the Helm chart repository hosting the | https://virtana.gitlab.io/helm-charts |
| Chart version to deploy. Replace with the latest version discovered through | <LATEST_VERSION> |
| Helm release name used for this deployment. | opscruise-backend |
| This enables only the backend components within the |
|
| Inline Helm values (equivalent to -f on the CLI). | <contents of ORG_ID-common-values.yaml + ORG_ID-CLUSTER_NAME-values.yaml> |
| When true, Argo CD automatically deletes Kubernetes resources that are no longer defined in the Helm chart output | true |
| When true, Argo CD automatically re-applies the desired state if someone manually modifies a managed resource in the cluster | true |
| Instructs Argo CD to create the target namespace if it does not already exist. | CreateNamespace=true |
You can use this option to provision and manage each CO backend instance as part of a broader infrastructure-as-code workflow using Terraform's helm_release resource. Terraform renders two values files via templatefile, the shared ORG_ID-common-values.yaml for global settings and a per-cluster ORG_ID-CLUSTER_NAME-values.yaml for cluster-specific parameters like machine type and cluster name, and merges them in order before passing them to Helm.
Define a helm_release resource in your Terraform configuration (for example, virtana-dp-backend.tf). Set the tags.backend value to true.
resource "helm_release" "backend" {
create_namespace = true
chart = "virtana-co-controller"
name = "opscruise-backend"
namespace = var.cluster_name
repository = "https://virtana.gitlab.io/helm-charts"
version = var.helm_version
timeout = 1200
wait = true
values = [
templatefile("${path.module}/../values/ORG_ID-common-values.yaml", {
deployment_mode = "VP_ONPREM"
storage_class = var.storage_class
docker_password = var.docker_password
docker_username = var.docker_username
frontend_dns = "${var.org_id}-oc-${var.cp_endpoint}"
tenant_name = var.tenant_name
ui_parent_app_url = var.ui_parent_app_url
keycloak_hostname = var.keycloak_hostname
keycloak_password = var.keycloak_password
keycloak_username = var.keycloak_username
global_view_hostname = var.global_view_hostname
}),
templatefile("${path.module}/../values/ORG_ID-CLUSTER_NAME-values.yaml", {
machine_type = var.machine_type
cluster_name = var.cluster_name
})
]
set {
name = "tags.backend"
value = "true"
}
}Field | Description | Default value |
|---|---|---|
| Creates the target namespace automatically if it does not already exist. | true |
| Name of the Helm chart to install from the specified repository. | "virtana-co-controller" |
| Helm release name. | "opscruise-backend" |
| Target Kubernetes namespace for the backend release. | var.cluster_name |
| URL of the Helm chart repository hosting the virtana-co-controller chart. | "https://virtana.gitlab.io/helm-charts" |
| Chart version to deploy, controlled by the Terraform variable helm_version. | var.helm_version |
| Maximum time in seconds Terraform will wait for the release to complete before failing. | 1200 |
| When true, Terraform waits for all Kubernetes resources in the release to reach a healthy state before marking the deployment as successful. | true |
| The values list passes two available YAML strings to the Helm chart. The common values and the per-cluster values which are merged in order. | |
| This enables only the backend components within the |
Deploy additional backends
To add more clusters, repeat the following steps:
Create another
<ORG_ID>-<CLUSTER_NAME>-values.yaml. For more details, see Cluster values files.Deploy another backend release targeting the new
<CLUSTER_NAME>namespace. For more details, see Deploy Backend.
Deployment verification
To ensure Container Observability is accessible, perform the following steps:
Open the following URL in a web browser:
https://<GLOBAL_VIEW_HOSTNAME>/ui.Log in using your org email and password.
Navigate to Container Observability > CLUSTER.
Optional settings
The following optional configurations allow you to customize your CO Frontend and Backend deployment beyond the default settings. These include sending telemetry data to Virtana Analytics, using a private image registry, enabling high availability for Nodeapp and CCMongoDB, setting node selectors and tolerations for pod scheduling, and configuring Kafka external service types. Apply any of these settings by adding the relevant configuration block to your <ORG_ID>-common-values.yaml file before deploying or upgrading.
Send data to Virtana Analytics (Matomo)
You can enable a web analytics tool to track and analyze website traffic and behavior.
Perform the following steps:
Enable Virtana Analytics in GlobalView. See Deploying Global View on Virtana Platform.
Add the following configuration to
<ORG_ID>-common-values.yamlfile.global: matomo: url: "https://virtana-analytics.<domain.com>" site_id: "1"
Use a private image registry
Enter the following command to <ORG_ID>-common-values.yaml to use the private image registry.
global: image_registry: example.io
Enable HA for Nodeapp and CCMongoDB
Enabling High Availability (HA) for Nodeapp and CCMongoDB is essential in dynamic Kubernetes environments where nodes can frequently restart or undergo maintenance. Without HA, both Nodeapp and CCMongoDB run as single instances, creating a single point of failure. By enabling HA, multiple replicas of Nodeapp and a MongoDB replica set for CCMongoDB are deployed across different nodes. This results in uninterrupted access to the monitoring UI, improved fault tolerance, and a more resilient production deployment overall.
For existing Nodeapp and CCMongoDB
Perform the following steps:
Download the Backup and Restore script.
curl -o mongodb_dump_restore.sh https://oc-tesla.s3.amazonaws.com/Build/mongodb_dump_restore.sh
Run the backup command.
bash mongodb_dump_restore.sh backup <NAMESPACE>
Deploy CCMongoDB and Nodeapp in HA by adding the following command to
<ORG_ID>-common-values.yaml.For the new Nodeapp and CCMongoDB deployment, you can enable HA directly with this command.
global: frontend: ha_enabled: trueRun the restore command.
bash mongodb_dump_restore.sh restore <NAMESPACE>
Set NodeSelector and Toleration
In Kubernetes, pods are scheduled on any available node by default, which may not always be desirable in production environments where you need to control workload placement for performance, compliance, or resource isolation reasons. NodeSelector allows you to constrain pods to run only on nodes that match specific labels. Tolerations work alongside Kubernetes taints to allow pods to be scheduled on nodes that would otherwise repel them.
Globally for Keycloal, frontend, and backend
Add the following command to <ORG_ID>-common-values.yaml.
global:
nodeSelector:
topology.kubernetes.io/zone: us-east-2a
tolerations:
- effect: NoSchedule
key: cluster_name
operator: Equal
value: stagingFor Keycloak and frontend
Add the following command to <ORG_ID>-common-values.yaml.
global:
frontend:
nodeSelector:
topology.kubernetes.io/zone: us-east-2a
tolerations:
- effect: NoSchedule
key: cluster_name
operator: Equal
value: stagingFor backend
Add the following command to <ORG_ID>-common-values.yaml.
global:
backend:
nodeSelector:
topology.kubernetes.io/zone: us-east-2a
tolerations:
- effect: NoSchedule
key: cluster_name
operator: Equal
value: stagingKafka external service type
Kafka is a core messaging backbone in the CO architecture, responsible for streaming telemetry and metric data between backend components. The Kafka external service type determines how Kafka is exposed outside the Kubernetes cluster, which directly impacts how backend services and external collectors communicate with the Kafka brokers.
LoadBalancer
By default, Kafka is exposed using a LoadBalancer service type, which provisions a cloud-provider-managed load balancer that automatically assigns a stable external IP or DNS endpoint to the Kafka brokers.
Add the following command to <ORG_ID>-common-values.yaml to deploy Kafka with LoadBalancer service type.
global:
kafka_external_service:
type: LoadBalancerNodePort
In environments where a cloud load balancer is not available or not desired, such as on-premises clusters or restricted network setups, Kafka can be exposed using a NodePort service type. NodePort exposes a fixed port on every cluster node, enabling external access to Kafka through any node IP. Since no load balancer provides a stable endpoint, you must explicitly set the BACKEND_DNS parameter to a reachable backend IP or hostname so other CO components can connect to Kafka reliably.
Add the following command to <ORG_ID>-common-values.yaml to deploy Kafka with NodePort service type.
global:
kafka_external_service:
type: NodePort
backend:
BACKEND_DNS: "IP/HOSTNAME"