Last active
May 26, 2025 18:57
-
-
Save felipou/0b3248796fe8cf026519648cd60288f6 to your computer and use it in GitHub Desktop.
trace_k8s_pod_connections.sh
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 | |
# Created with help from ChatGPT, so beware, use at your own risk. Tested with EKS nodes | |
# running Amazon Linux 2. | |
set -euo pipefail | |
TARGET_PORT=6379 # Change to your target port | |
TARGET_IP="" # Optional: set to filter by IP | |
declare -A seen_netns | |
declare -A container_id_to_podname | |
declare -A pid_to_container_id | |
# Get container metadata in bulk and store in a map | |
load_all_container_metadata() { | |
while read -r cid name ns; do | |
container_id_to_podname["$cid"]="$name/$ns" | |
done < <( | |
crictl --runtime-endpoint=unix:///run/containerd/containerd.sock ps -o json \ | |
| jq -r '.containers[] | [.id, .labels["io.kubernetes.pod.name"], .labels["io.kubernetes.pod.namespace"]] | @tsv' | |
) | |
} | |
# Try to extract the container ID for a given PID by reading cgroup | |
get_container_id_from_pid() { | |
local pid="$1" | |
local cid | |
cid=$(grep -aoE '([a-f0-9]{64})' "/proc/$pid/cgroup" 2>/dev/null | head -n1 || true) | |
[[ -z "$cid" ]] && echo "warn: no container ID found for pid $pid" >&2 | |
echo "$cid" | |
} | |
# Get the pod name from container ID (from preloaded map) | |
get_pod_name_from_container_id() { | |
local cid="$1" | |
if [[ -z "$cid" ]]; then | |
echo "unknown" | |
else | |
echo "${container_id_to_podname[$cid]:-unknown}" | |
fi | |
} | |
handle_connection_line() { | |
local line="$1" | |
# Extract remote IP and port | |
local remote=$(echo "$line" | awk '{print $5}') | |
local ip=${remote%:*} | |
local port=${remote##*:} | |
# Match port and IP | |
[[ "$port" -eq "$TARGET_PORT" ]] || continue | |
[[ -n "$TARGET_IP" && "$ip" != "$TARGET_IP" ]] && continue | |
# Extract PID from line, e.g., pid=1234 | |
local proc_info=$(echo "$line" | grep -oP 'pid=\d+') | |
local real_pid=$(echo "$proc_info" | grep -oP '\d+') | |
# Validate real_pid | |
[[ -z "$real_pid" ]] && continue | |
local container_id=$(get_container_id_from_pid "$real_pid") | |
local pod_name=$(get_pod_name_from_container_id "$container_id") | |
echo "PID: $real_pid | Remote: $ip:$port | Proc: $proc_info | Pod: $pod_name" | |
} | |
# Parse the output of `ss -tnp` for established connections to TARGET_PORT and optional TARGET_IP | |
parse_connections() { | |
local owner_pid="$1" | |
((sudo nsenter -t "$owner_pid" -n ss -tnp 2>/dev/null | grep ESTAB) || true) | while read -r line; do | |
handle_connection_line "$line" | |
done | |
} | |
# Loop through all netns, de-duplicated | |
scan_all_netns() { | |
for pid in $(ls /proc | grep -E '^[0-9]+$'); do | |
local netns_path="/proc/$pid/ns/net" | |
[[ -e "$netns_path" ]] || continue | |
local netns_inode=$(readlink "$netns_path") | |
[[ -n "$netns_inode" && -z "${seen_netns[$netns_inode]:-}" ]] || continue | |
seen_netns["$netns_inode"]=1 | |
parse_connections "$pid" | |
done | |
} | |
main() { | |
load_all_container_metadata | |
scan_all_netns | |
} | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment