Helm upgrade guide

[Edit this page](https://github.com/ClickHouse/clickhouse-docs/blob/main/docs/use-cases/observability/clickstack/deployment/oss/helm/v2/helm-upgrade.md)

This guide covers migrating from the inline-template ClickStack Helm chart (v1.x) to the subchart-based architecture (v2.x). This is a **breaking change** that replaces hand-rolled Kubernetes resources with operator-managed custom resources for MongoDB and ClickHouse, and uses the official OpenTelemetry Collector Helm chart.

Breaking Change

The v2.x chart is **not** backwards compatible with v1.x. An in-place `helm upgrade` is not supported. We recommend performing a fresh install alongside the existing deployment and migrating data, rather than attempting an in-place upgrade.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

- Back up your data before upgrading (MongoDB, ClickHouse PVCs)
- Review your current `values.yaml` overrides — most keys have moved or been renamed

## Two-phase installation[​](#two-phase-installation "Direct link to Two-phase installation")

The v2.x chart uses a two-phase install. Operators (which register CRDs) must be installed before the main chart (which creates CRs):

```
# Phase 1: Install operators and CRDs
helm install clickstack-operators clickstack/clickstack-operators

# Phase 2: Install ClickStack
helm install my-clickstack clickstack/clickstack
```

Uninstall in reverse order:

```
helm uninstall my-clickstack
helm uninstall clickstack-operators
```

### Data persistence[​](#data-persistence "Direct link to Data persistence")

PersistentVolumeClaims created by the MongoDB and ClickHouse operators are **not** removed by `helm uninstall`. This is by design to prevent accidental data loss. To clean up PVCs after uninstalling, refer to:

- [MongoDB Kubernetes Operator docs](https://github.com/mongodb/mongodb-kubernetes/tree/master/docs/mongodbcommunity)
- [ClickHouse Operator cleanup docs](https://clickhouse.com/docs/clickhouse-operator/managing-clusters/cleanup)

### Storage class[​](#storage-class "Direct link to Storage class")

`global.storageClassName` and `global.keepPVC` have been removed. Storage class is now configured directly in each operator's CR spec:

```
mongodb:
  spec:
    statefulSet:
      spec:
        volumeClaimTemplates:
          - spec:
              storageClassName: "fast-ssd"

clickhouse:
  keeper:
    spec:
      dataVolumeClaimSpec:
        storageClassName: "fast-ssd"
  cluster:
    spec:
      dataVolumeClaimSpec:
        storageClassName: "fast-ssd"
```

## What changed[​](#what-changed "Direct link to What changed")

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Component Before (v1.x) After (v2.x)|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | MongoDB Inline Deployment + Service + PVC [MongoDB Kubernetes Operator (MCK)](https://github.com/mongodb/mongodb-kubernetes) managing a `MongoDBCommunity` CR| ClickHouse Inline Deployment + Service + ConfigMaps + PVCs [ClickHouse Operator](https://clickhouse.com/docs/clickhouse-operator/overview) managing `ClickHouseCluster` + `KeeperCluster` CRs| OTEL Collector Inline Deployment + Service (`otel.*` block) [Official OpenTelemetry Collector Helm chart](https://github.com/open-telemetry/opentelemetry-helm-charts) (`otel-collector:` subchart)| HyperDX values Flat keys under `hyperdx.*` plus top-level `tasks:` and `appUrl` Reorganized by K8s resource type under `hyperdx.*` (see below)| hdx-oss-v2 Deprecated legacy chart Removed entirely | | | | | | | | | | | | | | | | | |

## HyperDX values reorganization[​](#hyperdx-values-reorganization "Direct link to HyperDX values reorganization")

The `hyperdx:` block is now organized by Kubernetes resource type:

```
hyperdx:
  ports:          # Shared port numbers (Deployment, Service, ConfigMap, Ingress)
    api: 8000
    app: 3000
    opamp: 4320

  frontendUrl: "http://localhost:3000"   # Replaces the removed appUrl

  config:         # → clickstack-config ConfigMap (non-sensitive env vars)
    APP_PORT: "3000"
    HYPERDX_LOG_LEVEL: "info"

  secrets:        # → clickstack-secret Secret (sensitive env vars)
    HYPERDX_API_KEY: "..."
    CLICKHOUSE_PASSWORD: "otelcollectorpass"
    CLICKHOUSE_APP_PASSWORD: "hyperdx"
    MONGODB_PASSWORD: "hyperdx"

  deployment:     # K8s Deployment spec (image, replicas, probes, etc.)
  service:        # K8s Service spec (type, annotations)
  ingress:        # K8s Ingress spec (host, tls, annotations)
  podDisruptionBudget:  # K8s PDB spec
  tasks:          # K8s CronJob specs (previously top-level tasks:)
```

### Key moves[​](#key-moves "Direct link to Key moves")

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Before (v1.x) After (v2.x)|  |  |  |  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | `appUrl` Removed. Use `hyperdx.frontendUrl` (defaults to `http://localhost:3000`)| `tasks.*` (top-level) `hyperdx.tasks.*`| `mongodb.password` `hyperdx.secrets.MONGODB_PASSWORD`| `clickhouse.config.users.appUserPassword` `hyperdx.secrets.CLICKHOUSE_APP_PASSWORD`| `clickhouse.config.users.otelUserPassword` `hyperdx.secrets.CLICKHOUSE_PASSWORD`| `otel.*` env overrides `hyperdx.config.*` (non-sensitive) and `hyperdx.secrets.*` (sensitive) | | | | | | | | | | | | | |

### Unified ConfigMap and Secret[​](#unified-configmap-and-secret "Direct link to Unified ConfigMap and Secret")

All environment variables now flow through two static-named resources that are shared by the HyperDX Deployment **and** the OTEL Collector via `envFrom`:

- **`clickstack-config`** ConfigMap — populated from `hyperdx.config`
- **`clickstack-secret`** Secret — populated from `hyperdx.secrets`

There is no longer a separate OTEL-specific ConfigMap. Both workloads read from the same sources.

## MongoDB migration[​](#mongodb-migration "Direct link to MongoDB migration")

### Removed values[​](#mongodb-removed-values "Direct link to Removed values")

The following `mongodb.*` values no longer exist:

```
# REMOVED — do not use
mongodb:
  image: "..."
  port: 27017
  strategy: ...
  nodeSelector: {}
  tolerations: []
  livenessProbe: ...
  readinessProbe: ...
  persistence:
    enabled: true
    dataSize: 10Gi
```

### New values[​](#mongodb-new-values "Direct link to New values")

MongoDB is now managed by the MCK operator via a `MongoDBCommunity` custom resource. The CR spec is rendered verbatim from `mongodb.spec`:

```
mongodb:
  enabled: true
  spec:
    members: 1
    type: ReplicaSet
    version: "5.0.32"
    security:
      authentication:
        modes: ["SCRAM"]
    users:
      - name: hyperdx
        db: hyperdx
        passwordSecretRef:
          name: '{{ include "clickstack.mongodb.fullname" . }}-password'
        roles:
          - name: dbOwner
            db: hyperdx
          - name: clusterMonitor
            db: admin
        scramCredentialsSecretName: '{{ include "clickstack.mongodb.fullname" . }}-scram'
    additionalMongodConfig:
      storage.wiredTiger.engineConfig.journalCompressor: zlib
```

The MongoDB password is set in `hyperdx.secrets.MONGODB_PASSWORD` (not `mongodb.password`). It is referenced automatically by the password Secret and the `mongoUri` template.

To add persistence, add a `statefulSet` block inside `mongodb.spec`:

```
mongodb:
  spec:
    statefulSet:
      spec:
        volumeClaimTemplates:
          - metadata:
              name: data-volume
            spec:
              accessModes: ["ReadWriteOnce"]
              storageClassName: "your-storage-class"
              resources:
                requests:
                  storage: 10Gi
```

The MCK operator subchart is configured under `mongodb-operator:` (not `mongodb-kubernetes:`). See the [MCK documentation](https://github.com/mongodb/mongodb-kubernetes/tree/master/docs/mongodbcommunity) for all available CRD fields.