node-labeling2

진웅·2025년 6월 4일

K8S Basics

목록 보기
7/40
import pandas as pd
from kubernetes import client, config
import logging
import os
import sys
from tabulate import tabulate

# 로깅 설정
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def load_excel_data(file_path):
    """엑셀 파일을 읽고 클러스터별 데이터를 반환"""
    try:
        logger.info(f"Reading Excel file: {file_path}")
        xl = pd.ExcelFile(file_path)
        cluster_data = {}
        for sheet_name in xl.sheet_names:
            df = pd.read_excel(xl, sheet_name=sheet_name)
            cluster_data[sheet_name] = df[['hostname', 'ip', '구입 목적']].dropna()
        return cluster_data
    except Exception as e:
        logger.error(f"엑셀 파일 로드 실패: {e}")
        return {}

def load_csv_data(file_path):
    """CSV 파일을 읽고 단일 클러스터 데이터를 반환"""
    try:
        logger.info(f"Reading CSV file: {file_path}")
        df = pd.read_csv(file_path)
        return {"default_cluster": df[['hostname', 'ip', '구입 목적']].dropna()}
    except Exception as e:
        logger.error(f"CSV 파일 로드 실패: {e}")
        return {}

def get_node_by_ip(v1, target_ip):
    """IP를 기반으로 노드 이름 찾기"""
    nodes = v1.list_node().items
    for node in nodes:
        for address in node.status.addresses:
            if address.type == "InternalIP" and address.address == target_ip:
                return node.metadata.name
    return None

def apply_node_label(v1, node_name, label_key):
    """노드에 라벨 적용"""
    try:
        body = {
            "metadata": {
                "labels": {label_key: "true"}
            }
        }
        v1.patch_node(node_name, body)
        logger.info(f"노드 {node_name}에 라벨 {label_key}=true 적용 성공")
    except Exception as e:
        logger.error(f"노드 {node_name} 라벨 적용 실패: {e}")

def list_node_labels(v1):
    """현재 클러스터의 노드 이름과 라벨을 표 형식으로 출력"""
    try:
        nodes = v1.list_node().items
        if not nodes:
            logger.info("노드가 없습니다.")
            return

        # 모든 노드의 라벨 키 수집
        all_labels = set()
        node_data = {}
        for node in nodes:
            node_name = node.metadata.name
            labels = node.metadata.labels or {}
            node_data[node_name] = labels
            all_labels.update(labels.keys())

        # 정렬된 라벨 목록
        all_labels = sorted(all_labels)

        # 표 데이터 준비
        table_data = []
        for label in all_labels:
            row = [label]
            for node in nodes:
                node_name = node.metadata.name
                row.append(node_data[node_name].get(label, ""))
            table_data.append(row)

        # 노드 이름 헤더
        headers = ["Label"] + [node.metadata.name for node in nodes]

        # 표 출력
        print(tabulate(table_data, headers=headers, tablefmt="grid"))

    except Exception as e:
        logger.error(f"노드 목록 조회 실패: {e}")

def manage_node_labels(arg, kubeconfig_dir):
    """메인 함수: 인수에 따라 노드 라벨 관리 또는 목록 출력"""
    if arg.lower() == "list":
        # "list"인 경우, 노드 목록과 라벨 출력
        kubeconfig_path = os.path.join(kubeconfig_dir, "default-kubeconfig")
        if not os.path.exists(kubeconfig_path):
            logger.error(f"default-kubeconfig 파일이 존재하지 않습니다: {kubeconfig_path}")
            return
        try:
            logger.info(f"Loading kubeconfig for list: {kubeconfig_path}")
            config.load_kube_config(kubeconfig_path)
            v1 = client.CoreV1Api()
            list_node_labels(v1)
        except Exception as e:
            logger.error(f"클러스터 연결 실패: {e}")
    else:
        # 파일 경로인 경우, 기존 로직 수행
        file_path = arg
        if file_path.endswith('.xlsx'):
            cluster_data = load_excel_data(file_path)
        elif file_path.endswith('.csv'):
            cluster_data = load_csv_data(file_path)
        else:
            logger.error("지원하지 않는 파일 형식입니다. 엑셀(.xlsx) 또는 CSV(.csv) 파일을 사용하세요.")
            return

        if not cluster_data:
            logger.error("클러스터 데이터 로드 실패. 프로그램 종료.")
            return

        for cluster_name, df in cluster_data.items():
            kubeconfig_path = os.path.join(kubeconfig_dir, f"{cluster_name}-kubeconfig")
            if not os.path.exists(kubeconfig_path):
                logger.warning(f"{cluster_name}에 대한 kubeconfig 파일 없음 ({kubeconfig_path}). 건너뜀.")
                continue

            try:
                logger.info(f"Loading kubeconfig for {cluster_name}: {kubeconfig_path}")
                config.load_kube_config(kubeconfig_path)
                v1 = client.CoreV1Api()
                logger.info(f"{cluster_name} 클러스터 연결 성공")
            except Exception as e:
                logger.error(f"{cluster_name} 클러스터 연결 실패: {e}")
                continue

            for _, row in df.iterrows():
                ip = row['ip']
                purpose = row['구입 목적']
                node_name = get_node_by_ip(v1, ip)
                if node_name:
                    apply_node_label(v1, node_name, purpose)
                else:
                    logger.warning(f"IP {ip}에 해당하는 노드 없음 ({cluster_name})")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        logger.error("사용법: python script.py <파일 경로 또는 'list'>")
        sys.exit(1)

    arg = sys.argv[1]
    kubeconfig_dir = "./kubeconfigs"  # 기본 kubeconfig 디렉토리
    manage_node_labels(arg, kubeconfig_dir)```
profile
bytebliss

0개의 댓글