Skip to content

Instantly share code, notes, and snippets.

@venkata-qa
Last active April 10, 2025 07:32
Show Gist options
  • Save venkata-qa/ab349b562f5ef399c18ae31cf957044f to your computer and use it in GitHub Desktop.
Save venkata-qa/ab349b562f5ef399c18ae31cf957044f to your computer and use it in GitHub Desktop.

Revisions

  1. venkata-qa revised this gist Apr 10, 2025. 1 changed file with 21 additions and 13 deletions.
    34 changes: 21 additions & 13 deletions k8s_report_v5.sh
    Original file line number Diff line number Diff line change
    @@ -118,19 +118,7 @@ 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. 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"

    # 10. Image Versions
    # 9. Image Versions
    add_heading "10. πŸ§ͺ Deployed Image Versions"
    echo '| Image | Version |' >> "$REPORT"
    echo '|--------|---------|' >> "$REPORT"
    @@ -142,5 +130,25 @@ while read -r image; do
    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"
  2. venkata-qa revised this gist Apr 10, 2025. 1 changed file with 43 additions and 17 deletions.
    60 changes: 43 additions & 17 deletions k8s_report_v5.sh
    Original file line number Diff line number Diff line change
    @@ -13,8 +13,8 @@ add_heading() {
    echo -e "\n## $1\n" >> "$REPORT"
    }

    add_table() {
    echo -e "$1" >> "$REPORT"
    add_subheading() {
    echo -e "\n### $1\n" >> "$REPORT"
    }

    # Header
    @@ -32,13 +32,17 @@ EOF
    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 ]]; then
    echo "**βœ… Cluster is healthy and ready for release.**" >> "$REPORT"

    if [[ "$CRASHING" -eq 0 && "$REPLICA_ISSUES" -eq 0 ]]; then
    echo "**βœ… Cluster is healthy and ready for release. All deployments are stable.**" >> "$REPORT"
    else
    echo "**⚠️ $CRASHING CrashLoopBackOff pod(s) detected. Investigate before release.**" >> "$REPORT"
    echo "**⚠️ Issues detected:**" >> "$REPORT"
    echo "- CrashLoopBackOff Pods: **$CRASHING**" >> "$REPORT"
    echo "- Deployment Replica Mismatches: **$REPLICA_ISSUES**" >> "$REPORT"
    fi

    # 2. Namespace Metadata
    @@ -51,8 +55,30 @@ 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. Expected vs Running Pods
    add_heading "4. πŸ”„ Expected vs Running Pods"
    # 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')
    @@ -66,15 +92,15 @@ echo "| DaemonSets | $DS |" >> "$REPORT"
    echo "| **Total** | **$EXPECTED** |" >> "$REPORT"
    echo "| **Running** | **$POD_RUNNING** / $POD_TOTAL |" >> "$REPORT"

    # 5. Pod Health Summary
    add_heading "5. βœ… Pod Health Summary"
    # 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"

    # 6. CrashLoopBackOff Pods
    # 7. CrashLoopBackOff Pods
    if [[ "$CRASHING" -gt 0 ]]; then
    add_heading "6. 🚫 CrashLoopBackOff Pods"
    add_heading "7. 🚫 CrashLoopBackOff Pods"
    echo '| Pod Name | Node | Restarts |' >> "$REPORT"
    echo '|----------|------|----------|' >> "$REPORT"
    kubectl get pods -n "$NAMESPACE" -o json | jq -r '
    @@ -86,14 +112,14 @@ if [[ "$CRASHING" -gt 0 ]]; then
    done >> "$REPORT"
    fi

    # 7. Top Resource Usage
    add_heading "7. πŸ“Š Top Resource Usage (CPU)"
    # 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"

    # 8. Recent Warning Events
    add_heading "8. πŸ”₯ Recent Warning Events"
    # 9. 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 '
    @@ -104,8 +130,8 @@ kubectl get events -n "$NAMESPACE" --sort-by=.lastTimestamp -o json | jq -r '
    printf "| %s | %s | %s | %s |\n" "$type" "$reason" "$msg" "$time"
    done >> "$REPORT"

    # 9. Image Versions
    add_heading "9. πŸ§ͺ Deployed Image Versions"
    # 10. Image Versions
    add_heading "10. πŸ§ͺ Deployed Image Versions"
    echo '| Image | Version |' >> "$REPORT"
    echo '|--------|---------|' >> "$REPORT"
    kubectl get pods -n "$NAMESPACE" -o json | jq -r '
  3. venkata-qa created this gist Apr 10, 2025.
    120 changes: 120 additions & 0 deletions k8s_report_v5.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,120 @@
    #!/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_table() {
    echo -e "$1" >> "$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)

    # 1. Cluster Readiness Summary
    add_heading "1. 🚦 Cluster Readiness Summary"
    if [[ "$CRASHING" -eq 0 ]]; then
    echo "**βœ… Cluster is healthy and ready for release.**" >> "$REPORT"
    else
    echo "**⚠️ $CRASHING CrashLoopBackOff pod(s) detected. Investigate before release.**" >> "$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. Expected vs Running Pods
    add_heading "4. πŸ”„ 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"

    # 5. Pod Health Summary
    add_heading "5. βœ… Pod Health Summary"
    echo "- Total Pods: **$POD_TOTAL**" >> "$REPORT"
    echo "- Running Pods: **$POD_RUNNING**" >> "$REPORT"
    echo "- CrashLoopBackOff Pods: **$CRASHING**" >> "$REPORT"

    # 6. CrashLoopBackOff Pods
    if [[ "$CRASHING" -gt 0 ]]; then
    add_heading "6. 🚫 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

    # 7. Top Resource Usage
    add_heading "7. πŸ“Š 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"

    # 8. Recent Warning Events
    add_heading "8. πŸ”₯ 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"

    # 9. Image Versions
    add_heading "9. πŸ§ͺ 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"

    echo ""
    echo "βœ… Report generated: $REPORT"