Created
October 24, 2025 02:36
-
-
Save iwanhae/cdc30ce37af747b41c941c58b736f7fc to your computer and use it in GitHub Desktop.
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
| #!/usr/bin/env python3 | |
| import json | |
| from collections import defaultdict | |
| import subprocess | |
| def parse_memory(memory_str): | |
| """메모리 문자열을 MB로 변환""" | |
| if not memory_str: | |
| return 0 | |
| # 'n' 접미사 처리 (나노바이트) | |
| if memory_str.endswith("n"): | |
| try: | |
| value = float(memory_str[:-1]) | |
| return value / (1024**2 * 1e9) # 나노바이트 -> MB로 변환 (1 byte = 10^9 n) | |
| except Exception: | |
| return 0 | |
| units = {"Ki": 1024, "Mi": 1024**2, "Gi": 1024**3} | |
| for unit, divisor in units.items(): | |
| if memory_str.endswith(unit): | |
| try: | |
| value = float(memory_str[:-2]) | |
| return value * divisor / (1024**2) # MB로 변환 | |
| except Exception: | |
| return 0 | |
| try: | |
| return float(memory_str) / (1024**2) # 바이트 -> MB | |
| except Exception: | |
| return 0 | |
| def parse_cpu(cpu_str): | |
| """CPU 문자열을 millicore로 변환""" | |
| if not cpu_str: | |
| return 0 | |
| # 'n' 접미사 처리 (나노코어) | |
| if cpu_str.endswith("n"): | |
| try: | |
| value = float(cpu_str[:-1]) | |
| return value / 1e6 # 나노코어 -> millicore로 변환 (1 core = 10^9 n) | |
| except Exception: | |
| return 0 | |
| # 'm' 접미사 처리 (millicore) | |
| if cpu_str.endswith("m"): | |
| try: | |
| return float(cpu_str[:-1]) | |
| except Exception: | |
| return 0 | |
| try: | |
| return float(cpu_str) * 1000 | |
| except Exception: | |
| return 0 | |
| def parse_kubernetes_metrics(metrics_data): | |
| """Kubernetes metrics를 파싱하여 네임스페이스별 CPU, Memory 사용량 계산""" | |
| namespace_stats = defaultdict(lambda: {"cpu": 0, "memory": 0, "pod_count": 0}) | |
| for metric in metrics_data: | |
| try: | |
| namespace = metric.get("metadata", {}).get("namespace", "Unknown") | |
| containers = metric.get("containers", []) | |
| for container in containers: | |
| usage = container.get("usage", {}) | |
| # CPU 사용량 파싱 | |
| cpu_str = usage.get("cpu", "0") | |
| cpu_value = parse_cpu(cpu_str) | |
| # Memory 사용량 파싱 | |
| memory_str = usage.get("memory", "0") | |
| memory_value = parse_memory(memory_str) | |
| namespace_stats[namespace]["cpu"] += cpu_value | |
| namespace_stats[namespace]["memory"] += memory_value | |
| namespace_stats[namespace]["pod_count"] += 1 | |
| except Exception as e: | |
| print(f"에러 발생: {e}") | |
| continue | |
| return namespace_stats | |
| # usage.jsonl 파일 로드 | |
| metrics_data = [] | |
| try: | |
| # kubectl 명령어 실행 | |
| result = subprocess.run( | |
| 'kubectl get pods.metrics.k8s.io -A -o json | jq ".items[]" -c > usage.jsonl', | |
| shell=True, | |
| capture_output=True, | |
| text=True, | |
| ) | |
| if result.returncode != 0: | |
| print(f"kubectl 명령어 실행 오류: {result.stderr}") | |
| metrics_data = [] | |
| else: | |
| print("usage.jsonl 파일이 생성되었습니다.") | |
| # 생성된 파일 로드 | |
| with open("usage.jsonl", "r") as f: | |
| for line in f: | |
| if line.strip(): | |
| metrics_data.append(json.loads(line)) | |
| except Exception as e: | |
| print(f"에러 발생: {e}") | |
| metrics_data = [] | |
| print(f"로드된 메트릭 데이터: {len(metrics_data)}개") | |
| if metrics_data: | |
| print("\n첫 번째 항목 샘플:") | |
| print(json.dumps(metrics_data[0], indent=2)[:500]) | |
| # 계산 실행 | |
| namespace_stats = parse_kubernetes_metrics(metrics_data) | |
| # 결과를 딕셔너리 리스트로 변환 | |
| results = [ | |
| { | |
| "Namespace": ns, | |
| "CPU (millicore)": round(stats["cpu"], 2), | |
| "Memory (MB)": round(stats["memory"], 2), | |
| "Pod Count": stats["pod_count"], | |
| } | |
| for ns, stats in sorted(namespace_stats.items()) | |
| ] | |
| # 백분율 계산 | |
| total_cpu = sum(r["CPU (millicore)"] for r in results) | |
| total_memory = sum(r["Memory (MB)"] for r in results) | |
| # 0으로 나누기 방지 | |
| for result in results: | |
| if total_cpu > 0: | |
| result["CPU %"] = round(result["CPU (millicore)"] / total_cpu * 100, 2) | |
| else: | |
| result["CPU %"] = 0.0 | |
| if total_memory > 0: | |
| result["Memory %"] = round(result["Memory (MB)"] / total_memory * 100, 2) | |
| else: | |
| result["Memory %"] = 0.0 | |
| # CPU 사용량 기준으로 정렬 | |
| results = sorted(results, key=lambda x: x["CPU (millicore)"], reverse=True) | |
| print("=" * 100) | |
| print("네임스페이스별 리소스 사용량 (CPU 기준 정렬)") | |
| print("=" * 100) | |
| # 테이블 출력 (헤더) | |
| print( | |
| f"{'Namespace':70s} {'CPU (millicore)':>18s} {'CPU %':>8s} {'Memory (MB)':>15s} {'Memory %':>8s} {'Pod Count':>10s}" | |
| ) | |
| print("-" * 130) | |
| # 테이블 출력 (데이터) | |
| for result in results: | |
| print( | |
| f"{result['Namespace']:70s} {result['CPU (millicore)']:>18.2f} {result['CPU %']:>7.2f}% {result['Memory (MB)']:>14.2f} {result['Memory %']:>7.2f}% {result['Pod Count']:>10d}" | |
| ) | |
| print("=" * 100) | |
| print("\n총 요약:") | |
| print(f"- 총 CPU 사용량: {total_cpu:.2f} millicore (100.00%)") | |
| print( | |
| f"- 총 Memory 사용량: {total_memory:.2f} MB ({total_memory / 1024:.2f} GB) (100.00%)" | |
| ) | |
| print(f"- 총 Pod 수: {sum(r['Pod Count'] for r in results)}") | |
| top_cpu = results[:20] | |
| for result in top_cpu: | |
| cpu_bar = "█" * int(result["CPU %"] / 2) | |
| print( | |
| f" {result['Namespace']:70s} {result['CPU (millicore)'] / 1000:10.2f} core ({result['CPU %']:6.2f}%) {cpu_bar}" | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment