Skip to content

PuppyGraph Helm Chart Installation Guide

This guide walks you through installing PuppyGraph using Helm Charts. Before you start, check the System Requirements. For the cluster architecture the chart provisions, the configuration knobs it exposes, scaling, and upgrades, see Cluster Deployment.

The chart has two deployment modes. The default, cluster, deploys separate controlplane, leader and compute pods and is the recommended production topology. single-node deploys one pod running all of PuppyGraph, the same topology as Launching PuppyGraph in Docker, for evaluation, development and small on-premises installs; see Single-Node Deployment.

Install Helm

Helm is a package manager for Kubernetes that simplifies deployment and management of applications. Install Helm by following the instructions for your operating system:

# macOS (Homebrew)
brew install helm

# Linux (via script)
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Windows (Chocolatey)
choco install kubernetes-helm

For more installation details, refer to the official guide: Installing Helm

Verify Helm installation:

Run:

helm version
If the command executes successfully and outputs version information such as version.BuildInfo, Helm is installed correctly.


Add the PuppyGraph Helm Repository

Add the PuppyGraph Helm repository to access the latest charts:

# Add PuppyGraph Helm repository
helm repo add puppygraph https://puppygraph.github.io/puppygraph-helm-chart/

# Update local Helm chart repository cache
helm repo update

Custom Deployment Guide

Deploy PuppyGraph on any Kubernetes cluster by customizing configuration values.

Deploying to production?

Pin the PuppyGraph image to a release. See Pin the Image for Production.

Generate Default Values

# Generate default values file
helm show values puppygraph/puppygraph > values.yaml

A sample of the key components of the default values file is shown below:

nameOverride: ""

# "cluster" deploys the controlplane, leader and compute StatefulSets described in
# https://docs.puppygraph.com/installation/cluster-deployment/.
# "single-node" deploys one pod running all of PuppyGraph, the same topology as the Docker
# quick start. It is not highly available. Configure it under singleNode, service.singleNode
# and env.singleNode; controlplane, leader, compute and query settings are not used.
# A live release cannot be switched between modes with helm upgrade: uninstall it first.
deploymentMode: cluster

image:
  repository: docker.io/puppygraph/puppygraph
  pullPolicy: Always
  # PuppyGraph image tag to deploy; leave empty to use Chart.appVersion.
  # In production, pin a specific version (e.g. "1.0.0").
  # Available tags: https://hub.docker.com/r/puppygraph/puppygraph/tags
  tag: "latest"

imagePullSecret: ""

rootless: false

serviceAccount:
  create: false
  automount: true
  annotations: {}
  name: "default"

# additional node selectors
nodeSelectors:
  # cloud.google.com/machine-family: "c3d"

# service customizations
service:
  controlplane:
    # Set to LoadBalancer to expose the web UI externally (may incur cloud costs).
    type: ClusterIP
    # Optional LoadBalancer class, for example "service.k8s.aws/nlb" for AWS Load Balancer Controller.
    # Only used when type is LoadBalancer.
    loadBalancerClass: ""
    annotations: {}
  query:
    # Set to LoadBalancer to expose the query service externally (may incur cloud costs).
    type: ClusterIP
    # Optional LoadBalancer class, for example "service.k8s.aws/nlb" for AWS Load Balancer Controller.
    # Only used when type is LoadBalancer.
    loadBalancerClass: ""
    annotations: {}
  # single-node mode only: one service for the web UI (8081), Gremlin (8182) and Bolt (7687).
  singleNode:
    # Set to LoadBalancer to expose the service externally (may incur cloud costs).
    type: ClusterIP
    # Optional LoadBalancer class, for example "service.k8s.aws/nlb" for AWS Load Balancer Controller.
    # Only used when type is LoadBalancer.
    loadBalancerClass: ""
    annotations: {}
  leader:
    annotations: {}
  compute:
    annotations: {}

