Collect a Support Bundle
A support bundle is a single archive of cluster state and component logs that GoodData Support uses to investigate a problem in your GoodData.CN deployment. You generate it yourself with troubleshoot, an open-source tool from Replicated, driven by a YAML specification that tells it what to collect and which checks to run.
The GoodData.CN Helm chart ships that specification with it and publishes it into your cluster, so the namespaces, release name and Secret names it collects always match the deployment you actually installed. In most cases you do not need a specification file at all.
The specification collects no Secret values: it records which Secrets exist and which keys they contain, which is what diagnoses a failed install. The connectivity probes, which are off by default, are the one exception – they read the credentials they need into a temporary pod in order to open a connection, and write none of them to the archive. It does collect container logs, and those logs can carry credentials, tokens, connection strings or customer data that a component wrote to its output. Troubleshoot applies its built-in redactors plus a set of GoodData-specific ones covering license keys, database connection strings, bearer tokens and object-storage credentials.
Treat the Bundle as Sensitive
Redaction is pattern-based and best-effort, so a secret in an unusual log format can survive it. Review the unpacked archive before you share it if your environment requires that, and always submit the bundle to GoodData through the secure support portal rather than email or chat.
Prerequisites
kubectlconfigured against the cluster running GoodData.CN.- Read access to the namespaces you collect from and to cluster-scoped
resources (nodes, cluster version). A read-only cluster role is enough;
cluster-adminalso works.
Install the support-bundle plugin
Install the plugin with krew, the kubectl plugin
manager:
kubectl krew install support-bundleIf you don’t use krew, the installer script from Replicated does both steps for you:
curl -s https://krew.sh/support-bundle | bashThe script downloads and runs code from the internet. Read it first if your
environment requires that. Then add krew’s binary directory to your PATH:
export PATH="${PATH}:${HOME}/.krew/bin"Collect the bundle
Point the plugin at your cluster and let it discover the specification the chart published:
kubectl support-bundle --load-cluster-specs -n <namespace>Use the namespace your GoodData.CN release is installed in; the examples below
use gooddata-cn.
--load-cluster-specs finds any ConfigMap labelled
troubleshoot.sh/kind: support-bundle, which is what the chart creates as
<release>-support-bundle. Nothing needs editing, and there is no namespace to
get wrong.
In CI or any non-interactive shell, skip the results browser:
kubectl support-bundle --load-cluster-specs -n gooddata-cn --interactive=falseThe run writes a compressed archive named support-bundle-<TIMESTAMP>.tar.gz to
the current directory. Unpack it to review what was collected:
tar -xzf support-bundle-<TIMESTAMP>.tar.gzTune what gets collected
Everything below is a Helm value, so the change survives upgrades and applies to whoever runs the collection next. Apply them the way you apply any other value, then re-run the collection.
Include your ingress controller and other namespaces
The chart collects from its own namespace and from Pulsar’s automatically. It cannot guess which ingress controller you run, so add it:
supportBundle:
extraNamespaces:
- ingress-nginx
- cert-manager
extraLogs:
- name: ingress-nginx
namespace: ingress-nginx
selector:
- app.kubernetes.io/name=ingress-nginx
- name: cert-manager
namespace: cert-manager
selector:
- app.kubernetes.io/instance=cert-managerextraNamespaces collects Kubernetes objects and events; extraLogs collects
container logs. Add both for a component you want fully covered.
Adjust log volume
This is the setting to reach for if collection is slow or times out, or if the archive is too large to attach.
supportBundle:
logs:
maxLines: 3000
maxBytes: 2000000Logs are collected one namespace at a time, with no label selector, so these caps apply to every container in the namespace. They are enforced by the Kubernetes API rather than after the fact, so a capped log is never transferred.
They are also the only thing bounding the collection: a request covering a whole
namespace runs under a hard 60 second timeout, and each container is fetched
twice (its current and previous instance). Lower maxBytes first if a collection
times out; raise both when support asks for more history.
Do not add maxAge
Troubleshoot applies maxAge instead of maxLines and maxBytes, not
alongside them. Adding it silently removes both caps and streams the entire
window, which is the usual cause of a collection that times out on a busy
cluster.
Report on your TLS certificate and public endpoints
supportBundle:
certificateSecrets:
- name: gooddata-cn-tls
namespaces: [gooddata-cn]
organizationHostnames:
- analytics.example.comcertificateSecrets reports expiry, SANs and issuer, reading only the public
half of the certificate. Each entry in organizationHostnames gets an HTTPS
request from the machine running the collection, which exercises public DNS, the
load balancer, the ingress and the certificate in one step. A 401 there is a
good result: it proves the request reached the gateway.
Pulsar in its own namespace, or in yours
Pulsar’s pod logs and its Helm values and upgrade history are collected
automatically, and the namespace is worked out from the broker host your services
are already configured with (service.pulsar.host). All the usual layouts work
without configuration:
service.pulsar.host | Pulsar collected from |
|---|---|
pulsar-broker.pulsar | pulsar – the separate namespace we recommend |
pulsar-broker | the GoodData.CN namespace – Pulsar shares it |
pulsar-broker.pulsar.svc.cluster.local | pulsar |
pulsar-prod-broker.messaging | messaging |
The collector selects Pulsar’s pods by their release label, derived from the broker service name, so it finds your Pulsar whatever the release is called and picks up only its pods when the namespace holds anything else.
A host that is not in-cluster DNS – a managed Pulsar at pulsar.example.com, or
an IP address – means Pulsar is not in this cluster, so its collectors are
skipped rather than pointed at a namespace that does not exist. If Pulsar is in
the cluster but reached through a name like that, name the namespace yourself:
supportBundle:
pulsar:
namespace: pulsarPulsar always gets its own collector, selected by its release label, so it stays separate from GoodData.CN’s even when the two share a namespace. To skip Pulsar’s logs or its Helm release:
supportBundle:
pulsar:
collectLogs: false
collectHelmRelease: falseCheck DNS resolution
The bundle can check DNS resolution, which separates a broken CoreDNS from a
broken upstream resolver. It is off by default: the check runs a pod,
troubleshoot always creates that pod in the default namespace rather than
in the GoodData.CN one, and it does not remove it afterwards. Turn it on when a
DNS problem is suspected, or when support asks:
supportBundle:
dns:
enabled: trueTest connectivity to the backing services
supportBundle:
probes:
enabled: trueThis runs one short-lived pod that checks PostgreSQL, Pulsar and Redis using the same credentials the services use, injected from your Secrets and never written into the archive. It is off by default because it creates a pod in your cluster; the DNS check above is the only other step that does, and it is off by default too. Unlike that one, this pod is removed when the collection finishes.
Troubleshoot creates that pod itself, so it does not carry the chart’s
commonLabels. If an admission policy requires ownership labels on every pod,
leave the probes disabled or exempt that pod.
Add your own collectors and redactors
supportBundle.extraCollectors, extraAnalyzers and extraRedactors are
appended to the specification verbatim, so anything in the
troubleshoot documentation can be
added without forking the chart. Use extraRedactors for credential formats
specific to your environment.
Use a specification file instead
If you cannot use --load-cluster-specs – an older plugin version, or a
workstation that may not list ConfigMaps – write the same specification to a
file and pass it directly.
Extract the copy your own cluster published, which needs no editing. Set the two variables to your namespace and Helm release name:
NAMESPACE=gooddata-cn
RELEASE_NAME=gooddata-cn
kubectl -n "$NAMESPACE" get configmap "${RELEASE_NAME}-support-bundle" \
-o go-template='{{ index .data "support-bundle-spec" }}' \
> support-bundle-gooddata-cn.yaml
kubectl -n "$NAMESPACE" get configmap "${RELEASE_NAME}-support-bundle" \
-o go-template='{{ index .data "redactor-spec" }}' \
> support-bundle-redactors.yamlPass both files, so the GoodData-specific redaction rules are applied:
kubectl support-bundle support-bundle-gooddata-cn.yaml \
--redactors=support-bundle-redactors.yamlIf the ConfigMap is not there – the release is not installed yet, or its chart
predates this feature – render the same two documents from the chart instead.
helm template prints the whole ConfigMap, so pull each key out of it:
helm template "$RELEASE_NAME" gooddata/gooddata-cn \
--namespace "$NAMESPACE" \
--values your-values.yaml \
--set license.key='<your-license-key>' \
-s templates/support-bundle.yaml > support-bundle-configmap.yaml
yq '.data."support-bundle-spec"' support-bundle-configmap.yaml \
> support-bundle-gooddata-cn.yaml
yq '.data."redactor-spec"' support-bundle-configmap.yaml \
> support-bundle-redactors.yamlPass Your Own Values
Without --values, helm template renders the chart’s defaults. The
specification would then look for Pulsar and your Secrets where an untouched
chart puts them, not where your deployment does, and the bundle can come back
nearly empty. Use the same values file you install with. For a running release,
helm get values <release> -n <namespace> --all -o yaml writes out the values it
was installed with.
The chart on your cluster does not have to be the one you render from. If your release is older than this feature, pull a current chart and render the specification from it without upgrading anything:
helm pull gooddata/gooddata-cn --untar
helm template "$RELEASE_NAME" ./gooddata-cn \
--namespace "$NAMESPACE" \
--values your-values.yaml \
--set license.key='<your-license-key>' \
-s templates/support-bundle.yaml > support-bundle-configmap.yamlIf the collection fails
It times out, or takes far too long
Lower the log limits, which is what usually dominates collection time:
supportBundle:
logs:
maxLines: 1000
maxBytes: 500000Avoid --since and --since-time
The --since and --since-time flags look like a way to shrink the collection,
but they behave like maxAge: troubleshoot applies a start time instead of the
line and byte caps, not alongside them. Passing either one removes both caps from
every log request and usually makes a slow collection slower. Lower the values
above instead.
client rate limiter Wait returned an
error
Despite the wording, nothing is being throttled. Troubleshoot fetches container logs one at a time, and each container costs two requests – for its current and its previous instance. A collector gets 60 seconds in total for every pod it matches, not 60 seconds per pod, and when that runs out the remaining requests report the expired deadline through the rate limiter, which is where the misleading message comes from.
It means a collector was given more containers than it could read in a minute.
Lower maxBytes so each log takes less time to transfer. Note the failed
containers are recorded per container inside the archive, in files named
*-errors.json, and the run still exits successfully – so a bundle can look
complete while individual logs are missing.
Advice you may find elsewhere to raise qps and burst in the
kube-proxy-config ConfigMap does not apply: that is kube-proxy’s own client
configuration, unrelated to the tool collecting the bundle, which already runs at
100 QPS.
Some collectors report permission errors
The collection continues and produces a bundle regardless; the missing pieces are recorded in the archive. Grant the missing read permissions and re-run if support asks for something that was skipped. Collecting from a namespace that does not exist is harmless – it produces nothing and no error.
Send the bundle to support
Attach the archive when you open a case at
GoodData Support. Include when the problem
started, which organizations or workspaces are affected, and what changed before
it started, such as the last helm upgrade, a configuration edit, or an
infrastructure change.