This skill creates ephemeral pods cloned from existing deployments for interactive shell access with full application context. Use this when you need Rails console, database access, or debugging with env vars and secrets without affecting production pods.
Create a dedicated pod cloned from an existing deployment for interactive shell access with full application context (environment variables, secrets, volume mounts).
Why not kubectl exec into an existing pod? This approach:
kubectl installed and configuredjq installed (for JSON transformation)If your cluster uses AWS EKS with SSO authentication:
# Check if SSO session is valid
kubectl get deployments -n <NAMESPACE> 2>&1 | grep -q "SSO session" && echo "SSO expired"
# Find the AWS profile from your kubeconfig
grep -A15 'exec:' <KUBECONFIG_PATH> | grep 'AWS_PROFILE' -A1
# Login with the profile
aws sso login --profile <PROFILE_NAME>
Important: Keep the same terminal session open throughout. Variables must persist across all steps.
export KUBECONFIG=/path/to/your/kubeconfig
# List matching deployments
kubectl get deployments -n <NAMESPACE> -l <LABEL_SELECTOR>
# Pick one and store the name
DEPLOYMENT_NAME=<name-from-output>
# List containers to find the app container (not sidecars like linkerd-proxy, proxy, envoy)
kubectl get deployment "$DEPLOYMENT_NAME" -n <NAMESPACE> -o jsonpath='{.spec.template.spec.containers[*].name}'
# The app container usually matches the deployment name
CONTAINER_NAME=<app-container-name>
NAMESPACE=<namespace>
# Generate a unique pod name
POD_NAME="${DEPLOYMENT_NAME}-exec-`date +%s`"
echo "Pod name: $POD_NAME"
# Extract deployment and transform to ephemeral pod
kubectl get deployment "$DEPLOYMENT_NAME" -n "$NAMESPACE" -o json | jq \
--arg podname "$POD_NAME" \
--arg namespace "$NAMESPACE" \
--arg container "$CONTAINER_NAME" '
.spec.template |
.apiVersion = "v1" |
.kind = "Pod" |
.metadata = {name: $podname, namespace: $namespace, labels: {ephemeral: "true"}} |
.spec.restartPolicy = "Never" |
.spec.containers = [.spec.containers[] | select(.name == $container) | .command = ["sleep", "14400"] | .args = [] | del(.readinessProbe) | del(.livenessProbe) | del(.startupProbe)] |
del(.spec.initContainers)
' > /tmp/exec-pod.json
# Verify the pod spec looks correct
jq '{name: .metadata.name, namespace: .metadata.namespace, containers: [.spec.containers[].name]}' /tmp/exec-pod.json
This creates a pod that:
sleep 14400 (4 hours) instead of the app's entrypoint# If you need more memory (e.g., 1024Mi):
jq '.spec.containers[0].resources = {
limits: {memory: "1024Mi"},
requests: {memory: "1024Mi"}
}' /tmp/exec-pod.json > /tmp/exec-pod-final.json && mv /tmp/exec-pod-final.json /tmp/exec-pod.json
kubectl apply -f /tmp/exec-pod.json
kubectl wait --for=condition=Ready "pod/$POD_NAME" -n "$NAMESPACE" --timeout=120s
# Interactive shell
kubectl exec -it "$POD_NAME" -n "$NAMESPACE" -- bash
# Or run Rails console directly
kubectl exec -it "$POD_NAME" -n "$NAMESPACE" -- bin/rails console
Always delete the pod when done:
kubectl delete pod "$POD_NAME" -n "$NAMESPACE" --grace-period=1
Find orphaned exec pods:
kubectl get pods -n "$NAMESPACE" -l ephemeral=true
export KUBECONFIG=/path/to/your/kubeconfig
NAMESPACE=<namespace>
# Find your most recent exec pod
POD_NAME=$(kubectl get pods -n "$NAMESPACE" -l ephemeral=true --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1:].metadata.name}')
echo "Found pod: $POD_NAME"
The SSO session associated with this profile has expired or is otherwise invalid.
Re-authenticate with aws sso login --profile <PROFILE_NAME>.
kubectl describe pod "$POD_NAME" -n "$NAMESPACE"
Common causes: insufficient cluster resources, node selector can't be satisfied, image pull secrets missing.
Check image pull secrets are included:
kubectl get deployment "$DEPLOYMENT_NAME" -n "$NAMESPACE" -o jsonpath='{.spec.template.spec.imagePullSecrets}'
Pod ran out of memory. Recreate with higher memory value in step 4.
Try sh instead:
kubectl exec -it "$POD_NAME" -n "$NAMESPACE" -- sh
Run a one-off command:
kubectl exec "$POD_NAME" -n "$NAMESPACE" -- bin/rails runner "puts User.count"
Shorter timeout (1 hour):
In step 3, change "sleep", "14400" to "sleep", "3600".