Skip to content

Instantly share code, notes, and snippets.

@felipou
Last active May 26, 2025 18:57
Show Gist options
  • Save felipou/0b3248796fe8cf026519648cd60288f6 to your computer and use it in GitHub Desktop.
Save felipou/0b3248796fe8cf026519648cd60288f6 to your computer and use it in GitHub Desktop.
trace_k8s_pod_connections.sh
#!/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