import pandas as pd
from kubernetes import client, config
import logging
import os
import sys
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def load_excel_data(file_path):
"""엑셀 파일을 읽고 클러스터별 데이터를 반환"""
try:
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:
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
for node in nodes:
node_name = node.metadata.name
labels = node.metadata.labels or {}
print(f"Node: {node_name}")
for key, value in labels.items():
print(f" {key}: {value}")
print()
except Exception as e:
logger.error(f"노드 목록 조회 실패: {e}")
def manage_node_labels(arg, kubeconfig_dir):
"""메인 함수: 인수에 따라 노드 라벨 관리 또는 목록 출력"""
if arg.lower() == "list":
try:
config.load_kube_config(os.path.join(kubeconfig_dir, "default-kubeconfig"))
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:
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"
manage_node_labels(arg, kubeconfig_dir)하세요