# Please refer to "System Requirements" in PuppyGraph docs. https://docs.puppygraph.com/installation/

# resource for controlplane node (web UI and registry)
controlplane:
  replicas: 1

  # Controlplane readiness probe tuning.
  # Increase initialDelaySeconds/timeoutSeconds/failureThreshold when startup
  # phases are heavy and may briefly fail health checks.

  # readinessProbe:
  #   # Set to false to disable rendering readinessProbe for controlplane pods.
  #   enabled: true
  #   # Wait time before the first probe after container starts.
  #   initialDelaySeconds: 30
  #   # Maximum time for one probe request before it is treated as failed.
  #   timeoutSeconds: 3
  #   # Probe interval.
  #   periodSeconds: 10
  #   # Consecutive failures required to mark the pod Unready.
  #   failureThreshold: 5

  # inject extra Kubernetes PodSpec fields into spec.template.spec
  extraPodSpec: {}
  # inject extra fields into the controlplane container spec
  # examples: securityContext, lifecycle, livenessProbe, startupProbe
  # NOTE: these fields are rendered after chart defaults and may override resources,
  # readinessProbe, lifecycle, and securityContext.
  extraContainerSpec: {}
  # workload-targeted pod annotations rendered into spec.template.metadata.annotations
  # (not on the StatefulSet metadata). Use for things that must live on the pod
  # template, e.g. Datadog Agent Kubernetes autodiscovery (ad.datadoghq.com/...).
  podAnnotations: {}
  # override controlplane image; inherit from global image when empty
  image:
    repository: ""
    pullPolicy: ""
    tag: ""
  resources:
    requests:
      cpu: "2"
      memory: "4Gi"
    limits:
      memory: "4Gi"
  storage:
    size: "10Gi"

# resource for leader nodes
leader:
  replicas: 3

  # Leader readiness probe tuning.
  # Increase initialDelaySeconds/timeoutSeconds/failureThreshold when startup,
  # scaling, or indexing phases are heavy and may briefly fail health checks.

  # readinessProbe:
  #   # Set to false to disable rendering readinessProbe for leader pods.
  #   enabled: true
  #   # Wait time before the first probe after container starts.
  #   initialDelaySeconds: 30
  #   # Maximum time for one probe request before it is treated as failed.
  #   timeoutSeconds: 3
  #   # Probe interval.
  #   periodSeconds: 10
  #   # Consecutive failures required to mark the pod Unready.
  #   failureThreshold: 5

  # inject extra Kubernetes PodSpec fields into spec.template.spec
  # examples: affinity, tolerations, topologySpreadConstraints, hostAliases, priorityClassName
  # NOTE: these fields are rendered after chart defaults and may override securityContext,
  # serviceAccountName, imagePullSecrets, and nodeSelector.
  extraPodSpec: {}
  # inject extra fields into the leader container spec
  # examples: securityContext, lifecycle, livenessProbe, startupProbe
  # NOTE: these fields are rendered after chart defaults and may override resources,
  # readinessProbe, lifecycle, and securityContext.
  extraContainerSpec: {}
  # workload-targeted pod annotations rendered into spec.template.metadata.annotations
  # (not on the StatefulSet metadata). Use for things that must live on the pod
  # template, e.g. Datadog Agent Kubernetes autodiscovery (ad.datadoghq.com/...).
  podAnnotations: {}
  # override leader image; inherit from global image when empty
  image:
    repository: ""
    pullPolicy: ""
    tag: ""
  resources:
    requests:
      cpu: "8"
      memory: "32Gi"
      ephemeral-storage: "10Gi"
    limits:
      memory: "32Gi"

