여러 Kubernetes 클러스터를 운영할 때, 중앙 관리 시스템에 등록되지 않은 노드들의 리소스 상태를 주기적으로 수집해야 하는 상황이 발생합니다. 이러한 경우 각 클러스터의 마스터 노드에 간단한 데이터 수집 스크립트를 배포하고, 중앙 서버에서 Ansible을 통해 해당 스크립트를 원격 실행한 뒤 그 결과를 엑셀 파일로 취합하는 자동화 파이프라인을 구축할 수 있습니다.
각 마스터 노드에서는 /root/cluster_metrics.sh와 같은 스크립트가 실행되어 클러스터의 핵심 지표 9개를 줄바꿈으로 구분하여 출력한다고 가정해 보겠습니다.
Cluster-A
12
45
1024
2048
512
89
150
300
450
이제 중앙 제어 노드에서 파이썬을 사용하여 Ansible ad-hoc 명령을 실행하고, openpyxl 라이브러리로 결과를 구조화된 엑셀 시트에 저장하는 코드를 작성해 보겠습니다. 기존 subprocess.Popen 대신 현대적인 파이썬 관례에 맞게 subprocess.run을 사용하며, 데이터 무결성 검사와 로깅 기능을 추가하여 안정성을 높였습니다.
import subprocess
import openpyxl
from datetime import datetime
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def collect_cluster_metrics():
# 타겟 클러스터 마스터 노드 IP 목록
target_nodes = ["192.168.1.10", "192.168.2.20", "192.168.3.30"]
# 원격에서 실행할 데이터 수집 스크립트 경로
remote_script_path = "/root/cluster_metrics.sh"
# 엑셀 헤더 정의 (노드 IP, 실행 결과 상태, 그리고 9개의 메트릭 데이터)
excel_headers = [
"Node_IP", "Execution_Status", "Metric_1", "Metric_2", "Metric_3",
"Metric_4", "Metric_5", "Metric_6", "Metric_7", "Metric_8", "Metric_9"
]
# 새로운 워크북 생성 및 활성 시트 설정
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "K8s_Cluster_Report"
ws.append(excel_headers)
for node_ip in target_nodes:
logging.info(f"Executing Ansible command on {node_ip}...")
# Ansible ad-hoc 명령 실행
ansible_cmd = [
"ansible", node_ip,
"-m", "shell",
"-a", f"bash {remote_script_path}"
]
try:
result = subprocess.run(
ansible_cmd,
capture_output=True,
text=True,
check=True
)
# 표준 출력에서 불필요한 공백 제거 및 줄바꿈으로 분할
raw_metrics = result.stdout.strip().split('\n')
# 데이터 무결성 검사 (9개의 데이터가 정상적으로 반환되었는지 확인)
if len(raw_metrics) >= 9:
# 노드 IP, 성공 상태, 그리고 추출된 9개의 메트릭 데이터 행 구성
row_data = [node_ip, "SUCCESS"] + raw_metrics[:9]
else:
# 데이터가 부족할 경우 예외 처리
row_data = [node_ip, "DATA_INCOMPLETE", f"Expected 9 metrics, got {len(raw_metrics)}"]
except subprocess.CalledProcessError as e:
# 명령 실행 실패 시 에러 메시지 기록
error_msg = e.stderr.strip() if e.stderr else "Unknown error"
row_data = [node_ip, "FAILED", error_msg]
except Exception as e:
row_data = [node_ip, "ERROR", str(e)]
ws.append(row_data)
# 타임스탬프가 포함된 파일명으로 저장
current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
output_filename = f"k8s_metrics_report_{current_time}.xlsx"
wb.save(output_filename)
logging.info(f"Report successfully saved to {output_filename}")
if __name__ == "__main__":
collect_cluster_metrics()