Grafana Community Helm Charts

repository·main·Indexed 42 days ago

https://github.com/grafana-community/helm-charts

Kubernetes Helm charts for various Grafana Community projects, including the core Grafana and grafana-mcp charts. Provides documentation on installation via OCI and HTTP registries, configuration via grafana.ini, and dynamic provisioning of dashboards, datasources, notifiers, and alerting resources using sidecar containers.

Tokens
17.4K
Snippets
68
Records
89
Agent score
54%

What's inside Grafana Community Helm Charts

  1. Scale down live-stores safely

    main

    Scaling down liveStore.replicas reduces the number of Kafka partitions managed. To prevent data loss or service interruption, use the following opt-in settings which require the rollout-operator admission webhooks:

    1. noDownscale: true: Rejects any scale-down attempt of the live-stores.
    2. prepareDownscale.enabled: true: Coordinates a staggered scale-down. It moves a partition to INACTIVE to stop writes, then waits for minTimeBetweenZonesDownscale before allowing the next zone to scale down. This ensures the read path remains intact until the last zone is removed.
    liveStore:
      zoneAwareReplication:
        prepareDownscale:
          enabled: true
          minTimeBetweenZonesDownscale: 12h
  2. Follow versioning and breaking change guidelines

    main

    All charts must follow Semantic Versioning (SemVer) in the format MAJOR.MINOR.PATCH.

    • Bumping Versions: The version field in Chart.yaml must be incremented for every release.
    • Breaking Changes: If a change is backwards-incompatible, you must bump the MAJOR version. Additionally, you must add a ### X.0.0 subsection under the ## Upgrading heading in the chart's README to document the breaking change.
  3. Understand Loki StatefulSet immutability and updates

    main

    Most fields in a Kubernetes StatefulSet are immutable. Changing certain configuration values in your values.yaml will not take effect via a standard helm upgrade unless specific conditions are met.

    Immutable Fields (Requires manual intervention or recreation)

    The following fields cannot be updated via standard upgrade and are not covered by the experimental recreate job:

    • *.persistence.storageClass
    • *.persistence.claims[].storageClass
    • *.persistence.accessModes
    • *.persistence.selector
    • *.persistence.volumeAttributesClassName
    • *.persistence.annotations
    • Chart-generated selector labels

    Fields covered by the Recreate Job

    If you enable the experimental recreate job, you can update certain fields. The job deletes the StatefulSet with --cascade=orphan to allow the new spec to take effect.

    Supported updates via Recreate Job:

    • *.persistence.size (and cache persistence.storageSize)
    • *.podManagementPolicy
    • serviceName (affected by nameOverride or fullnameOverride)
    • Volume-claim count, claim name, or claim size (if defaults.statefulSetRecreateJob.patchPVC is true)

    Note: The recreate job does not work for Memcached cache StatefulSets.

  4. How zone-aware replication works for the live-store

    main

    In a standard configuration, the live-store is a single flat StatefulSet where each Kafka partition has exactly one live-store instance. If that pod fails, recent-trace queries for that partition fail.

    Zone-aware replication solves this by rendering one StatefulSet per zone. Each zone runs a full set of live-stores and consumes Kafka partitions independently. This ensures that the loss of a single zone does not break recent-trace queries.

    Key requirements and behaviors:

    • Rollout Operator: The chart requires a rollout_operator to coordinate rollouts and manage ZoneAwarePodDisruptionBudget. The chart will refuse to render without it.
    • Replicas: liveStore.replicas must equal the Kafka partition count. This value represents the size of one zone, not the total count across all zones.
    • Topology: Use topologyKey (e.g., topology.kubernetes.io/zone) to ensure anti-affinity. At least 2 zones are required.
    • Switching on: Enabling zone-awareness replaces the flat StatefulSet with per-zone ones. This causes all live-stores to restart and requires them to replay the Kafka lookback period to rebuild state. Plan this as a full live-store restart.
    rollout_operator:
      enabled: true
    
    liveStore:
      enabled: true
      replicas: 3  # partitions per zone; must equal the Kafka partition count
      zoneAwareReplication:
        enabled: true
        topologyKey: topology.kubernetes.io/zone
        zones:
          - name: zone-a
            nodeSelector:
              topology.kubernetes.io/zone: eu-west-1a
          - name: zone-b
            nodeSelector:
              topology.kubernetes.io/zone: eu-west-1b
  5. Use the Dashboard Sidecar for dynamic dashboard loading

    main

    When sidecar.dashboards.enabled is set to true, a sidecar container is deployed to watch ConfigMaps or Secrets in the cluster. It filters resources based on the label defined in sidecar.dashboards.label.

    Files within the matching ConfigMaps/Secrets are written to a folder accessible by Grafana. Changes to the ConfigMap/Secret trigger updates or deletions in Grafana.

    Recommendation: Use one ConfigMap per dashboard to ensure proper mirroring.

    Example ConfigMap

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: sample-grafana-dashboard
      labels:
        grafana_dashboard: "1"
    data:
      k8s-dashboard.json: |- 
        # Dashboard JSON content here
  6. Use recommended Kubernetes labels and selectors

    main

    When writing templates, follow these labeling standards:

    • Standard Labels: Use the recommended app.kubernetes.io/* labels (e.g., app.kubernetes.io/name, app.kubernetes.io/instance).
    • Selector Immutability: Do not include helm.sh/chart in spec.selector.matchLabels. Because Kubernetes selectors are immutable after creation, including the chart version in the selector will prevent successful upgrades.
  7. Manage node draining with ZoneAwarePodDisruptionBudget

    main

    When using zone-aware replication, standard PodDisruptionBudgets (PDB) are insufficient because they cannot express that an eviction should be coordinated across zones per partition.

    The chart renders a ZoneAwarePodDisruptionBudget enforced by the rollout-operator. This budget ensures that a drain takes at most maxUnavailable live-stores per partition across all zones, preventing the last owner of a partition from being evicted.

    If your live-stores use the default readiness-target-lag of 0, you should set crossZoneEvictionDelay to allow time for the live-store to finish replaying its partition before it is considered ready.

    liveStore:
      zoneAwareReplication:
        podDisruptionBudget:
          enabled: true
          maxUnavailable: 1
    
    # If using default readiness-target-lag of 0:
    # liveStore.zoneAwareReplication.podDisruptionBudget.crossZoneEvictionDelay: 20m
  8. Use the Datasource Sidecar for dynamic datasource provisioning

    main

    When sidecar.datasources.enabled is set to true, an init container is deployed. It watches Secrets (recommended) or ConfigMaps for resources matching the label in sidecar.datasources.label. The files are written to a folder and imported into Grafana on startup.

    Reloading Datasources: To reload datasources automatically when a Secret changes, set sidecar.datasources.skipReload: false and provide a sidecar.datasources.reloadURL (e.g., http://<svc-name>.<namespace>.svc.cluster.local/api/admin/provisioning/datasources/reload).

    Example Secret for Postgres Datasource

    apiVersion: v1
    kind: Secret
    metadata:
      name: grafana-datasources
      labels:
        grafana_datasource: 'true'
    stringData:
      pg-db.yaml: |
        apiVersion: 1
        datasources:
          - name: My pg db datasource
            type: postgres
            url: my-postgresql-db:5432
            user: db-readonly-user
            secureJsonData:
              password: 'SUperSEcretPa$$word'
            jsonData:
              database: my_datase
              sslmode: 'disable'
            editable: false
  9. Configure Tempo Distributed components

    main

    The tempo-distributed Helm chart installs a set of core components by default, while other specialized components are optional and must be explicitly enabled via their respective enabled flags.

    Always Installed:

    • distributor: Writes spans to Kafka in Tempo 3.0.
    • querier: Handles query execution.
    • query-frontend: Manages query requests.

    Optional Components: To use these, you must set their enabled key to true in your values.yaml:

    • backend-scheduler (backendScheduler.enabled): Required for compaction and retention.
    • backend-worker: Automatically enabled when backend-scheduler is active; executes compaction jobs.
    • block-builder (blockBuilder.enabled): Consumes from Kafka and writes blocks to object storage.
    • live-store (liveStore.enabled): Consumes from Kafka and serves recent-data queries.
    • metrics-generator: Generates metrics from traces.
    • memcached: Provides caching.
    • memcached-exporter: Exports metrics for Memcached.
    • gateway: Provides an entry point for requests.
    • rollout-operator: Manages rollout processes.
    # Example enabling optional components
    backendScheduler:
      enabled: true
    blockBuilder:
      enabled: true
    liveStore:
      enabled: true
    metricsGenerator:
      enabled: true
  10. Upgrade Tempo Chart from versions < 0.7.0

    main

    Upgrading from versions older than 0.7.0 changes the default trace storage path from /tmp/tempo/traces to /var/tempo/traces.

    Warning: This change will cause Tempo to lose trace history. To retain history, manually copy the contents from the old folder to the new folder before upgrading.

  11. Migrate or retain built-in MinIO during upgrade

    main

    The built-in MinIO subchart has been removed in Tempo 3.0. Setting minio.enabled: true will now cause a render failure.

    Option 1: Migrate to external S3 storage

    Deploy MinIO (or another S3-compatible store) separately and configure Tempo via storage.trace.s3.

    Option 2: Keep existing built-in MinIO running (Manual Detachment)

    If you used minio.enabled: true, a standard helm upgrade will delete the MinIO resources and your data. To prevent this, you must annotate the MinIO resources with helm.sh/resource-policy: keep to detach them from the Helm release before upgrading.

    1. Annotate resources:
    # RELEASE and NAMESPACE are your existing tempo-distributed install.
    for kind in deployment service secret pvc serviceaccount; do
      kubectl -n "$NAMESPACE" annotate "$kind" \
        -l app=minio,release="$RELEASE" \
        helm.sh/resource-policy=keep --overwrite
    done
    1. Verify annotations (especially on the PVC):
    kubectl -n "$NAMESPACE" get deploy,svc,secret,pvc,sa -l app=minio,release="$RELEASE" \
      -o jsonpath='{range .items[*]}{.kind}/{.metadata.name}: {.metadata.annotations.helm\.sh/resource-policy}{"\n"}{end}'
    1. Update values: Remove the minio: block and point Tempo to the surviving MinIO service using the storage.trace.s3 configuration.