# resource for compute nodes
compute:
  replicas: 3

  # Compute readiness probe tuning.
  # Increase initialDelaySeconds/timeoutSeconds/failureThreshold when startup
  # phases are heavy and may briefly fail health checks.

  # readinessProbe:
  #   # Set to false to disable rendering readinessProbe for compute pods.
  #   enabled: true
  #   # Wait time before the first probe after container starts.
  #   initialDelaySeconds: 30
  #   # Maximum time for one probe request before it is treated as failed.
  #   timeoutSeconds: 3
  #   # Probe interval.
  #   periodSeconds: 10
  #   # Consecutive failures required to mark the pod Unready.
  #   failureThreshold: 5

  # inject extra Kubernetes PodSpec fields into spec.template.spec
  # examples: affinity, tolerations, topologySpreadConstraints, hostAliases, priorityClassName
  # NOTE: these fields are rendered after chart defaults and may override securityContext,
  # serviceAccountName, imagePullSecrets, and nodeSelector.
  extraPodSpec: {}
  # inject extra fields into the compute container spec
  # examples: securityContext, lifecycle, livenessProbe, startupProbe
  # NOTE: these fields are rendered after chart defaults and may override resources,
  # readinessProbe, lifecycle, and securityContext.
  extraContainerSpec: {}
  # workload-targeted pod annotations rendered into spec.template.metadata.annotations
  # (not on the StatefulSet metadata). Use for things that must live on the pod
  # template, e.g. Datadog Agent Kubernetes autodiscovery (ad.datadoghq.com/...).
  podAnnotations: {}
  # override compute image; inherit from global image when empty
  image:
    repository: ""
    pullPolicy: ""
    tag: ""
  resources:
    requests:
      cpu: "8"
      memory: "64Gi"
      ephemeral-storage: "10Gi"
    limits:
      memory: "64Gi"

# single-node mode only: the one pod that runs the controlplane, query engine and storage.
singleNode:

  # Single-node readiness probe tuning.
  # Increase initialDelaySeconds/timeoutSeconds/failureThreshold when startup
  # phases are heavy and may briefly fail health checks.

  # readinessProbe:
  #   # Set to false to disable rendering readinessProbe for the single-node pod.
  #   enabled: true
  #   # Wait time before the first probe after container starts.
  #   initialDelaySeconds: 30
  #   # Maximum time for one probe request before it is treated as failed.
  #   timeoutSeconds: 3
  #   # Probe interval.
  #   periodSeconds: 10
  #   # Consecutive failures required to mark the pod Unready.
  #   failureThreshold: 5

  # Liveness probe on the controlplane (port 8081). The container keeps running if the
  # controlplane process exits, so this is what restarts a pod whose Web UI has died.

  # livenessProbe:
  #   # Set to false to disable rendering livenessProbe for the single-node pod.
  #   enabled: true
  #   initialDelaySeconds: 30
  #   timeoutSeconds: 3
  #   periodSeconds: 10
  #   # Consecutive failures required to restart the container.
  #   failureThreshold: 6

  # inject extra Kubernetes PodSpec fields into spec.template.spec
  # examples: affinity, tolerations, hostAliases, priorityClassName
  # NOTE: these fields are rendered after chart defaults and may override securityContext,
  # serviceAccountName, imagePullSecrets, and nodeSelector.
  extraPodSpec: {}
  # inject extra fields into the single-node container spec
  # examples: securityContext, lifecycle, livenessProbe, startupProbe
  # NOTE: these fields are rendered after chart defaults and may override resources,
  # readinessProbe, lifecycle, and securityContext.
  extraContainerSpec: {}
  # workload-targeted pod annotations rendered into spec.template.metadata.annotations
  # (not on the StatefulSet metadata).
  podAnnotations: {}
  # override single-node image; inherit from global image when empty
  image:
    repository: ""
    pullPolicy: ""
    tag: ""
  # Minimums enforced by the chart: 2 CPU and 8Gi memory.
  resources:
    requests:
      cpu: "4"
      memory: "16Gi"
    limits:
      memory: "16Gi"
  storage:
    # Persistent volume mounted at /data: registry, graph metadata and cached data.
    # The StorageClass comes from storage.name / storage.provisioner below. Minimum 20Gi.
    size: "50Gi"

