슈퍼컴퓨터 관리자로 일하기 시작한 지 약 세 달째가 되었다. 대략적으로 하고 있는 일들은 익숙해졌다. 가장 중요한 일 중 하나는 비정상(abnormal)으로 작동하고 있는 노드들을 고치는 것이다. 주로 소프트웨어적인 측면에서 발생하는 문제는 HPC(High Performance Computer)를 클러스터링 할 때, Slurm이라는 툴을 사용하는데, Slurm에서 node의 상태가 drain으로 찍히는 경우이다.
이러한 경우에는 먼저 ssh로 접속하여 htop같은 명령어를 통해 리소스 사용량을 조회하고, slurm의 로그 파일을 읽어 어떤 문제가 있는지 확인하고, reboot 명령어를 통해 서버를 재실행하는 방법으로 해결하곤 한다.
소프트웨어적인 측면이 아니라 하드웨어적인 측면에서도 비정상(abnormal)이 있다. 서버실에서 특정 노드에서 빨간불이 들어와 하드웨어를 재부팅해야하는 것이었다. 이러한 문제점을 해결하기 위해서 먼저 노드를 drain으로 설정하여, Slurm에서 작업을 컨트롤하는 slurmctl이 해당 문제가 되는 비정상 노드에 job이 들어가지 않게 처리하고, 해당 노드에서 작업이 끝났다면 halt로 해당 노드를 종료하고, 물리적으로 재부팅하는 방법이었다. 그렇게 재부팅을 하면 iPXE라는 인터넷을 통해서 운영체제 및 slurmd 서비스 등을 다시 올리는 구조로 되어있다.
그렇게 이따금씩 비정상적인 노드들을 정비하면서, 서버가 다운되는 한 가지 사항을 확인했다. 그것은 바로 파이썬 가상환경 프로그램인 아나콘다를 사용하는 경우 slurmctl이 CPU 사용량을 정확하게 측정하지 못하게 되면서, slurmctl이 job을 같은 노드에 집어넣으면서 문제가 발생하게 되는 것이다. slurmctl은 일반적으로 노드의 CPU load를 50~60%로 유지하는데, 아나콘다와 같은 가상환경을 측정하지 못해 CPU가 100%를 찍으면서 다운된다.
이러한 slurm에서의 워커 노드들의 상태를 측정하는 명령어는 pestat이다. 이러한 명령어를 통해 확인하는 CPUload는 직관적이지 않으며, 실제 CPU 사용량 및 메모리를 측정하지 못하는 상황이 있기 때문에 GUI를 통해 Grafana로 측정할 수 있게 만들어보자.
본론
이전 포스팅에서 node-exporter를 통해서 노드의 상태를 모니터링하는 그라파나 대시보드를 포스팅한 적이 있다.
- [tistory] 프로메테우스와 그라파나로 리눅스 시스템 모니터링 : https://marsboy.tistory.com/41
해당 내용의 스크립트를 살짝 수정하여, 많은 워커 노드들의 정보를 수집할 수 있는 그라파나 대시보드를 만들어보자. 먼저 워커 노드의 네트워크 토폴로지는 아래와 같은 상황이다.
약 100개의 노드가 워커 노드로서 마스터 노드 세 대에 물리적으로 연결되어 있는 상황이다. 마스터 노드에서 프로메테우스와 그라파나를 docker-compose로 함께 묶어서 올릴 예정이다. 마스터 노드의 프로메테우스에서 모든 워커 노드에서 뿜어져 나오는 node-exporter의 매트릭을 수집하는 아키텍처로 구현할 것이다.
워커 노드 세팅
먼저 워커 노드에서 간단하게 node-exporter를 실행시키는 스크립트는 이미 레퍼런스에 구성되어 있다. 위 블로그 포스팅에 깃허브 레퍼런스가 있다. 아래와 같다.
- [github] node-exporter-moritoring : https://github.com/marsboy02/node-exporter-monitoring
위 링크에 있는 .sh 파일을 살펴보면 아래와 같다. 아래는 node_exporter라는 패키지를 다운로드해서 실행시키는 내용이다. 아래와 같은 명령어를 통해서 node_exporter.service를 실행시키고, 마스터 노드에서 prometheus.yml에 targets에 추가하면 매트릭을 수집할 수 있다.
# download tar
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xvfz node_exporter-1.8.1.linux-amd64.tar.gz
mv node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/
# insert script
cat <<EOF > /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=root
Group=root
Type=simple
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
EOF
# always
systemctl enable node_exporter.service
# start
systemctl start node_exporter.service
# check status
systemctl status node_exporter.service
마스터 노드 세팅
중요한 포인트는, 위와 같은 설정을 모든 워커 노드에 전파해 주는 것이다. 이러한 설정을 돕는 명령어로 pdsh라는 명령어가 있다. 마스터 노드에서 다수의 워커 노드에게 한번에 명령을 전달하기 위해서 pdsh라는 명령어를 쓴다. 이는 ssh 프로토콜을 사용하여 원격 호스트에 접속하여 전달된 명령을 동시에 실행하는 역할을 한다.
아래의 명령어를 통해서 깃허브에 올린 node-exporter-init.sh 파일을 다운로드하고 실행시키는 명령어를 전파할 수 있다. 한 가지 주의 사항은 아래 명령어에서 n001 노드부터 n101 노드까지 표현식을 사용해서 지정하는데, 이때 pdsh가 인식할 수 있도록 /etc/hosts 등 호스트 파일 등에 각각의 호스트명이 IP 주소로 올바르게 변환될 수 있도록 사전에 설정되어 있어야 한다.
pdsh -w n[001-101] ‘curl -O https://raw.githubusercontent.com/marsboy02/node-exporter-monitoring/main/node-exporter-init.sh | ./node-exporter-init.sh’
호스트명에 별다른 문제가 없다면 위 명령어를 통해 모든 워커 노드에 node-exporter를 전파할 수 있다. 반대로 모든 노드에서 node-exporter.service를 중지하고 싶다면 systemctl stop 명령어를 전파하는 방법을 쓸 수 있겠다.
docker-compose 세팅
모든 노드에 설정을 전파하는 것을 마쳤다면, 마스터 노드에서 docker-compose.yml을 조금 수정하여 프로메테우스와 그라파나를 실행시킨다. 먼저 prometheus.yml을 아래와 같이 수정한다. 마스터 노드에서 targets의 IP를 직접 지정해줘야 한다. 마스터 노드에서 pdsh 명령어를 썼을 때와는 다르게 호스트명을 입력하면 안 된다! docker 환경에서는 호스트 파일이 격리되어 있기 때문에 따로 volumes를 연결하는 것이 아니라면, IP 주소를 적어줘야 한다.
global:
scrape_interval: 15s
scrape_timeout: 15s
evaluation_interval: 2m
external_labels:
monitor: "codelab-monitor"
query_log_file: query_log_file.log
scrape_configs:
- job_name: "monitoring-item"
scrape_interval: 10s
scrape_timeout: 10s
metrics_path: "/metrics"
scheme: "http"
static_configs:
# worker node를 원하는 만큼 추가
- targets: ["prometheus:9090", "192.168.100.1:9100","192.168.100.2:9100" ...]
labels:
service: "monitor"
그 후 docker-compose.yml 파일을 살짝 수정하여 기존의 node_exporter에 대한 서비스를 빼고 프로메테우스와 그라파나를 실행시킨다. 코드는 아래와 같다.
version: "3"
networks:
t4y:
driver: bridge
services:
prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- 9090:9090
command:
- "--storage.tsdb.path=/prometheus"
- "--config.file=/etc/prometheus/prometheus.yml"
restart: always
networks:
- t4y
grafana:
image: grafana/grafana
container_name: grafana
ports:
- 3000:3000
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning/:/etc/grafana/provisioning/
restart: always
depends_on:
- prometheus
networks:
- t4y
volumes:
grafana-data:
prometheus-data:
Grafana Dashboard
docker-compose가 정상적으로 작동되는 것을 확인했다면 마스터 노드의 3000번 포트에서 grafana dashboard를 확인할 수 있다. 대시보드를 띄우는 가장 간단한 방법은 다양한 프리셋 대시보드를 import하는 것이다.
위와 같은 그라파나 대시보드를 통해서 실제 사용량을 조회할 수 있게 되었다. 기존에 slurm을 통해서 조회하는 경우는 slurm을 통해서 제출한 작업에 대해서 조회하게 되어 있다. 예를 들어 sbatch와 같은 명령어를 통해서 특정 셸 스크립트를 제출하거나 혹은 srun 명령어를 통해서 특정 노드에 진입하여 명령어를 실행하는 것이었다.
하지만 특정 노드에 srun으로 붙어 가상환경을 실행하는 등의 작업을 하는 사용자들은 slurm에서 리소스 추적이 정확하지 않았는데, 이 경우에는 htop으로 프로세스들을 직접 확인해보는 등의 작업으로 리소스를 추적할 수 있었다.
이러한 문제점을 손쉽게 추적할 수 있게 GUI가 있었으면 좋겠다고 생각하여, 위와 같은 아키텍처로 설계하였다. 위 모니터링 툴을 통해서 slurm에서 추적하는 CPU Loads와 node-exporter를 타고 오는 실제 CPU Loads를 비교하여 어떠한 요소가 노드를 비정상으로 만들 수 있는지 손쉽게 추적할 수 있게 되었다.
마치며
slurm에서 충돌을 일으켜 CPU 100%를 찍고 다운되는 서버들을 추적한 결과, 대부분의 이유가 anaconda 환경을 slurm에서 추적하지 못하고 작업을 가상환경 관련된 작업을 한 곳으로 몰아 넣어, 노드가 다운되는 것으로 확인이 되었다.
slurm에서 봤을 때에는 몇 퍼센트 찍히지 않지만, 모니터링을 해보면 실제 CPU는 100%에 가깝게 나오는 것을 확인할 수 있었다. 이러한 사용자들을 추적하여 anaconda가 아닌 miniconda로 유도하였는데, 이 경우에는 정상적으로 그라파나로 조회한 CPU 사용량과 slurm으로 조회한 CPU 사용량이 일치하는 것을 확인할 수 있었다.
레퍼런스 조사 결과 아나콘다의 경우에는 두가지 문제점이 있었다. 첫 번째는 다양한 환경 변수를 설정하고, PATH에 여러 디렉터리를 추가한다는 것이고, 두 번째는 미니콘다는 일반적으로 사용자 홈 디렉터리에 설치된다는 점이다. 이러한 두 가지 추정되는 이유가 있는데, 아마 후자의 이유로 slurm에서 확실하게 CPU Loads를 추적할 수 있는 것으로 보인다.
모니터링 시스템 덕분에 손쉽게 slurm에서 발생하는 문제점을 해결할 수 있었다. 하지만 살짝 아쉬운 점이 있었는데, 그것은 바로 리소스 사용량만을 시계열 데이터로 수집하는 그라파나 대시보드에서는 예방 차원의 대비책만 세울 수 있다는 점이다. 예를 들어, slurm과 grafana에서의 CPU 점유율이 다를 경우에 추정을 통해 발생할 문제점을 예방할 수 있는 수준의 작업만 할 수 있다는 것이다.
다음 번에는 시간적인 여건이 된다면, 노드가 다운된 이후에도 조치할 수 있는 수습 차원의 대비책도 세울 예정이다. 이러한 방안을 구현하기 위해 slurm에서 쌓이는 log들을 쌓아두고 확인할 수 있는 대시보드가 있었으면 좋을 것 같다는 생각이다.
'project' 카테고리의 다른 글
채팅 서버 만들기 feat. AWS, Serverless (2) | 2024.09.20 |
---|---|
github.io를 이용한 포트폴리오 사이트 만들기 (2) | 2024.03.06 |
크롤러, 스크래퍼를 만드는 방법 (2) | 2024.01.09 |