forked from PinSpace-Org/GistPin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandle-interruption.sh
More file actions
87 lines (74 loc) · 2.38 KB
/
Copy pathhandle-interruption.sh
File metadata and controls
87 lines (74 loc) · 2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env bash
# Handles AWS EC2 spot instance interruption notices.
# Polls the IMDS, cordons the node, evicts pods, and notifies.
# Designed to run inside the spot-handler DaemonSet pod.
set -euo pipefail
NODE_NAME="${NODE_NAME:-$(hostname)}"
DRAIN_GRACE_PERIOD="${DRAIN_GRACE_PERIOD:-120}"
IMDS_URL="http://169.254.169.254/latest/meta-data/spot/instance-action"
REBALANCE_URL="http://169.254.169.254/latest/meta-data/events/recommendations/rebalance"
WEBHOOK_URL="${WEBHOOK_URL:-}"
POLL_INTERVAL="${POLL_INTERVAL:-5}"
log() { echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] $*"; }
notify() {
local msg="$1"
log "$msg"
if [[ -n "$WEBHOOK_URL" ]]; then
curl -s -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"text\": \"[spot-handler] $msg\"}" || true
fi
}
check_imds() {
# Returns HTTP status 200 if the notice is present, 404 otherwise
curl -s -o /dev/null -w "%{http_code}" \
--max-time 2 \
-H "X-aws-ec2-metadata-token: $(get_imds_token)" \
"$1"
}
get_imds_token() {
curl -s -X PUT \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600" \
--max-time 2 \
"http://169.254.169.254/latest/api/token"
}
cordon_node() {
log "Cordoning node $NODE_NAME"
kubectl cordon "$NODE_NAME"
}
drain_node() {
log "Draining node $NODE_NAME (grace period: ${DRAIN_GRACE_PERIOD}s)"
kubectl drain "$NODE_NAME" \
--ignore-daemonsets \
--delete-emptydir-data \
--force \
--grace-period="$DRAIN_GRACE_PERIOD" \
--timeout="$((DRAIN_GRACE_PERIOD + 30))s" || {
log "WARNING: drain did not complete cleanly — continuing"
}
}
handle_interruption() {
notify "SPOT INTERRUPTION detected on node $NODE_NAME — starting graceful eviction"
cordon_node
drain_node
notify "Eviction complete on $NODE_NAME. Node is safe to terminate."
}
handle_rebalance() {
notify "REBALANCE RECOMMENDATION received for node $NODE_NAME — cordoning for proactive replacement"
cordon_node
}
log "Spot interruption handler started (node=$NODE_NAME, poll=${POLL_INTERVAL}s)"
while true; do
interruption_status=$(check_imds "$IMDS_URL")
if [[ "$interruption_status" == "200" ]]; then
handle_interruption
# After handling, wait for actual termination (max 2 min)
sleep 120
exit 0
fi
rebalance_status=$(check_imds "$REBALANCE_URL")
if [[ "$rebalance_status" == "200" ]]; then
handle_rebalance
fi
sleep "$POLL_INTERVAL"
done