# define data storage
# if provisioner is not provided, will use preset storage class by name
# other key value pairs are parameters compatible with the provisioner
storage:
  name: ""
  size: "200Gi"
  provisioner: ""
  type: ""

env:
  # applied to every PuppyGraph pod: controlplane, leader and compute in cluster mode, the
  # single-node pod in single-node mode
  common:
    PRIORITY_IP_CIDR: ""
  # applied to controlplane pods only
  controlplane:
    # The chart sets DATAACCESS_DATA_REPLICATIONNUM (data replicas for PuppyGraph
    # metadata and local storage) to "3" on controlplane and leader pods. For a single
    # compute node, set it to "1" under both env.controlplane and env.leader.
    # DATAACCESS_DATA_REPLICATIONNUM: "3"
  # applied to leader pods only
  leader:
    # DATAACCESS_DATA_REPLICATIONNUM: "3"
  # applied to the single-node pod only, after env.common. env.controlplane and env.leader
  # are not applied in single-node mode.
  singleNode: {}

# these files will be mounted to /etc/config/puppygraph/
config:
  # Built-in schema content. Set via --set-file config.presetSchema=/path/to/puppygraph-schema.json
  # This will be mounted as /etc/config/puppygraph/schema.json
  presetSchema: ""
  # additional files to mount: map of filename -> file content
  # can be set via --set-file config.files.key\\.json=/path/to/key.json
  files: {}

# If existingSecretName is set, use that Secret and skip creating a new one.
# If `create` is true and existingSecretName is empty, create a Secret from values below.
# `PUPPYGRAPH_USERNAME` and `PUPPYGRAPH_PASSWORD` are for login puppygraph.
# `AUTHENTICATION_JWT_SECRETKEY` is for JWT token signing between controlplane and other nodes.
# More secrets may be needed by schema as environment variables and we can set them here.
secrets:
  existingSecretName: ""
  create: true
  PUPPYGRAPH_USERNAME: "puppygraph"
  PUPPYGRAPH_PASSWORD: "puppygraph123"
  AUTHENTICATION_JWT_SECRETKEY: ""
  # SOME_OTHER_KEY:

Customize Configuration

Edit values.yaml to match your environment. Key configurations include:

  • Image Version: To deploy a specific version of PuppyGraph, update the image.tag field in your values.yaml. For production, see Pin the Image for Production.

    Example for specifying PuppyGraph version

    image:
      repository: docker.io/puppygraph/puppygraph
      tag: latest
      pullPolicy: Always
    
    To find out the latest versions, please check released PuppyGraph versions.

    To install a specific chart version, pass an explicit version:

    helm install $RELEASE_NAME puppygraph/puppygraph --version <chart-version>
    
  • Network CIDR: Set env.common.PRIORITY_IP_CIDR to match your cluster node IP range.

    Check Node IP Range

    Before deployment, check your node internal IPs to configure the network correctly:

    kubectl get nodes -o wide
    

  • Storage Size: Adjust storage.size based on data requirements (default: 50Gi).

    Storage Auto-Detection

    If you don't specify storage.provisioner and storage.type, the chart will automatically use the default storage class configured in your Kubernetes cluster.

  • Resources: Adjust CPU and memory requests/limits based on cluster capacity.

  • Replicas: Set appropriate replica counts for leader and compute pods.
  • Environment Variables: Configure PuppyGraph-specific settings under env.*.

Pin the Image for Production

The chart's default image is puppygraph/puppygraph:latest, with pullPolicy: Always. That is fine for evaluation, but latest is a moving tag. Each pod pulls whatever latest points to when it starts. Once the tag is moved, a restarted pod can come up on a different version than the rest of the deployment. No helm upgrade is involved.

In production, pin the image to a fixed release version.

To upgrade a cluster deployment, move each role to the new release in turn. Follow the order in Image upgrade: controlplane, then compute, then leaders. Check each step before you start the next. Do not change only the global image.tag in one helm upgrade. That upgrades every role at the same time.

In single-node mode, change image.tag and run helm upgrade.

Pin a release tag

Set image.tag to a release version. Replace <release-version> below with the version you deploy. The release notes list the released versions.

image:
  repository: docker.io/puppygraph/puppygraph
  tag: "<release-version>"
  pullPolicy: IfNotPresent

If you set leader.image, compute.image, controlplane.image or singleNode.image, pin those tags too. They override image for their own pods.

Pin a digest

A tag can be moved to a different image. A digest cannot. To make sure every pod runs the exact same image, add the digest to the tag.

Look up the digest of the release:

export PUPPYGRAPH_VERSION=<release-version>

docker buildx imagetools inspect docker.io/puppygraph/puppygraph:$PUPPYGRAPH_VERSION

The output has a line like Digest: sha256:.... Copy the value after Digest:, starting with sha256:. Put it in image.tag, after the version and an @:

image:
  repository: docker.io/puppygraph/puppygraph
  tag: "<release-version>@<digest>"
  pullPolicy: IfNotPresent

The chart builds the image reference as <repository>:<tag>. Kubernetes pulls the image by its digest. The version in front of the @ is only a label.

Use a private registry mirror

Copy the release into your own registry, with PUPPYGRAPH_VERSION set as shown above:

docker buildx imagetools create \
  --tag registry.example.com/puppygraph/puppygraph:$PUPPYGRAPH_VERSION \
  docker.io/puppygraph/puppygraph:$PUPPYGRAPH_VERSION

Look up the digest in your registry, as shown above, with your registry's image name.

Create a pull secret in the namespace you deploy to. Use the same namespace when you deploy the chart.

export NAMESPACE=default

# Only if the namespace does not exist yet
kubectl create namespace $NAMESPACE

kubectl create secret docker-registry puppygraph-registry \
  --namespace $NAMESPACE \
  --docker-server=registry.example.com \
  --docker-username=<username> \
  --docker-password=<password>

Point the chart at the mirror and the secret:

image:
  repository: registry.example.com/puppygraph/puppygraph
  tag: "<release-version>@<digest>"
  pullPolicy: IfNotPresent

imagePullSecret: puppygraph-registry

imagePullSecret takes the name of one secret. The chart adds it to every PuppyGraph pod.

Deploy with Custom Configuration

# Set environment variables
export RELEASE_NAME=puppygraph-test
export NAMESPACE=default

# Deploy with custom configuration
helm upgrade --install $RELEASE_NAME puppygraph/puppygraph \
  --namespace $NAMESPACE \
  --create-namespace \
  -f values.yaml

Override Specific Values

You can also override specific values without editing the file using --set flags:

helm upgrade --install $RELEASE_NAME puppygraph/puppygraph \
    -f values.yaml \
    --set leader.replicas=3 \
    --set compute.replicas=3

Verify Deployment

# Check pod status
kubectl get pods -n $NAMESPACE

# Check persistent volumes
kubectl get pvc -n $NAMESPACE

# Check services
kubectl get svc -n $NAMESPACE

Access PuppyGraph

The chart deploys four services:

  • $RELEASE_NAME-controlplane-service exposes the Web UI (port 8081) and the controlplane gRPC endpoint (port 8082). Configurable via service.controlplane.type (default ClusterIP).
  • $RELEASE_NAME-query-service exposes the openCypher Bolt endpoint (port 7687). Configurable via service.query.type (default ClusterIP).
  • $RELEASE_NAME-leader-service is a headless service used for inter-leader communication; it also exposes the Gremlin port (8182) for direct Gremlin access.
  • $RELEASE_NAME-compute-service is a headless service used for inter-cluster communication.

