Last active
April 10, 2025 07:32
-
-
Save venkata-qa/ab349b562f5ef399c18ae31cf957044f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| NAMESPACE=$1 | |
| if [[ -z "$NAMESPACE" ]]; then | |
| echo "β Usage: $0 <namespace>" | |
| exit 1 | |
| fi | |
| DATE=$(date "+%Y-%m-%d %H:%M:%S") | |
| REPORT="k8s_health_report_${NAMESPACE}_$(date +%Y%m%d).md" | |
| add_heading() { | |
| echo -e "\n## $1\n" >> "$REPORT" | |
| } | |
| add_subheading() { | |
| echo -e "\n### $1\n" >> "$REPORT" | |
| } | |
| # Header | |
| cat <<EOF > "$REPORT" | |
| # π Kubernetes Cluster Health Report | |
| - **Namespace**: \`$NAMESPACE\` | |
| - **Cluster**: \`$(kubectl config current-context)\` | |
| - **Generated On**: \`$DATE\` | |
| --- | |
| EOF | |
| # Pre-fetch values | |
| CRASHING=$(kubectl get pods -n "$NAMESPACE" -o json | jq '[.items[] | select(.status.containerStatuses[]?.state.waiting.reason == "CrashLoopBackOff")] | length') | |
| POD_TOTAL=$(kubectl get pods -n "$NAMESPACE" --no-headers | wc -l) | |
| POD_RUNNING=$(kubectl get pods -n "$NAMESPACE" --field-selector=status.phase=Running --no-headers | wc -l) | |
| REPLICA_ISSUES=$(kubectl get deployments -n "$NAMESPACE" -o json | jq '[.items[] | select((.spec.replicas // 0) != (.status.readyReplicas // 0))] | length') | |
| # 1. Cluster Readiness Summary | |
| add_heading "1. π¦ Cluster Readiness Summary" | |
| if [[ "$CRASHING" -eq 0 && "$REPLICA_ISSUES" -eq 0 ]]; then | |
| echo "**β Cluster is healthy and ready for release. All deployments are stable.**" >> "$REPORT" | |
| else | |
| echo "**β οΈ Issues detected:**" >> "$REPORT" | |
| echo "- CrashLoopBackOff Pods: **$CRASHING**" >> "$REPORT" | |
| echo "- Deployment Replica Mismatches: **$REPLICA_ISSUES**" >> "$REPORT" | |
| fi | |
| # 2. Namespace Metadata | |
| add_heading "2. π·οΈ Namespace Overview" | |
| kubectl describe namespace "$NAMESPACE" | grep -E 'Name:|Labels:|Status:' >> "$REPORT" | |
| # 3. Deployment Status | |
| add_heading "3. π¦ Deployment Status" | |
| echo '| Name | Ready | Up-to-date | Available |' >> "$REPORT" | |
| echo '|------|-------|-------------|-----------|' >> "$REPORT" | |
| kubectl get deployments -n "$NAMESPACE" --no-headers | awk '{printf "| %s | %s | %s | %s |\n", $1, $2, $3, $4}' >> "$REPORT" | |
| # 4. Deployment Replica Mismatches | |
| add_heading "4. π§ Deployment Replica Mismatches" | |
| MISMATCHES=$(kubectl get deployments -n "$NAMESPACE" -o json | jq -r ' | |
| .items[] | | |
| { | |
| name: .metadata.name, | |
| expected: (.spec.replicas // 0), | |
| ready: (.status.readyReplicas // 0) | |
| } | | |
| select(.expected != .ready) | | |
| [.name, .expected, .ready] | @tsv') | |
| if [[ -z "$MISMATCHES" ]]; then | |
| echo "_β All deployments have expected number of ready replicas._" >> "$REPORT" | |
| else | |
| echo '| Deployment | Expected | Ready |' >> "$REPORT" | |
| echo '|------------|----------|-------|' >> "$REPORT" | |
| echo "$MISMATCHES" | while IFS=$'\t' read -r name expected ready; do | |
| echo "| $name | $expected | $ready |" | |
| done >> "$REPORT" | |
| fi | |
| # 5. Expected vs Running Pods | |
| add_heading "5. π Expected vs Running Pods" | |
| DEPLOY=$(kubectl get deployments -n "$NAMESPACE" -o json | jq '[.items[].spec.replicas // 0] | add') | |
| STS=$(kubectl get statefulsets -n "$NAMESPACE" -o json | jq '[.items[].spec.replicas // 0] | add') | |
| DS=$(kubectl get daemonsets -n "$NAMESPACE" -o json | jq '[.items[].status.desiredNumberScheduled // 0] | add') | |
| EXPECTED=$((DEPLOY + STS + DS)) | |
| echo '| Source | Expected |' >> "$REPORT" | |
| echo '|---------------|----------|' >> "$REPORT" | |
| echo "| Deployments | $DEPLOY |" >> "$REPORT" | |
| echo "| StatefulSets | $STS |" >> "$REPORT" | |
| echo "| DaemonSets | $DS |" >> "$REPORT" | |
| echo "| **Total** | **$EXPECTED** |" >> "$REPORT" | |
| echo "| **Running** | **$POD_RUNNING** / $POD_TOTAL |" >> "$REPORT" | |
| # 6. Pod Health Summary | |
| add_heading "6. β Pod Health Summary" | |
| echo "- Total Pods: **$POD_TOTAL**" >> "$REPORT" | |
| echo "- Running Pods: **$POD_RUNNING**" >> "$REPORT" | |
| echo "- CrashLoopBackOff Pods: **$CRASHING**" >> "$REPORT" | |
| # 7. CrashLoopBackOff Pods | |
| if [[ "$CRASHING" -gt 0 ]]; then | |
| add_heading "7. π« CrashLoopBackOff Pods" | |
| echo '| Pod Name | Node | Restarts |' >> "$REPORT" | |
| echo '|----------|------|----------|' >> "$REPORT" | |
| kubectl get pods -n "$NAMESPACE" -o json | jq -r ' | |
| .items[] | | |
| select(.status.containerStatuses[]?.state.waiting.reason == "CrashLoopBackOff") | | |
| [.metadata.name, .spec.nodeName, (.status.containerStatuses[0].restartCount // 0)] | @tsv' | | |
| while IFS=$'\t' read -r pod node restarts; do | |
| printf "| %s | %s | %s |\n" "$pod" "$node" "$restarts" | |
| done >> "$REPORT" | |
| fi | |
| # 8. Top Resource Usage | |
| add_heading "8. π Top Resource Usage (CPU)" | |
| echo '| Pod | CPU (m) | Memory (Mi) |' >> "$REPORT" | |
| echo '|-----|---------|--------------|' >> "$REPORT" | |
| kubectl top pods -n "$NAMESPACE" --no-headers 2>/dev/null | sort -k2 -rh | head -n 5 | awk '{printf "| %s | %s | %s |\n", $1, $2, $3}' >> "$REPORT" || echo '| Metrics unavailable | - | - |' >> "$REPORT" | |
| # 9. Image Versions | |
| add_heading "10. π§ͺ Deployed Image Versions" | |
| echo '| Image | Version |' >> "$REPORT" | |
| echo '|--------|---------|' >> "$REPORT" | |
| kubectl get pods -n "$NAMESPACE" -o json | jq -r ' | |
| [.items[].spec.containers[].image] | unique | .[]' | sort | | |
| while read -r image; do | |
| base=$(echo "$image" | cut -d":" -f1) | |
| tag=$(echo "$image" | cut -d":" -f2) | |
| echo "| $base | ${tag:-latest} |" | |
| done >> "$REPORT" | |
| # 10. Recent Warning Events | |
| add_heading "9. π₯ Recent Warning Events" | |
| echo '| Type | Reason | Message | Time |' >> "$REPORT" | |
| echo '|------|--------|---------|------|' >> "$REPORT" | |
| kubectl get events -n "$NAMESPACE" --sort-by=.lastTimestamp -o json | jq -r ' | |
| .items[] | |
| | select(.type == "Warning") | |
| | [ | |
| .type, | |
| .reason, | |
| (.message // "N/A" | tostring | gsub("[\n\r\t]+"; " ") | sub("^(.{0,60}).*"; "\\1...")), | |
| (.lastTimestamp // "N/A") | |
| ] | |
| | @tsv' | tail -n 10 | | |
| while IFS=$'\t' read -r type reason msg time; do | |
| printf "| %s | %s | %s | %s |\n" "$type" "$reason" "$msg" "$time" | |
| done >> "$REPORT" | |
| echo "" | |
| echo "β Report generated: $REPORT" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment