#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
show_help() {
echo "사용법: $0 [OPTIONS]"
echo ""
echo "옵션:"
echo " -h, --help 도움말 표시"
echo " -v, --verbose 상세 정보 표시"
echo " -n, --namespace 특정 네임스페이스 파드만 계산"
echo " -s, --sort 파드 수로 정렬 (기본: 노드명 정렬)"
echo " -l, --limit 파드 수 제한 표시 (기본: 110)"
echo " -f, --format 출력 형식 (table|json|csv)"
echo ""
echo "예시:"
echo " $0 # 기본 실행"
echo " $0 -v # 상세 정보 포함"
echo " $0 -n kube-system # kube-system 네임스페이스만"
echo " $0 -s # 파드 수로 정렬"
echo " $0 -f json # JSON 형태로 출력"
}
VERBOSE=false
NAMESPACE=""
SORT_BY_COUNT=false
POD_LIMIT=110
FORMAT="table"
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-v|--verbose)
VERBOSE=true
shift
;;
-n|--namespace)
NAMESPACE="$2"
shift 2
;;
-s|--sort)
SORT_BY_COUNT=true
shift
;;
-l|--limit)
POD_LIMIT="$2"
shift 2
;;
-f|--format)
FORMAT="$2"
shift 2
;;
*)
echo "알 수 없는 옵션: $1"
show_help
exit 1
;;
esac
done
if ! command -v kubectl &> /dev/null; then
echo -e "{NC}"
exit 1
fi
if ! kubectl cluster-info &> /dev/null; then
echo -e "{NC}"
exit 1
fi
echo -e "{NC}"
echo ""
if [[ "$VERBOSE" == true ]]; then
echo -e "{NC}"
fi
NS_OPTION=""
if [[ -n "$NAMESPACE" ]]; then
NS_OPTION="--namespace={YELLOW}네임스페이스 필터: {NC}"
echo ""
fi
calculate_pod_counts() {
local temp_file="/tmp/node_pod_counts.tmp"
# 모든 노드 목록 가져오기
kubectl get nodes --no-headers -o custom-columns="NAME:.metadata.name" > "$temp_file"
# 결과 저장을 위한 배열
declare -A node_pod_counts
declare -A node_status
declare -A node_max_pods
# 각 노드별 파드 수 계산
while IFS= read -r node; do
if [[ -n "$NAMESPACE" ]]; then
pod_count=$(kubectl get pods $NS_OPTION --field-selector=spec.nodeName="$node" --no-headers 2>/dev/null | wc -l)
else
pod_count=$(kubectl get pods --all-namespaces --field-selector=spec.nodeName="$node" --no-headers 2>/dev/null | wc -l)
fi
# 노드 상태 확인
node_ready=$(kubectl get node "$node" --no-headers -o custom-columns="STATUS:.status.conditions[?(@.type=='Ready')].status" 2>/dev/null)
if [[ "$node_ready" == "True" ]]; then
status="Ready"
else
status="NotReady"
fi
# 노드 최대 파드 수 확인
max_pods=$(kubectl get node "$node" -o jsonpath='{.status.capacity.pods}' 2>/dev/null)
node_pod_counts["$node"]="$pod_count"
node_status["$node"]="$status"
node_max_pods["$node"]="$max_pods"
done < "$temp_file"
rm -f "$temp_file"
# 결과 출력
case "$FORMAT" in
"json")
output_json
;;
"csv")
output_csv
;;
*)
output_table
;;
esac
}
output_table() {
printf "%-20s %-10s %-10s %-10s %-10s\n" "노드명" "파드수" "최대파드" "사용률" "상태"
printf "%-20s %-10s %-10s %-10s %-10s\n" "----" "----" "----" "----" "----"
# 정렬 방식 결정
if [[ "$SORT_BY_COUNT" == true ]]; then
# 파드 수로 정렬
for node in $(printf '%s\n' "${!node_pod_counts[@]}" | sort -k1,1); do
print_node_info "$node"
done | sort -k2,2nr
else
# 노드명으로 정렬
for node in $(printf '%s\n' "${!node_pod_counts[@]}" | sort); do
print_node_info "$node"
done
fi
echo ""
print_summary
}
print_node_info() {
local node="{node_pod_counts[$node]}"
local max_pods="{node_max_pods[node]}"
local status="{node_status[node]}"
local usage_percent=""
if [[ -n "$max_pods" && "$max_pods" -gt 0 ]]; then
usage_percent=$(echo "scale=1; $pod_count * 100 / $max_pods" | bc -l 2>/dev/null)
usage_percent="${usage_percent}%"
else
usage_percent="N/A"
fi
# 색상 적용
local color=""
if [[ "$status" != "Ready" ]]; then
color="$RED"
elif [[ "$pod_count" -ge "$POD_LIMIT" ]]; then
color="$RED"
elif [[ "$pod_count" -ge $((POD_LIMIT * 80 / 100)) ]]; then
color="$YELLOW"
else
color="$GREEN"
fi
printf "${color}%-20s %-10s %-10s %-10s %-10s${NC}\n" \
"$node" "$pod_count" "$max_pods" "$usage_percent" "$status"
}
output_json() {
echo "{"
echo " \"timestamp\": \"{NAMESPACE:-all}\","
echo " \"nodes\": ["
local first=true
for node in $(printf '%s\n' "${!node_pod_counts[@]}" | sort); do
if [[ "$first" == true ]]; then
first=false
else
echo ","
fi
local pod_count="${node_pod_counts[$node]}"
local max_pods="${node_max_pods[$node]}"
local status="${node_status[$node]}"
echo " {"
echo " \"name\": \"$node\","
echo " \"pod_count\": $pod_count,"
echo " \"max_pods\": ${max_pods:-null},"
echo " \"status\": \"$status\""
echo -n " }"
done
echo ""
echo " ]"
echo "}"
}
output_csv() {
echo "노드명,파드수,최대파드,사용률,상태"
for node in $(printf '%s\n' "${!node_pod_counts[@]}" | sort); do
local pod_count="${node_pod_counts[$node]}"
local max_pods="${node_max_pods[$node]}"
local status="${node_status[$node]}"
local usage_percent=""
if [[ -n "$max_pods" && "$max_pods" -gt 0 ]]; then
usage_percent=$(echo "scale=1; $pod_count * 100 / $max_pods" | bc -l 2>/dev/null)
usage_percent="${usage_percent}%"
else
usage_percent="N/A"
fi
echo "$node,$pod_count,$max_pods,$usage_percent,$status"
done
}
print_summary() {
local total_nodes=0
local total_pods=0
local ready_nodes=0
local overloaded_nodes=0
for node in "${!node_pod_counts[@]}"; do
total_nodes=$((total_nodes + 1))
total_pods=$((total_pods + ${node_pod_counts[$node]}))
if [[ "${node_status[$node]}" == "Ready" ]]; then
ready_nodes=$((ready_nodes + 1))
fi
if [[ "${node_pod_counts[$node]}" -ge "$POD_LIMIT" ]]; then
overloaded_nodes=$((overloaded_nodes + 1))
fi
done
echo -e "${BLUE}=== 요약 정보 ===${NC}"
echo "총 노드 수: $total_nodes"
echo "준비된 노드: $ready_nodes"
echo "총 파드 수: $total_pods"
echo "과부하 노드: $overloaded_nodes (파드 수 >= $POD_LIMIT)"
if [[ "$VERBOSE" == true ]]; then
echo ""
echo -e "${YELLOW}상세 정보:${NC}"
echo "- 네임스페이스: ${NAMESPACE:-전체}"
echo "- 정렬 방식: $([ "$SORT_BY_COUNT" == true ] && echo "파드 수" || echo "노드명")"
echo "- 출력 형식: $FORMAT"
echo "- 파드 제한: $POD_LIMIT"
fi
}
calculate_pod_counts