To access the Web UI locally, port-forward the controlplane service:

kubectl -n $NAMESPACE port-forward --address 0.0.0.0 svc/$RELEASE_NAME-controlplane-service 8081:8081

Then open http://localhost:8081 in your browser. See PuppyGraph Web UI for a tour of the pages, and Monitoring for the health-check and metrics endpoints to wire into your monitoring system.

For Bolt access, port-forward the query service:

kubectl -n $NAMESPACE port-forward --address 0.0.0.0 svc/$RELEASE_NAME-query-service 7687:7687

For Gremlin access, port-forward the leader service:

kubectl -n $NAMESPACE port-forward --address 0.0.0.0 svc/$RELEASE_NAME-leader-service 8182:8182

Access Method

LoadBalancer services are supported on cloud platforms (AWS EKS, GCP GKE, Azure AKS). Set service.controlplane.type=LoadBalancer (or service.query.type=LoadBalancer) in values.yaml to expose externally. For local development with Docker Desktop, use the port-forward method.


Single-Node Deployment

Single-node mode requires chart version 1.1.0 or later. It runs the controlplane, the query engine and storage in one pod, so it is not highly available and does not scale out. Use it when you would otherwise run the Docker container but need Kubernetes and Helm, for example to evaluate PuppyGraph on an on-premises cluster.

Configure

Create a values-single-node.yaml:

deploymentMode: single-node

image:
  # Pin a release in production. See "Pin the Image for Production" above.
  tag: latest

singleNode:
  resources:
    requests:
      cpu: "16"
      memory: "64Gi"
    limits:
      memory: "64Gi"
  storage:
    # Persistent volume for the registry, graph metadata and cached data.
    size: "50Gi"

env:
  singleNode:
    QUERY_TIMEOUT: "5m"

secrets:
  PUPPYGRAPH_USERNAME: "puppygraph"
  # Change this before exposing the service or using it in production.
  PUPPYGRAPH_PASSWORD: "puppygraph123"

Change the default password

Replace puppygraph123 with a strong, unique password before exposing the service outside the cluster or using it in production.

The resources above follow the production hardware recommendations in System Requirements. The chart's defaults, 4 CPU and 16Gi of memory, are sufficient for evaluation. The chart refuses to install with fewer than 2 CPU, 8Gi of memory or a 20Gi volume.

Notes on the values:

  • singleNode.*, service.singleNode.* and env.singleNode configure this mode. The controlplane, leader, compute and service.query values are not used, and neither are env.leader and env.controlplane. env.common is applied.
  • The role variables (CONTROLPLANE, LEADER, COMPUTE_NODE, CONTROLPLANE_ADDR) and the storage paths are set by the chart and cannot be overridden.
  • The volume uses the cluster's default StorageClass unless storage.name or storage.provisioner is set, as in cluster mode.
  • The same secrets and config values apply, including secrets.existingSecretName and config.presetSchema.

Deploy

export RELEASE_NAME=puppygraph
export NAMESPACE=puppygraph

helm upgrade --install $RELEASE_NAME puppygraph/puppygraph \
  --namespace $NAMESPACE \
  --create-namespace \
  -f values-single-node.yaml

kubectl -n $NAMESPACE rollout status statefulset/$RELEASE_NAME-single-node --timeout=600s

The pod becomes Ready once the query engine has started, which takes a few minutes on the first start.

Access

The chart deploys one service, $RELEASE_NAME-single-node-service, exposing the Web UI and REST API (port 8081), Gremlin (port 8182) and openCypher over Bolt (port 7687). Set service.singleNode.type=LoadBalancer to expose it externally on a cloud platform, or forward the ports locally:

kubectl -n $NAMESPACE port-forward svc/$RELEASE_NAME-single-node-service 8081:8081 8182:8182 7687:7687

