kubectl and Kubernetes Automation
`kubectl` is a remote API client whose current context can point at very different clusters. Production Bash must verify targeting before mutation and rely on Kubernetes conditions instead of human-formatted output or guessed sleeps.
Learning objectives
By the end of this lesson
- Validate current context before mutation.
- Pass namespaces explicitly.
- Use machine-oriented output.
- Wait on rollout conditions.
- Know when to use Helm, Kustomize, or GitOps instead of Bash.
1. kubectl is a client for a remote API
Unlike local process commands, kubectl usually talks to a Kubernetes API server using current context, cluster, user credentials, and namespace. A safe script must make those targeting assumptions visible.
flowchart LR B["Bash"] --> K["kubectl"] K --> A["Kubernetes API"] A --> O["objects / status"] O --> K K --> B
2. Validate context before mutation
context=$(kubectl config current-context)
printf 'context=%s\n' "$context"
[[ $context == "$EXPECTED_CONTEXT" ]] || {
printf 'refusing unexpected context\n' >&2
exit 65
}A script that accidentally points at production instead of staging can make perfectly valid commands disastrously wrong.
3. Pass namespace explicitly
kubectl \
--namespace "$namespace" \
get deployment apiDo not depend on whichever default namespace is currently stored in a user's kubeconfig.
4. Use structured output formats
image=$(
kubectl \
--namespace "$namespace" \
get deployment api \
-o jsonpath='{.spec.template.spec.containers[0].image}'
)
printf 'image=%s\n' "$image"Prefer JSON, JSONPath, or other machine-oriented formats instead of parsing aligned table columns.
5. Use rollout and wait primitives instead of blind sleeps
kubectl \
--namespace "$namespace" \
rollout status deployment/api \
--timeout=120sA fixed sleep 30 guesses how long readiness will take. Kubernetes already exposes object conditions and rollout status.
6. Declarative apply is usually safer than imperative mutation
kubectl \
--namespace "$namespace" \
apply -f deployment.yamlDeclarative manifests are reviewable and rerunnable. Imperative commands can still be appropriate for narrow operational tasks, but should not become an invisible configuration system inside Bash.
7. Validate manifests before changing the cluster
kubectl \
--namespace "$namespace" \
apply \
--dry-run=server \
-f deployment.yamlServer-side dry-run asks the API server to validate the request without persisting it, which can catch policy and schema problems earlier.
8. Patches need explicit structured payloads
patch=$(
jq -n \
--arg image "$image" \
'{
spec: {
template: {
spec: {
containers: [
{name: "api", image: $image}
]
}
}
}
}'
)
kubectl \
--namespace "$namespace" \
patch deployment api \
--type strategic \
--patch "$patch"Use structured generators rather than hand-escaped JSON inside nested shell quotes.
9. Preserve kubectl status and collect focused diagnostics
if kubectl -n "$namespace" rollout status deployment/api --timeout=120s; then
printf 'rollout=ok\n'
else
status=$?
kubectl -n "$namespace" get pods -o wide >&2 || true
kubectl -n "$namespace" describe deployment api >&2 || true
exit "$status"
fi10. Know when Bash is orchestrating too much cluster logic
If a script starts implementing dependency ordering, drift correction, retries across many resources, rollout strategy, and environment overlays, move that logic into Kubernetes-native configuration tooling, Helm, Kustomize, GitOps, or another purpose-built layer.
11. Hands-on lab: read-only Kubernetes preflight
mkdir -p "$HOME/devops-academy/bash/chapter15/lesson03"
cd "$HOME/devops-academy/bash/chapter15/lesson03"
cat > kube-preflight.sh <<'EOF'
#!/usr/bin/env bash
set -u
namespace=${1:-default}
command -v kubectl >/dev/null 2>&1 || {
printf 'kubectl is required\n' >&2
exit 69
}
context=$(kubectl config current-context 2>/dev/null) || {
printf 'no current Kubernetes context\n' >&2
exit 69
}
printf 'context=%s namespace=%s\n' "$context" "$namespace"
if kubectl \
--namespace "$namespace" \
get namespace "$namespace" \
-o name >/dev/null 2>&1; then
printf 'api_access=ok\n'
else
status=$?
printf 'api_access=failed status=%d\n' "$status" >&2
exit "$status"
fi
EOF
chmod u+x kube-preflight.sh
printf 'Run ./kube-preflight.sh NAMESPACE against a configured cluster.\n'Verification checklist
12. Knowledge check
Question 1. Why validate the current Kubernetes context?
Question 2. Why prefer rollout status over sleep?
Question 3. Why use structured output such as JSONPath?
Question 4. When should Bash give way to Helm/Kustomize/GitOps?
13. Summary
Safe kubectl automation makes cluster, context, namespace, and output format explicit; validates before mutation; waits on Kubernetes conditions rather than time guesses; and keeps complex desired-state logic outside ad-hoc shell code.
14. Further reading
- Kubernetes kubectl reference.
- Kubernetes documentation — contexts and namespaces.
- Kubernetes rollout and wait documentation.
- Kustomize, Helm, and GitOps documentation for larger configuration workflows.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this address.