Troubleshooting Kubernetes
We provide a read-only script k8s-diagnostics-collector.sh that collects Kubernetes logs, events, and API objects from a single namespace. It packages everything into a .tar.gz bundle you can send to Tines support to help diagnose issues with your deployment (for example pods that restart, crash, or fail health checks).
The bundle includes kubectl context and version information, pod status, resource usage, namespace events, container logs, and namespaced Kubernetes objects. Secrets and ConfigMaps are excluded because they may contain credentials or sensitive configuration.
When you contact support, include:
Tines version — the Helm chart version and/or application version you have deployed
Kubernetes platform — where the cluster runs, for example Google Kubernetes Engine (GKE), Amazon EKS, Microsoft Azure Kubernetes Service (AKS), or another distribution
Review the bundle and remove sensitive information before sending it to support. Container logs and exported objects may contain sensitive data you do not want to share. Pay close attention to app secrets, passwords, and tokens.
Quickstart
You need kubectl configured for the target cluster. Install it from the Kubernetes documentation↗ if it is not already on your PATH.
Download the script, make it executable, and run it against your Tines namespace:
curl -fsSL -O https://assets.sh.tines.com/collectors/k8s/k8s-diagnostics-collector.sh
chmod +x k8s-diagnostics-collector.sh
./k8s-diagnostics-collector.sh --namespace your-tines-namespaceThe script prints the current kubectl context and asks you to confirm before collecting any data. When it finishes, it creates an archive named k8s-namespace-debug-<namespace>-<timestamp>.tar.gz.
Send that archive to your Tines support contact after reviewing its contents and removing anything sensitive.
Manual collection
This section walks through the same read-only diagnostic collection performed by k8s-diagnostics-collector.sh, but as individual commands you can run yourself. Use this when you prefer not to run the script, need to collect only part of the bundle, or want to inspect output as you go.
The automated script is equivalent to running every section below in order and packaging the result into a .tar.gz archive.
What is collected
Current kubectl context and client/server version
Pod status for all pods in the namespace
Current CPU and memory usage for all pods (
kubectl top; requires metrics-server)Namespace events (probe failures, OOMKills, scheduling, and so on)
Container logs for every pod (current and previous for regular containers; current for init containers)
All namespaced Kubernetes API objects except Secrets and ConfigMaps
What is not collected
Secrets (may contain credentials)
ConfigMaps (may contain sensitive application configuration)
Cluster-wide resources outside the target namespace
Historical metrics or live profiling data
Prerequisites
kubectlinstalled and configured for the target clusterPermission to read pods, logs, events, and other namespace resources in the target namespace
bash,date,mkdir,tar, and standard Unix utilities on your PATH
1. Set environment variables
Define these once at the start of your shell session. Every section below reuses them.
# Required: namespace to collect from
NAMESPACE="your-namespace"
# Optional: max log lines per container (default in the script is 5000)
LOG_TAIL=5000
# Output directory and archive names (timestamp keeps each run unique)
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
OUT_DIR="k8s-namespace-debug-${NAMESPACE}-${TIMESTAMP}"
ARCHIVE="${OUT_DIR}.tar.gz"2. Confirm kubectl context
Purpose: Verify you are connected to the intended cluster before collecting any data.
kubectl config current-contextReview the output. Switch context if needed:
kubectl config use-context <context-name>Optionally store the context name for your records:
CONTEXT="$(kubectl config current-context)"
echo "Using context: ${CONTEXT}"3. Verify the namespace exists
Purpose: Fail fast if the namespace name is wrong or you lack access.
kubectl get namespace "${NAMESPACE}"4. Create the output directory
Purpose: Prepare the folder layout used by the script (logs/ and objects/ subdirectories).
mkdir -p "${OUT_DIR}/logs" "${OUT_DIR}/objects"5. Write collection metadata
Purpose: Record when the bundle was collected and which options were used.
{
echo "collected_at=${TIMESTAMP}"
echo "namespace=${NAMESPACE}"
echo "log_tail=${LOG_TAIL}"
} > "${OUT_DIR}/metadata.txt"6. Save kubectl context
Purpose: Capture which cluster/context the data came from.
Command: kubectl config current-context
Output file: ${OUT_DIR}/context.txt
kubectl config current-context > "${OUT_DIR}/context.txt" 2>&17. Save kubectl client and server version
Purpose: Document kubectl and API server versions for compatibility troubleshooting.
Command: kubectl version --output=yaml
Output file: ${OUT_DIR}/kubectl-version.yaml
kubectl version --output=yaml > "${OUT_DIR}/kubectl-version.yaml" 2>&18. Save pod status
Purpose: Snapshot pod names, phases, nodes, restart counts, and IP addresses.
Command: kubectl get pods -o wide
Output file: ${OUT_DIR}/pods.txt
kubectl -n "${NAMESPACE}" get pods -o wide > "${OUT_DIR}/pods.txt" 2>&19. Save pod resource usage
Purpose: Capture current CPU and memory usage for every pod in the namespace. Requires metrics-server in the cluster; the command fails harmlessly if it is not installed.
Command: kubectl top pods
Output file: ${OUT_DIR}/pods-top.txt
kubectl -n "${NAMESPACE}" top pods > "${OUT_DIR}/pods-top.txt" 2>&110. Save namespace events
Purpose: Collect scheduling, probe failure, OOMKill, and other cluster events for the namespace, ordered by time.
Command: kubectl get events --sort-by=.lastTimestamp
Output file: ${OUT_DIR}/events.txt
kubectl -n "${NAMESPACE}" get events --sort-by=.lastTimestamp \
> "${OUT_DIR}/events.txt" 2>&111. Save namespace API objects (excluding Secrets and ConfigMaps)
Purpose: Export YAML for every namespaced resource type the API exposes, except Secrets and ConfigMaps.
Command: For each namespaced resource type, kubectl get <resource> -o yaml
Output directory: ${OUT_DIR}/objects/ (one file per resource type)
for RESOURCE in $(kubectl api-resources --namespaced=true --verbs=list -o name); do
case "${RESOURCE}" in
secrets|configmaps)
continue
;;
esac
SAFE_NAME="${RESOURCE//\//_}"
echo "Collecting ${RESOURCE} -> objects/${SAFE_NAME}.yaml"
kubectl -n "${NAMESPACE}" get "${RESOURCE}" -o yaml \
> "${OUT_DIR}/objects/${SAFE_NAME}.yaml" 2>&1
doneTo collect a single resource type instead of everything, run one command directly. Example for Deployments:
kubectl -n "${NAMESPACE}" get deployments.apps -o yaml \
> "${OUT_DIR}/objects/deployments.apps.yaml" 2>&112. Save container logs
Purpose: Capture application output from every pod. Regular containers get both current logs and previous (crashed) logs; init containers get current logs only. Each file is capped at ${LOG_TAIL} lines.
12a. Regular containers — current logs
Command: kubectl logs <pod> -c <container> --tail=<lines>
Output file pattern: ${OUT_DIR}/logs/<pod>__<container>__current.log
for pod in $(kubectl -n "${NAMESPACE}" get pods -o name); do
POD="${pod#pod/}"
for CONTAINER in $(kubectl -n "${NAMESPACE}" get pod "${POD}" \
-o jsonpath='{.spec.containers[*].name}'); do
kubectl -n "${NAMESPACE}" logs "${POD}" -c "${CONTAINER}" \
--tail="${LOG_TAIL}" \
> "${OUT_DIR}/logs/${POD}__${CONTAINER}__current.log" 2>&1
done
done12b. Regular containers — previous (crashed) logs
Command: kubectl logs <pod> -c <container> --previous --tail=<lines>
Output file pattern: ${OUT_DIR}/logs/<pod>__<container>__previous.log
No previous log exists if the container has never restarted; that command will fail harmlessly for those containers.
for pod in $(kubectl -n "${NAMESPACE}" get pods -o name); do
POD="${pod#pod/}"
for CONTAINER in $(kubectl -n "${NAMESPACE}" get pod "${POD}" \
-o jsonpath='{.spec.containers[*].name}'); do
kubectl -n "${NAMESPACE}" logs "${POD}" -c "${CONTAINER}" --previous \
--tail="${LOG_TAIL}" \
> "${OUT_DIR}/logs/${POD}__${CONTAINER}__previous.log" 2>&1
done
done12c. Init containers — current logs
Command: kubectl logs <pod> -c <init-container> --tail=<lines>
Output file pattern: ${OUT_DIR}/logs/<pod>__init-<init-container>__current.log
for pod in $(kubectl -n "${NAMESPACE}" get pods -o name); do
POD="${pod#pod/}"
for INIT_CONTAINER in $(kubectl -n "${NAMESPACE}" get pod "${POD}" \
-o jsonpath='{.spec.initContainers[*].name}'); do
kubectl -n "${NAMESPACE}" logs "${POD}" -c "${INIT_CONTAINER}" \
--tail="${LOG_TAIL}" \
> "${OUT_DIR}/logs/${POD}__init-${INIT_CONTAINER}__current.log" 2>&1
done
done12d. Single pod or container
To collect logs for one pod only, set POD and run the relevant command directly:
POD="my-pod-name"
CONTAINER="my-container"
kubectl -n "${NAMESPACE}" logs "${POD}" -c "${CONTAINER}" \
--tail="${LOG_TAIL}" \
> "${OUT_DIR}/logs/${POD}__${CONTAINER}__current.log" 2>&113. Create the archive
Purpose: Package the output directory into a single file for sharing with support, matching the script's deliverable.
Command: tar -czf
Output file: ${ARCHIVE}
tar -czf "${ARCHIVE}" "${OUT_DIR}"
echo "Created archive: ${ARCHIVE}"Before sharing
Container logs and exported objects may contain sensitive application data. Review the contents of ${OUT_DIR} or ${ARCHIVE} and remove anything you do not want to share before sending the bundle to Tines support.
When you open a support request, include your Tines version (Helm chart and/or application version) and Kubernetes platform (for example GKE, EKS, or AKS).