Skip to main content

Quickly Inspect Kubernetes Pods' Environment Variables and Secrets

·5 mins·
Kubernetes Devops
Ana Cozma
Author
Ana Cozma
I’m a Cloud Engineer with a knack for CI/CD pipelines, Docker, Kubernetes, Azure and AWS with a focus on IaC, monitoring, and security. Let’s connect!
Table of Contents

Something that I love is to be able to troubleshoot fast (or at least have the right tooling for it). Working in a Kubernetes environment, I often find myself needing to get pods environment variables and secrets either for debugging purposes or auditing. I wanted something that would give me everything I need fast and at a glance in my terminal.

In this blog post I’ll share the little script I created to achieve this and how to add it to your shell as a function.

Why Extract Environment Variables and Secrets?
#

These are some of the cases I found myself needing to have access to the values for:

  • Debugging configuration issues: Confirming that environment variables are correctly injected.
  • Auditing security: Ensuring secrets are appropriately configured and securely resolved.
  • Monitoring: Verifying the dynamic configuration at runtime.

Retrieving Environment Variables and Secrets in One Command
#

I used a combination of kubectl and jq to extract all environment variables, including those that reference Kubernetes secrets.

Here’s the full script:

kubectl get pod <pod-name> -n <namespace> -o json | jq -r '
  .spec.containers[].env[] |
  if .valueFrom.secretKeyRef.name then
    "Secret: \(.name) -> \(.valueFrom.secretKeyRef.name)/\(.valueFrom.secretKeyRef.key)"
  elif .value then
    "Variable: \(.name) -> \(.value)"
  else
    "Other: \(.name) -> \(.)"
  end
' | while read line; do
  if [[ $line == Secret:* ]]; then
    secret_name=$(echo $line | awk -F "-> " '{print $2}' | awk -F "/" '{print $1}')
    secret_key=$(echo $line | awk -F "-> " '{print $2}' | awk -F "/" '{print $2}')
    resolved_value=$(kubectl get secret "$secret_name" -n <namespace> -o json | jq -r ".data.\"$secret_key\" | @base64d")
    echo "$line (Resolved Value: $resolved_value)"
  elif [[ $line == Other:* ]]; then
    echo "$line"
  else
    echo "$line"
  fi
done

What the script does:

  1. Environment Variables Directly Assigned:

    For variables with a direct value (value), it prints:
    Variable: <name> -> <value>.

  2. Environment Variables Referencing Secrets:

    For variables referencing secrets (valueFrom.secretKeyRef), it prints:
    Secret: <name> -> <secret-name>/<key>.

  3. Secrets Decoding:

    The script fetches the secret using kubectl get secret, decodes it with jq’s @base64d function, and appends the resolved value.

  4. Handling “Other” Configurations:

    It outputs additional details for variables configured with references like fieldRef, making it easier to debug and prints it:
    Other: <name>.

    The “Other” section captures configurations like:

    • fieldRef: References fields of the pod, such as status.podIP.
    • resourceFieldRef: References specific resources, such as limits or requests. These are less common but can be vital for debugging dynamic pod configurations.
  5. Dynamic Input:

    You can pass the pod name and namespace dynamically to analyze any pod’s configuration.

This script will give you an output similar to this one:

Other: MY_POD_IP -> {"name":"MY_POD_IP","valueFrom":{"fieldRef":{"fieldPath":"status.podIP"}}}
# Environment variable dynamically set to the pod's IP address.

Variable: AGENT_VERSION -> 0.0.1
# Static environment variable with a direct value.

Secret: LISTENER_URL -> my-pod-secret/my-pod-metrics-listener (Resolved Value: https://listener.io)
# Secret referencing a Kubernetes secret, resolved to its decoded value.

Secret: SPM_TOKEN -> my-pod-secret/my-pod-spm-shipping-token (Resolved Value: abc1234tokenvalue)
# Another secret resolved to its decoded token value.

But I don’t want to remember this script every time I need to run it. Which takes us to the next step.

Automating with a Shell Function
#

Option 1: Create a GitHub-Style Alias in Your Shell
#

To make this more convenient, you can create a shell function and add it to your .bashrc or .zshrc:

k8s-pod-env-secrets() {
    POD_NAME=$1
    NAMESPACE=$2

    if [[ -z $POD_NAME || -z $NAMESPACE ]]; then
        echo "Usage: k8s-pod-env-secrets <pod-name> <namespace>"
        return 1
    fi

    kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o json | jq -r '
      .spec.containers[].env[] |
      if .valueFrom.secretKeyRef.name then
        "Secret: \(.name) -> \(.valueFrom.secretKeyRef.name)/\(.valueFrom.secretKeyRef.key)"
      elif .value then
        "Variable: \(.name) -> \(.value)"
      else
        "Other: \(.name) -> \(.)"
      end
    ' | while read line; do
      if [[ $line == Secret:* ]]; then
        secret_name=$(echo $line | awk -F "-> " '{print $2}' | awk -F "/" '{print $1}')
        secret_key=$(echo $line | awk -F "-> " '{print $2}' | awk -F "/" '{print $2}')
        resolved_value=$(kubectl get secret "$secret_name" -n "$NAMESPACE" -o json | jq -r ".data.\"$secret_key\" | @base64d")
        echo "$line (Resolved Value: $resolved_value)"
      elif [[ $line == Other:* ]]; then
        echo "$line"
      else
        echo "$line"
      fi
    done
}

After adding this function, simply reload your shell:

source ~/.bashrc

Tip

If you use multiple environments, consider adding a check to confirm the current context with: kubectl config current-context

And in order to use the function created you can simply run:

k8s-pod-env-secrets <pod-name> <namespace>

Option 2: Create a Shell Script
#

This is very similar to the first approach. Save the following script to a file, for example, get-pod-env-secrets.sh:

#!/bin/bash

POD_NAME=$1
NAMESPACE=$2

if [[ -z $POD_NAME || -z $NAMESPACE ]]; then
    echo "Usage: $0 <pod-name> <namespace>"
    exit 1
fi

kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o json | jq -r '
  .spec.containers[].env[] |
  if .valueFrom.secretKeyRef.name then
    "Secret: \(.name) -> \(.valueFrom.secretKeyRef.name)/\(.valueFrom.secretKeyRef.key)"
  elif .value then
    "Variable: \(.name) -> \(.value)"
  else
    "Other: \(.name)"
  end
' | while read line; do
  if [[ $line == Secret:* ]]; then
    secret_name=$(echo $line | awk -F "-> " '{print $2}' | awk -F "/" '{print $1}')
    secret_key=$(echo $line | awk -F "-> " '{print $2}' | awk -F "/" '{print $2}')
    resolved_value=$(kubectl get secret "$secret_name" -n "$NAMESPACE" -o json | jq -r ".data.\"$secret_key\" | @base64d")
    echo "$line (Resolved Value: $resolved_value)"
  else
    echo "$line"
  fi
done

Make the script executable:

chmod +x get-pod-env-secrets.sh

Run the script with passing the pod name and namespace:

./get-pod-env-secrets.sh <pod-name> <namespace>

And that is it! Whether you’re troubleshooting, auditing, or monitoring, this script provides all the information you need in one glance.

Hope this helps someone else as well as it did me when I was troubleshooting and debugging!