Setting the file. One moment.
Cluster Snapshot · AKS Troubleshooting · microsoft/azure-skills · Skills Docs
ContentsBack to the top of the page scripts/cluster-snapshot.sh
scripts/ cluster-snapshot.sh
Shell · 97 lines · 4 KB
${
AKS_RESOURCE_GROUP
:-
}
}
"
12 CLUSTER = " ${2 :- ${ AKS_CLUSTER_NAME :- } } "
13 CONTEXT = " ${3 :- ${ AKS_KUBE_CONTEXT :- } } "
14
15 [ -n " $RG " ] && [ -n " $CLUSTER " ] && [ -n " $CONTEXT " ] || {
16 echo "usage: cluster-snapshot.sh <resource-group> <cluster-name> <kube-context>" >&2
17 exit 2
18 }
19
20 command -v az > /dev/null 2>&1 || {
21 echo "Azure CLI (az) is required. Install it from https://aka.ms/installazurecli and retry." >&2
22 exit 2
23 }
24 command -v kubectl > /dev/null 2>&1 || {
25 echo "kubectl is required. Install it from https://kubernetes.io/docs/tasks/tools/ and retry." >&2
26 exit 2
27 }
28 command -v jq > /dev/null 2>&1 || {
29 echo "jq is required. Install it from https://jqlang.github.io/jq/download/ and retry." >&2
30 exit 2
31 }
32
33 if [ -n "${ AKS_SUBSCRIPTION_ID :- }" ]; then
34 aks_json = $( az aks show --subscription " $AKS_SUBSCRIPTION_ID " \
35 -g " $RG " -n " $CLUSTER " -o json 2> /dev/null )
36 else
37 aks_json = $( az aks show -g " $RG " -n " $CLUSTER " -o json 2> /dev/null )
38 fi || {
39 echo "AKS resource target is inaccessible" >&2
40 exit 2
41 }
42 kube_server = $( kubectl --context " $CONTEXT " config view --minify \
43 -o jsonpath='{.clusters[0].cluster.server}' 2> /dev/null ) || {
44 echo "kube context is inaccessible" >&2
45 exit 2
46 }
47 normalize () {
48 printf '%s' " $1 " | tr '[:upper:]' '[:lower:]' |
49 sed -E 's#^[a-z]+://##; s#/.*$##; s#:[0-9]+$##; s/\.$//'
50 }
51 kube_host = $( normalize " $kube_server " )
52 public_host = $( normalize "$( printf '%s' " $aks_json " | jq -r '.fqdn // empty')" )
53 private_host = $( normalize "$( printf '%s' " $aks_json " | jq -r '.privateFqdn // empty')" )
54 [ -n " $kube_host " ] &&
55 { [ " $kube_host " = " $public_host " ] || [ " $kube_host " = " $private_host " ]; } || {
56 echo "kube context does not target the named AKS cluster" >&2
57 exit 2
58 }
59 kube () {
60 kubectl --context " $CONTEXT " " $@ "
61 }
62
63 echo "=== Cluster Snapshot $( date -u +%Y-%m-%dT%H:%M:%SZ) ==="
64 echo "targetProof=matched cluster= $RG / $CLUSTER context= $CONTEXT "
65
66 echo ""
67 echo "--- Nodes ---"
68 kube get nodes -o wide 2> /dev/null || echo "(kubectl not configured)"
69
70 echo ""
71 echo "--- Node Conditions (non-Ready or pressure) ---"
72 kube get nodes -o json 2> /dev/null | \
73 jq -r '.items[] | .metadata.name as $n | .status.conditions[] | select(.type != "Ready" and .status == "True") | [$n, .type, .reason] | @tsv' 2> /dev/null || true
74 kube get nodes -o json 2> /dev/null | \
75 jq -r '.items[] | .metadata.name as $n | .status.conditions[] | select(.type == "Ready" and .status != "True") | [$n, .type, .status, .reason] | @tsv' 2> /dev/null || true
76
77 echo ""
78 echo "--- Pods Not Running/Succeeded (all namespaces) ---"
79 kube get pods -A --field-selector 'status.phase!=Running,status.phase!=Succeeded' 2> /dev/null || echo "(none or error)"
80
81 echo ""
82 echo "--- Recent Warning Events (last 30m) ---"
83 kube get events -A --field-selector type=Warning --sort-by= '.lastTimestamp' 2> /dev/null | tail -20 || true
84
85 echo ""
86 echo "--- Resource Pressure ---"
87 kube top nodes 2> /dev/null || echo "(metrics-server not available)"
88
89 if [ -n " $RG " ] && [ -n " $CLUSTER " ]; then
90 echo ""
91 echo "--- AKS Cluster State ---"
92 printf '%s' " $aks_json " | \
93 jq '{provisioningState, powerState: .powerState.code, kubernetesVersion, networkPlugin: .networkProfile.networkPlugin, networkPolicy: .networkProfile.networkPolicy, nodePools: [.agentPoolProfiles[] | {name, count, vmSize, provisioningState, mode, osType}]}' 2> /dev/null || echo "(unable to project AKS state)"
94 fi
95
96 echo ""
97 echo "=== End Snapshot ==="