Then open http://localhost:8081, sign in with the configured credentials and continue with Explore the Example Graph. Bolt clients connect to bolt://localhost:7687 and Gremlin clients to ws://localhost:8182/gremlin.

Data persistence

Schema, catalogs, users and cached data live on the pod's persistent volume, data-$RELEASE_NAME-single-node-0. They survive pod restarts and helm upgrade. helm uninstall keeps the volume claim; reinstalling with the same release name and namespace reattaches it. Delete the claim to start clean, as described in Uninstall and Clean Up.

Switching deployment modes

A release cannot be moved between single-node and cluster with helm upgrade; the chart refuses the upgrade while a StatefulSet from the other mode exists. Uninstall the release first. Data is not migrated between the two topologies.


Monitoring

PuppyGraph serves node metrics on :8083/metrics and controlplane metrics on :8081/metrics, with different credentials. See Metrics for what each endpoint serves, how it authenticates, and the metrics it exposes. This section covers the chart-specific setup.

Enable Metrics

Metrics are off by default. Turn them on for every PuppyGraph pod with env.common, in cluster and single-node mode:

env:
  common:
    METRICS_ENABLED: "true"

Leave METRICS_AUTH_ENABLED at its default. For the other metrics settings, see Configuration.

Scrape Metrics with Datadog

The Datadog Agent discovers the PuppyGraph pods through autodiscovery annotations, which you set with the chart's podAnnotations values. The annotations reference the credentials as %%env_<NAME>%% template variables, which the Agent replaces with its own environment variables, so no credentials appear in the pod spec.

Give the Agent the credentials

Create a Secret in the namespace of the Datadog Agent:

kubectl -n <DATADOG_NAMESPACE> create secret generic puppygraph-metrics \
  --from-literal=PUPPYGRAPH_USERNAME='<PUPPYGRAPH_USERNAME>' \
  --from-literal=PUPPYGRAPH_PASSWORD='<PUPPYGRAPH_PASSWORD>' \
  --from-literal=PUPPYGRAPH_SA_NAME='<SERVICE_ACCOUNT_NAME>' \
  --from-literal=PUPPYGRAPH_SA_SECRET='<SERVICE_ACCOUNT_SECRET>'
  • PUPPYGRAPH_USERNAME and PUPPYGRAPH_PASSWORD are for node metrics. Use the admin credentials of the Helm release: secrets.PUPPYGRAPH_USERNAME and secrets.PUPPYGRAPH_PASSWORD, or the same keys of secrets.existingSecretName.
  • PUPPYGRAPH_SA_NAME and PUPPYGRAPH_SA_SECRET are for controlplane metrics. The chart does not create PuppyGraph service accounts. Create one with a role that has CLUSTER:read after PuppyGraph starts. Before PuppyGraph 1.16.0, leave out these two keys.

Chart 1.1.0 and earlier

In cluster mode, chart 1.1.0 and earlier do not pass customized admin credentials from secrets.* to compute pods. Compute pods keep the image's default credentials, and their metrics check fails with 401. If you customize the admin credentials, put PUPPYGRAPH_USERNAME, PUPPYGRAPH_PASSWORD and AUTHENTICATION_JWT_SECRETKEY in your own Secret and set secrets.existingSecretName, which the chart loads into every pod. This limitation does not affect single-node mode.

Load the Secret into the Agent's environment. With the Datadog Helm chart, add to its values:

datadog:
  envFrom:
    - secretRef:
        name: puppygraph-metrics

Find the container names

The ad.datadoghq.com/<container>.checks annotation needs Datadog Agent 7.36 or later. Its key must contain the exact name of the container it applies to. Otherwise, the Agent ignores the annotation. The chart names each container after the Helm release:

Pod Container name
Controlplane <release>-controlplane
Leader <release>-leader
Compute <release>-compute
Single-node <release>-single-node

If the release name does not contain puppygraph, the chart inserts -puppygraph after it, for example my-graph-puppygraph-controlplane for the release my-graph. nameOverride and fullnameOverride also change the names. Check the container names of a running release with:

kubectl -n $NAMESPACE get pods -o custom-columns='POD:.metadata.name,CONTAINERS:.spec.containers[*].name'

The examples below are for the release names used earlier in this guide. Replace the container names in the annotation keys with yours. Save an example as values-datadog.yaml and add it to your helm upgrade --install command after your other values files, for example -f values.yaml -f values-datadog.yaml.

Cluster mode

For the release puppygraph-test, collect controlplane metrics from the controlplane pod, and node metrics from each leader and compute pod:

env:
  common:
    METRICS_ENABLED: "true"

controlplane:
  podAnnotations:
    ad.datadoghq.com/puppygraph-test-controlplane.checks: |
      {"openmetrics": {"instances": [{"openmetrics_endpoint": "http://%%host%%:8081/metrics", "username": "%%env_PUPPYGRAPH_SA_NAME%%", "password": "%%env_PUPPYGRAPH_SA_SECRET%%", "namespace": "puppy", "metrics": [".*"]}]}}

leader:
  podAnnotations:
    ad.datadoghq.com/puppygraph-test-leader.checks: |
      {"openmetrics": {"instances": [{"openmetrics_endpoint": "http://%%host%%:8083/metrics", "username": "%%env_PUPPYGRAPH_USERNAME%%", "password": "%%env_PUPPYGRAPH_PASSWORD%%", "namespace": "puppy", "metrics": [".*"]}]}}

compute:
  podAnnotations:
    ad.datadoghq.com/puppygraph-test-compute.checks: |
      {"openmetrics": {"instances": [{"openmetrics_endpoint": "http://%%host%%:8083/metrics", "username": "%%env_PUPPYGRAPH_USERNAME%%", "password": "%%env_PUPPYGRAPH_PASSWORD%%", "namespace": "puppy", "metrics": [".*"]}]}}

Before PuppyGraph 1.16.0, leave out the controlplane annotation.

Single-node mode

For the release puppygraph, the single-node pod serves both endpoints, so its check has two instances, :8083 for node metrics and :8081 for controlplane metrics. Use it with -f values-single-node.yaml -f values-datadog.yaml:

env:
  common:
    METRICS_ENABLED: "true"

singleNode:
  podAnnotations:
    ad.datadoghq.com/puppygraph-single-node.checks: |
      {"openmetrics": {"instances": [{"openmetrics_endpoint": "http://%%host%%:8083/metrics", "username": "%%env_PUPPYGRAPH_USERNAME%%", "password": "%%env_PUPPYGRAPH_PASSWORD%%", "namespace": "puppy", "metrics": [".*"]}, {"openmetrics_endpoint": "http://%%host%%:8081/metrics", "username": "%%env_PUPPYGRAPH_SA_NAME%%", "password": "%%env_PUPPYGRAPH_SA_SECRET%%", "namespace": "puppy", "metrics": [".*"]}]}}

Before PuppyGraph 1.16.0, leave out the :8081 instance.

Check the setup

  • Keep "metrics": [".*"] in every instance. It selects the metrics to collect, and without it the check reports [OK] but sends no metrics.
  • "namespace": "puppy" makes the metrics appear in Datadog as puppy.<metric name>.
  • After the upgrade, run agent status in the Datadog Agent pod on the same node as a PuppyGraph pod. Under openmetrics, each instance should show [OK] and a nonzero number of metric samples.

Uninstall and Clean Up

Data Loss Warning

These steps will permanently delete all PuppyGraph data.

# Uninstall Helm release
helm uninstall $RELEASE_NAME --namespace $NAMESPACE

# Delete persistent volume claims
kubectl get pvc -n $NAMESPACE | cut -f 1 -d ' ' | grep -E "data-${RELEASE_NAME}\S+" | xargs kubectl delete pvc -n $NAMESPACE