Helm is the standard Kubernetes package manager — a single helm install command deploys a complete application stack by rendering and applying a collection of templated Kubernetes manifests called a chart. Beyond basic installation, Helm provides powerful package management workflows: multiple simultaneous releases of the same chart with different configurations, chart dependencies (a parent chart that includes database and cache charts as subcharts), private chart repositories for distributing internal applications, and OCI registry support for storing charts in Docker registries. This guide focuses on advanced Helm usage on RHEL 9 — managing chart dependencies, creating reusable charts with subchart composition, using Helm hooks for pre/post-deployment database migrations, and working with private chart repositories hosted on a self-hosted ChartMuseum or Nexus instance.

Prerequisites

  • Helm 3 installed on RHEL 9 with a working Kubernetes cluster

Step 1 — Chart Dependencies (Subcharts)

# Chart.yaml — define dependencies
apiVersion: v2
name: myapp
version: 1.0.0
dependencies:
  - name: postgresql
    version: "14.x.x"
    repository: https://charts.bitnami.com/bitnami
    condition: postgresql.enabled
  - name: redis
    version: "18.x.x"
    repository: https://charts.bitnami.com/bitnami
# Download dependencies
helm dependency update .
# Creates charts/ directory with downloaded dependency tarballs

# Install with all dependencies
helm install myapp . --namespace production --create-namespace

Step 2 — Helm Hooks (Pre/Post Install)

# templates/db-migration-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
  annotations:
    "helm.sh/hook": pre-upgrade,pre-install        # Run before deployment
    "helm.sh/hook-weight": "-5"                    # Order among hooks
    "helm.sh/hook-delete-policy": hook-succeeded   # Clean up after success
spec:
  template:
    spec:
      restartPolicy: OnFailure
      containers:
      - name: migration
        image: myapp:{{ .Values.image.tag }}
        command: ["node", "migrate.js"]

Step 3 — Private Chart Repository with ChartMuseum

# Deploy ChartMuseum (private Helm repository)
helm install chartmuseum chartmuseum/chartmuseum 
    --namespace tools 
    --set persistence.enabled=true 
    --set env.open.DISABLE_API=false

# Push a chart to ChartMuseum
helm plugin install https://github.com/chartmuseum/helm-push
helm package ./myapp
helm cm-push myapp-1.0.0.tgz chartmuseum

# Add private repo and install from it
helm repo add private https://charts.example.com
helm repo update
helm install myapp private/myapp

Step 4 — Helm with OCI Registries

# Push charts to an OCI registry (Docker Hub, GHCR, Harbor, etc.)
helm registry login registry.example.com
helm push myapp-1.0.0.tgz oci://registry.example.com/helm-charts

# Install from OCI registry
helm install myapp oci://registry.example.com/helm-charts/myapp --version 1.0.0

Conclusion

Advanced Helm on RHEL 9 — subchart dependencies, hooks, and private repositories — enables teams to package, version, and distribute complete application stacks as a single deployable unit. Helm hooks are the correct solution for database migrations in Kubernetes: running migrations as a pre-upgrade hook ensures the database schema is updated before new application pods start receiving traffic, preventing schema mismatch errors during rolling updates. Store Helm charts in a private registry rather than committing generated templates to application repositories — this keeps application code and infrastructure packaging separate, and allows the same application chart to be deployed to multiple clusters.

Next steps: How to Install and Use Helm on RHEL 9, How to Set Up ArgoCD for GitOps on RHEL 9, and How to Install Kubernetes on RHEL 9.