logo
Published on

HW3. HTCondor 클러스터 구축과 작업 처리

Authors
  • avatar
    Name
    seren-wib
    Twitter
Contents

HW2에서 만든 가상머신 3대에 HTCondor를 설치해서 클러스터를 만들고(교재 5장), 거기에 작업을 제출해 봤다(교재 6장). 뒤쪽에는 2~6장 연습문제 답을 정리했다.

0. 실습 환경

HW2와 같은 환경이다. M3 맥에서 UTM으로 Ubuntu를 띄우고, 그 안에서 KVM/libvirt로 Rocky Linux VM 3대를 돌린다.

macOS (Apple M3)
└─ UTM (Apple Virtualization, 중첩 가상화)
   └─ Ubuntu 24.04 ARM64 (호스트 yoosung-vm, 강의의 "Ubuntu 호스트")
      └─ KVM + libvirt   (VirtualBox 대체)
         ├─ main   Rocky Linux 10.2 aarch64 192.168.56.101 main.cloud.org
         ├─ work1  Rocky Linux 10.2 aarch64 192.168.56.102 work1.cloud.org
         └─ work2  Rocky Linux 10.2 aarch64 192.168.56.103 work2.cloud.org
교재 (슬라이드)이 환경
VirtualBox, x86_64KVM/libvirt, aarch64 (ARM64)
계정 cloud, 호스트 cloudman@abelia계정 yoosung, 호스트 yoosung@yoosung-vm
클러스터 인터페이스 enp0s8enp2s0 (192.168.56.0/24 사설망). enp1s0은 인터넷용 NAT
HTCondor 버전 명시 없음condor-25.14.1-1.el10.aarch64 (설치 스크립트 기본 채널)

Apple Silicon 맥에서 VirtualBox를 안 쓴 이유

Apple Silicon용 VirtualBox로 VM 3대를 만드는 것 자체는 된다. 문제는 그러면 VirtualBox를 돌리는 호스트가 macOS가 돼서, 강의가 전제하는 "Ubuntu 호스트"를 둘 수 없다는 거다. VirtualBox 7.2 공식 문서를 보고 확인한 내용은 이렇다.

  • Ubuntu에 VirtualBox 설치: 지원 호스트 목록에서 Linux는 x86_64만 지원하고 ARM64는 지원하지 않는다. Apple Silicon에서 Ubuntu를 쓰려면 ARM64 Ubuntu를 VM으로 띄워야 하는데, 여기에는 VirtualBox를 못 깐다.
  • VirtualBox 안의 Ubuntu에서 다시 VM 실행: 중첩 가상화가 필요한데 VirtualBox는 ARM 게스트에 중첩 가상화(Nested VT-x/AMD-V)를 제공하지 않는다.
  • x86 이미지 사용: ARM 호스트의 VirtualBox는 ARM 게스트만 돌린다. 어느 쪽이든 강의의 x86_64 VM은 그대로 못 쓴다.

그래서 "Ubuntu 호스트에서 VM을 만들고, 호스트 터미널에서 SSH로 접속하고, 호스트에서 만든 키를 VM에 배포하는" 강의 흐름을 최대한 그대로 따르려고, 중첩 가상화를 지원하는 UTM으로 Ubuntu를 띄우고 그 안에서 Linux 표준 하이퍼바이저인 KVM/libvirt를 썼다.

참고: Oracle VirtualBox 7.2 User Guide, Supported Host Operating Systems

키 파일 이름 지정

HW2에서는 ssh-keygen의 파일명 입력을 기본값(id_ed25519)으로 넘겼다. 클라우드에서는 여러 키를 구분해서 관리해야 하니까, 이번엔 Ch04-Extra 슬라이드처럼 cloud.key로 이름을 정해 새로 만들었다. -o IdentitiesOnly=yes는 기본 키를 시도하지 않고 지정한 키만 쓰게 하는 옵션이다.

ssh-keygen
Enter file in which to save the key (/home/yoosung/.ssh/id_ed25519): /home/yoosung/.ssh/cloud.key
Your identification has been saved in /home/yoosung/.ssh/cloud.key
Your public key has been saved in /home/yoosung/.ssh/cloud.key.pub

ssh-copy-id -i ~/.ssh/cloud.key.pub 192.168.56.101      (102, 103도 같음)
Number of key(s) added: 1

ssh -i ~/.ssh/cloud.key -o IdentitiesOnly=yes 192.168.56.101 hostname
main.cloud.org
ssh -i ~/.ssh/cloud.key -o IdentitiesOnly=yes 192.168.56.102 hostname
work1.cloud.org
ssh -i ~/.ssh/cloud.key -o IdentitiesOnly=yes 192.168.56.103 hostname
work2.cloud.org

1. HTCondor 클러스터 구축 (5장)

HTCondor 클러스터는 역할이 다른 노드로 이루어진다. 슬라이드처럼 main을 central manager + submit으로, work1·work2를 execute로 구성했다.

노드역할실행되는 데몬
maincentral manager: 노드 상태를 모으고 작업과 노드를 짝지음 / submit: 작업을 받아 대기열에 둠condor_collector, condor_negotiator, condor_schedd
work1, work2execute: 실제로 작업을 실행condor_startd

세 노드 모두 공통으로 condor_master(데몬 관리), condor_procd, condor_shared_port가 같이 돈다.

모든 명령은 Ubuntu 호스트 터미널에서 SSH로 각 VM에 접속해서 실행했다. 호스트의 /etc/hosts에는 VM 이름을 안 넣어서 IP로 접속했고, 워커 두 대는 터미널 두 개로 동시에 진행했다.

ssh 192.168.56.101     # main
ssh 192.168.56.102     # work1
ssh 192.168.56.103     # work2

main 노드 (central manager + submit)

① curl 설치

Rocky 10.2에는 curl이 이미 있었고, 이 명령으로 curl·libcurl·openssl-libs가 더 새 빌드로 올라갔다.

sudo dnf install -y curl

② HTCondor 설치

get.htcondor.org 설치 스크립트는 OS를 감지해서 HTCondor 저장소를 추가하고, Rocky에 필요한 EPEL·CRB 저장소를 켠 다음 condor를 설치한다. GET_HTCONDOR_PASSWORD는 노드끼리 인증할 때 쓰는 풀 비밀번호고, --central-manager는 이 노드의 역할이다. 스크립트가 Rocky 10과 aarch64를 지원해서 슬라이드 명령을 그대로 쓸 수 있었다.

curl -fsSL https://get.htcondor.org | sudo GET_HTCONDOR_PASSWORD="htcondor" /bin/bash -s -- --no-dry-run --central-manager main.cloud.org

슬라이드와 달리 지금 버전 스크립트는 설치 마지막에 방화벽에 HTCondor 포트(9618/tcp)를 열고 systemctl enable/start condor까지 해 준다. 설치된 버전은 condor-25.14.1이다.

③ 방화벽 끄기

노드 사이 통신이 막히지 않도록 firewalld를 멈추고 부팅 시 자동 시작도 껐다. --no-pager는 출력이 less에 걸려 멈추지 않게 하려고 붙였다.

systemctl status firewalld --no-pager
sudo systemctl stop firewalld
sudo systemctl disable firewalld
systemctl status firewalld --no-pager

④ submit 역할 추가

설치 스크립트가 만든 01-central-manager.config에는 central manager 역할만 있다. main에서 작업도 제출할 수 있게 submit 역할을 한 줄 추가했다.

cd /etc/condor/config.d
echo "use role:get_htcondor_submit" | sudo tee -a 01-central-manager.config
sudo cat 01-central-manager.config
CONDOR_HOST = main.cloud.org
# For details, run condor_config_val use role:get_htcondor_central_manager
use role:get_htcondor_central_manager
use role:get_htcondor_submit

⑤ condor_config.local 작성

NETWORK_INTERFACE는 HTCondor가 클러스터 통신에 쓸 인터페이스다. 슬라이드의 enp0s8은 VirtualBox 이름이고, 이 환경에서 192.168.56.0/24 사설망은 enp2s0이라 바꿔 줬다. 그대로 쓰면 없는 인터페이스를 지정하게 된다.

printf "%s\n" "UID_DOMAIN = main.cloud.org" "ALLOW_WRITE = *.cloud.org" \
  "CONDOR_HOST = main.cloud.org" "NETWORK_INTERFACE = enp2s0" | sudo tee condor_config.local
설정의미
UID_DOMAIN이 노드의 사용자 계정이 속한 도메인
ALLOW_WRITE쓰기 작업(작업 제출 등)을 허용할 호스트, *.cloud.org
CONDOR_HOSTcentral manager 노드, main.cloud.org
NETWORK_INTERFACE클러스터 통신에 쓸 인터페이스, enp2s0

⑥ HTCondor 시작

sudo systemctl restart condor
sudo systemctl enable condor
systemctl status condor --no-pager

condor_master 아래에 collector·negotiator·schedd가 떠서 central manager와 submit 역할이 모두 동작한다.

main condor 서비스

main: condor 서비스 active, collector·negotiator·schedd 실행 (central manager + submit)

work1·work2 노드 (execute)

같은 과정을 execute 역할로 반복했다. 설치 스크립트에 --execute main.cloud.org를 주고, UID_DOMAIN은 각자 자기 호스트네임으로, NETWORK_INTERFACE는 역시 enp2s0으로 했다.

sudo dnf install -y curl
curl -fsSL https://get.htcondor.org | sudo GET_HTCONDOR_PASSWORD="htcondor" /bin/bash -s -- --no-dry-run --execute main.cloud.org
sudo systemctl stop firewalld
sudo systemctl disable firewalld
cd /etc/condor/config.d
printf "%s\n" "UID_DOMAIN = work1.cloud.org" "ALLOW_WRITE = *.cloud.org" \
  "CONDOR_HOST = main.cloud.org" "NETWORK_INTERFACE = enp2s0" | sudo tee condor_config.local
sudo systemctl enable condor
sudo systemctl restart condor
systemctl status condor --no-pager

work2는 UID_DOMAIN = work2.cloud.org로 바꿔서 실행했다. 두 노드 모두 condor_startd가 떴고, /var/log/condor/에 MasterLog·StartLog 같은 로그 파일이 생겼다.

work1 condor 서비스

work1: condor 서비스 active, startd 실행 (execute)

work2 condor 서비스

work2: condor 서비스 active, startd 실행 (execute)

클러스터 확인

main에서 condor_status를 실행하면 실행 노드 두 대(slot1@work1.cloud.org, slot1@work2.cloud.org)가 Unclaimed / Idle, 즉 작업을 받을 수 있는 상태로 나온다. work1·work2에서 실행해도 같았다.

슬라이드와 달리 Arch가 X86_64가 아니라 aarch64고, Mem이 3653이 아니라 1696(MB)이다. ARM64 환경이고 VM마다 메모리를 2GB로 줬기 때문이다.

condor_status

main에서 condor_status: slot1@work1, slot1@work2 두 대가 Unclaimed / Idle (Arch aarch64)

설치하면서 생긴 문제

둘 다 클러스터 동작에는 영향이 없었지만 원인을 찾아서 고쳤다.

문제 1. condor 재시작 때 exim 권한 오류

main에서 systemctl restart condor 직후 systemctl status condor 로그에 이런 오류가 떴다.

Failed to create spool file /var/spool/exim//input//...: Permission denied
Cannot open main log file "/var/log/exim/main.log": Permission denied: euid=93 egid=93
exim: could not open panic log - aborting: see message(s) above
  • 조사: HTCondor는 데몬 재시작 같은 일이 있으면 관리자(CONDOR_ADMIN = root@main.cloud.org)에게 알림 메일을 보낸다. 이 메일을 처리하는 exim이 condor 설치 때 의존성으로 같이 깔렸는데, 자기 spool과 로그 디렉터리에 쓰지 못하고 있었다. 워커 설치 로그에도 warning: user exim does not exist - using root가 계속 찍혀 있었다.
  • 원인: rpm -V exim으로 설치된 파일을 패키지 정보와 비교하니 exim 디렉터리 5개에서 소유자(U)·그룹(G)이 안 맞았고, 실제 소유자는 root:root였다. 패키지가 디렉터리를 풀어놓을 때 exim 계정이 아직 없어서 root 소유로 만들어졌고, 나중에 생긴 exim 계정(uid 93)은 거기 쓸 수 없었던 거다.
sudo rpm -V exim
.....UG..    /var/log/exim
.....UG..    /var/spool/exim
.....UG..    /var/spool/exim/db
.....UG..    /var/spool/exim/input
.....UG..    /var/spool/exim/msglog
  • 해결: rpm --setugids로 패키지 정보에 적힌 소유자로 되돌렸다. 그 뒤 rpm -V exim이 불일치 없이 끝났고 디렉터리 소유자가 exim exim이 됐다. 같은 상태였던 work1·work2에도 적용했다.
sudo rpm --setugids exim
sudo rpm -V exim; echo "rpm -V exit=$?"
rpm -V exit=0
ls -ld /var/spool/exim /var/log/exim
drwxr-x---. 2 exim exim 6 Jan 3 2026 /var/log/exim
drwxr-x---. 5 exim exim 43 Jan 3 2026 /var/spool/exim
  • 확인: /usr/sbin/sendmail로 시험 메일을 보내니 exim이 정상적으로 받아서 보관함에 넣었다. root로의 최종 배달은 exim 기본 정책(never_users, root로는 배달 안 함)에 따라 보류되는데, 권한 오류와는 별개인 정상 동작이라 그대로 뒀다. 세 노드 condor를 다시 시작한 뒤에는 exim 오류가 안 나왔다.

문제 2. VM 시계가 약 32분 늦음

  • 증상: main의 서비스 로그 시각(18:35)이 호스트 시각(19:06)보다 30분쯤 늦었다.
  • 조사: chrony 상태를 보니 세 VM 모두 같은 만큼 늦었고 동기화도 안 된 상태였다.
chronyc tracking
System time     : 1957.179077148 seconds slow of NTP time
timedatectl show -p NTPSynchronized
NTPSynchronized=no
  • 원인: chrony는 부팅 직후 처음 몇 번만 시계를 한 번에 맞추고(step), 그 뒤에는 시계를 조금씩 빠르게 돌려 천천히 따라잡는다(slew). 약 1957초를 slew로 메우려면 몇 시간이 걸린다. 차이가 처음 생긴 이유는 못 찾았다.
  • 해결: 워커 설정 전에 세 VM에서 chronyc makestep으로 바로 맞췄다. 그 뒤 오차는 나노초 단위가 됐다. 세 VM이 같은 만큼 늦어서 클러스터에는 영향이 없었지만, 로그와 캡처 시각을 실제와 맞추려고 했다.
sudo chronyc makestep
chronyc tracking | grep "System time"
System time     : 0.000000001 seconds slow of NTP time

2. HTCondor로 작업 처리하기 (6장)

HTCondor에 작업을 맡길 때는 작업명세서(Job Description File, jds)에 무엇을 어떻게 실행할지 적고 condor_submit으로 제출한다. 제출된 작업은 main의 schedd가 대기열에 넣고, negotiator가 조건에 맞는 실행 노드를 골라 짝지으면 그 노드의 startd가 실행한다.

jds 항목의미
executable실행할 파일
universe실행 환경. 이번 실습은 모두 셸 스크립트라 vanilla
arguments / input실행 파일에 넘길 인자 / 표준 입력으로 줄 파일
output / error / log표준 출력, 표준 에러, HTCondor 실행 기록을 남길 파일
initialdir작업의 기준 디렉터리 (입출력 파일을 여기 기준으로 찾고 씀)
requirements작업을 실행할 기계가 만족해야 하는 조건
queue [N]작업을 N개 제출

작업은 전부 submit 역할인 main의 홈 디렉터리에 작업별 디렉터리(01.date ~ 07.requirment)를 만들어 제출했고, 실행은 work1·work2가 나눠 맡았다. 이번엔 제출하는 곳이 main이라 main 하나에만 SSH로 접속하면 된다. 슬라이드는 vi로 파일을 만들지만 같은 내용을 cat > 파일 <<'EOF'로 작성했다.

실행 노드슬롯동시 실행
work1, work2각 1개의 Partitionable 슬롯 (CPU 2, 메모리 1696MB)작업 하나가 CPU 1개·메모리 128MB를 요청하니까 두 노드 합쳐 최대 4개

main과 워커의 UID_DOMAIN·FILESYSTEM_DOMAIN이 서로 달라서(main.cloud.org / work1.cloud.org 등) 파일 시스템을 공유하지 않는 걸로 처리된다. 그래서 HTCondor가 실행 파일과 입력 파일을 워커로 보내고 결과 파일을 main으로 돌려받는 파일 전송 방식으로 돌았다(로그의 Started transferring input files).

작업 1. 간단한 작업 (01.date)

현재 시각을 출력하고 10초 쉰 뒤 다시 출력하는 스크립트다.

date.sh
#!/bin/bash

echo `date`
sleep 10
echo `date`
date.jds
executable = date.sh
universe = vanilla
output = out.txt
error = error.txt
log = log.txt
queue
condor_submit date.jds
condor_q
cat out.txt; cat error.txt; ls -l error.txt
head -n 20 log.txt

제출 1초 만에 work2에서 실행되기 시작해서 약 10초 뒤 끝났다. out.txt의 두 시각이 10초 차이 나고 error.txt는 0바이트다. log.txt에는 제출(000) → 입력 파일 전송(040) → 실행 시작(001, work2.cloud.org) 순서로 남는다.

작업 1 제출

작업 1 제출과 condor_q: 실행 중(RUN 1) → 완료(대기열 비어 있음)

작업 1 결과

작업 1 결과: out.txt에 10초 간격 시각 2줄, error.txt 0바이트

작업 1 log

작업 1 log.txt: work2.cloud.org(192.168.56.103)에서 실행

작업 2. 인자를 갖는 작업 (02.argument)

시작 값과 끝 값을 인자로 받아 합을 구하는 스크립트에 arguments = 1 10을 넘겼다.

count.sh
#!/bin/bash
NUM_START=$1
NUM_END=$2
LOOP_COUNT=$NUM_START
SUM=0
echo "Sum from $NUM_START to $NUM_END"
while [ $LOOP_COUNT -le $NUM_END ]
do
        SUM=`expr $SUM + $LOOP_COUNT`
        LOOP_COUNT=`expr $LOOP_COUNT + 1`
done
echo "Total Sum = $SUM"
argument.jds
executable = count.sh
universe = vanilla
arguments = 1 10
output = out.txt
error = error.txt
log = log.txt
queue

condor_q에서 대기(IDLE 1) → 실행(RUN 1) → 완료가 차례로 보였고, 결과는 Total Sum = 55였다.

작업 2 제출

작업 2 제출과 condor_q: IDLE → RUN → 완료

작업 2 결과

작업 2 결과: Sum from 1 to 10, Total Sum = 55

작업 3. 여러 작업 동시 실행 (03.multiple)

작업 2의 jds에서 마지막 줄만 queue 10으로 바꿔 10개를 제출했다.

실행 노드 CPU가 모두 4개라서 4개씩 실행됐다(DONE 2 / RUN 4 / IDLE 4). 10개는 work1과 work2에 5개씩 나뉘었다.

그런데 10개가 전부 같은 out.txt·error.txt·log.txt를 쓴다. 그래서 out.txt와 error.txt는 하나만 남아 서로 덮어써지고, log.txt에는 10개 작업 기록이 한 파일에 섞여 쌓인다. 이 문제를 작업 4~6에서 푼다.

작업 3 condor_q

작업 3 condor_q: 10개 제출, 4개씩 실행 (DONE 2, RUN 4, IDLE 4)

작업 3 결과

작업 3 결과: out.txt는 하나뿐, 10개 작업이 work1·work2에 5개씩 실행됨

작업 4. 디렉터리를 나눠 동시 실행 (04.multiple)

file.txt를 한 줄씩 읽어 출력하는 read.sh를 만들고, 작업마다 initialdir를 run_0, run_1로 다르게 줬다.

read.sh
#!/bin/bash

while read line
do
        echo "$line"
done < file.txt

문제: Extra data found after queue statement

슬라이드의 read.jds는 initialdir를 바꿔 가며 queue를 두 번 쓴다. 그대로 제출하니 제출 자체가 거부됐다.

condor_submit read.jds
ERROR: on Line 12 of read.jds: Extra data found after queue statement
ERROR: Failed to parse command file (line 12).
작업 4 제출 오류

슬라이드의 jds(queue 2번)는 제출 오류

  • 조사: 12행은 두 번째 initialdir = run_1이다. cat -A read.jds로 안 보이는 문자가 섞이지 않은 걸 확인했고, condor_submit -dry-run으로도 같은 오류가 났다. 오류 문구로 검색해서 HTCondor 25.x 릴리스 노트에서 이걸 찾았다.

    The condor_submit warning about submit files with multiple QUEUE statements has been changed to an error by changing the default value for SUBMIT_PREVENT_MULTI_QUEUE to True. (Version 25.14.1)

  • 원인: 설치된 HTCondor가 딱 이 25.14.1이다. 이전 버전에서는 queue를 여러 번 쓰면 경고만 나왔는데, 이 버전부터 오류로 바뀌었다.

  • 해결: HTCondor 공식 FAQ "Convert Multi-Queue Statements into One" 방식대로 queue 하나에 initialdir 값 목록을 주도록 바꿨다. SUBMIT_PREVENT_MULTI_QUEUE = False로 예전 문법을 다시 허용하는 방법도 있지만 폐기 예정이라 안 썼다.

read.jds
executable = read.sh
universe = vanilla
input = file.txt
output = out.txt
error = error.txt
log = log.txt
queue initialdir from (
    run_0
    run_1
)

고친 jds로 제출하니 작업 2개가 동시에 돌았고, run_0과 run_1에 결과 파일이 따로 생겼다. 로그를 보면 run_0은 work2, run_1은 work1에서 실행됐다.

작업 4 제출

고친 jds로 제출, 작업 2개 IDLE → RUN 2 → 완료

작업 4 결과

run_0, run_1에 결과 파일이 따로 생기고 error.txt는 비어 있다.

참고: HTCondor Version 25.x Feature Releases, Convert Multi-Queue Statements into One

작업 5. 파일 이름을 나눠 동시 실행 (05.multiple)

$(Process)는 같은 제출로 만들어진 작업마다 0, 1, 2…로 붙는 번호다. 출력 파일 이름에 넣으면 작업마다 다른 파일에 기록한다.

executable = count.sh
universe = vanilla
arguments = 1 10
output = out.$(Process).txt
error = error.$(Process).txt
log = log.$(Process).txt
queue 10

10개 작업의 out·error·log 파일 30개가 따로 생겼고, out.0.txt~out.9.txt 모두 Total Sum = 55였다.

작업 5 condor_q

작업 5 condor_q: RUN 4 / IDLE 6 → DONE 8 / RUN 2 → 완료

작업 5 결과

작업 번호별 파일 30개, out 10개 모두 55

작업 6. $(Process)로 디렉터리 나누기 (06.multiple)

작업 4의 파일을 복사하고, initialdir에 $(Process)를 넣어 queue 2 한 번으로 run_0, run_1을 나눴다. 작업 4의 다른 방법이고 queue가 하나라 위의 오류와도 상관없다.

executable = read.sh
universe = vanilla
input = file.txt
output = out.txt
error = error.txt
log = log.txt
initialdir = run_$(Process)
queue 2
작업 6 제출

작업 6 제출과 condor_q: 작업 2개 IDLE → RUN 2 → 완료

작업 6 결과

run_0, run_1에 각각 out·error·log 생성

작업 7. 요구사항을 갖는 작업 (07.requirment)

먼저 일부러 맞는 기계가 없는 조건(Arch == "INTEL")으로 제출했다. 협상 주기(60초)를 넘겨 76초 뒤에 봐도 작업은 계속 IDLE이었고, log.txt에는 제출 기록만 있었다.

req-error.jds
requirements = (OpSys == "LINUX" && Arch == "INTEL")
image_size = 28

나머지 줄은 작업 2의 argument.jds와 같다.

작업 7 IDLE

Arch == "INTEL" 조건, 76초가 지나도 IDLE

condor_q -better-analyze를 돌리면 이유가 나온다. Arch == "INTEL"에 맞는 슬롯이 0개고, 슬롯 2개가 모두 작업의 요구 조건 때문에 거절했다.

better-analyze

condor_q -better-analyze: 맞는 슬롯 0개, 2개 슬롯 모두 거절

문제: 슬라이드의 수정본도 안 맞음

슬라이드는 Arch == "X86_64"로 고쳐서 실행한다. 그런데 이 환경의 실행 노드는 ARM64라서 condor_status -l | grep Arch가 Arch = "aarch64"로 나온다. X86_64로 고쳐도 맞는 노드가 없어서 계속 대기한다. 그래서 condor_rm 8.0으로 지우고 aarch64로 고쳐서 다시 제출했다.

requirement.jds
requirements = (OpSys == "LINUX" && Arch == "aarch64")
image_size = 28
condor_submit req-error.jds
condor_q                         # 76초 뒤에도 IDLE
condor_status -l | grep Arch     # Arch = "aarch64"
condor_q -better-analyze 8.0
condor_rm 8.0
condor_submit requirement.jds
작업 7 정상 종료

Arch == "aarch64"로 고친 작업 9.0: 정상 종료, Total Sum = 55

3. 연습문제

Ch2-4. 멀티테넌시 모델의 장단점

멀티테넌시는 NIST 5가지 특성 중 리소스 풀링에서 나온 모델이다. 컴퓨팅 자원을 하나의 풀로 묶어서 서로 다른 사용자(테넌트)가 나눠 쓴다. 각 테넌트에게는 자기 자원만 보이게 논리적으로 격리하지만 실제 서버·스토리지·네트워크는 같이 쓴다.

장점

  • 자원 활용률: 한 사용자가 안 쓰는 자원을 다른 사용자가 쓸 수 있어서 노는 자원이 줄어든다. 용량의 10~15%만 쓰던 서버의 효용률을 70%까지 올릴 수 있는 바탕이 된다.
  • 비용 절감: 인프라 구축비와 전원·냉각·관리 인력 같은 운영비를 여러 사용자가 나눠 내니까 한 사람이 내는 비용이 낮아진다.
  • 관리와 확장: 제공자가 패치나 업그레이드를 한 번 하면 모든 테넌트에 적용된다. 풀에 여유가 있어서 필요할 때 바로 늘릴 수 있다(신속한 탄력성).

단점

  • 보안: 다른 기관과 같은 인프라를 쓰니까 격리에 결함이 있으면 내 데이터가 다른 테넌트에게 노출될 수 있다. 서로 다른 기관의 서비스가 같은 인프라를 쓰면서 생기는 "보안 정책의 상충"이 이 문제다.
  • 성능 간섭: 같은 물리 서버의 다른 테넌트가 CPU·디스크·네트워크를 많이 쓰면 내 서비스도 느려진다. 제공자가 약속된 성능을 지키기 어려워지는 원인이다.
  • 맞춤 설정 제약: 모두가 같은 플랫폼을 쓰니까 한 사용자만을 위해 설정이나 버전을 바꾸기 어렵고, 업데이트 시점도 제공자가 정한다.

정리: 장점은 전부 자원을 "나눠 쓴다"는 데서 나오는 효율이고, 단점은 "같이 쓴다"는 데서 나오는 격리 문제다. 비용이 중요한 일반 서비스에는 멀티테넌트 퍼블릭 클라우드가 유리하고, 격리와 통제가 중요한 데이터에는 프라이빗 클라우드나 전용 자원이 맞다.

Ch2-6. 대형 프로젝트의 클라우드 개발환경 사례

개발자마다 OS, 라이브러리 버전, 설정이 다르면 한 사람 컴퓨터에서는 되는 코드가 다른 사람 컴퓨터에서는 안 되고, 새 팀원은 환경 맞추는 데만 오래 걸린다. 같은 개발환경을 클라우드에 만들어 두고 다 같이 접속해서 쓰면 이 문제가 줄어든다.

사례: GitHub 개발팀의 Codespaces 전환 (2021)

  • 배경: GitHub.com 저장소는 디스크에서 약 13GB고 복제에만 20분이 걸렸다. 의존성 설치까지 합치면 개발환경 하나 준비하는 데 45분 이상 걸렸고, 로컬 환경이 망가지면 이걸 다시 해야 했다.
  • 방법: 개발환경을 클라우드 VM인 Codespaces로 옮겼다. 환경 구성은 저장소 안 설정 파일에 코드로 적어서 모두가 같은 환경을 받는다. 저장소 복제와 초기 설정을 미리 끝낸 환경(prebuild)을 풀로 만들어 대기시켜 둔다.
  • 결과: 개발환경을 새로 받는 시간이 45분에서 10초로 줄었다. 필요할 때 받고, 문제가 생기면 버리고 새로 받는다.
  • 강의 내용과 연결: 미리 만든 환경 풀에서 필요할 때 꺼내 쓰는 건 온디맨드 셀프서비스와 리소스 풀링이고, 망가진 환경을 새 VM으로 바꾸는 건 가상머신 파일로 서비스를 복원하는 복원성과 같은 방식이다.

참고: GitHub Blog, "GitHub's Engineering Team has moved to Codespaces" (2021-08-11)

Ch2-15. 다국적 클라우드 서비스의 데이터 분쟁 사례

클라우드에서는 데이터가 저장된 나라, 서비스 회사의 나라, 사용자의 나라가 다 다를 수 있다. 그러면 어느 나라 법을 따라야 하는지로 분쟁이 생긴다.

사례 1. 미국 정부 대 마이크로소프트 (아일랜드 이메일 사건, 2013~2018)

  • 미국 수사기관이 한 이메일 계정 내용을 제출하라는 영장을 받았는데, 그 이메일은 아일랜드 데이터센터에 있었다.
  • 마이크로소프트는 미국 영장이 해외에 저장된 데이터에는 미치지 않는다며 거부했고, 2심 법원이 이를 받아들였다. 정부가 상고해서 연방대법원까지 갔다.
  • 판결 전인 2018년 3월 미국 의회가 CLOUD Act를 통과시켜, 미국 기업이 보유·관리하는 데이터는 저장 위치와 상관없이 제출하게 했다. 정부가 이 법으로 새 영장을 받자 대법원은 2018년 4월 사건을 종결했다.

사례 2. 슈렘스 II 판결 (유럽연합 사법재판소, 2020)

  • 오스트리아의 막스 슈렘스가 페이스북이 유럽 사용자 데이터를 미국으로 옮기면 미국 정보기관 감시에 노출된다고 문제를 제기했다.
  • 2020년 7월 유럽연합 사법재판소는 미국으로 개인정보를 옮기는 근거였던 EU-미국 프라이버시 실드를 무효로 판결했다. 미국 법이 유럽 시민 데이터를 충분히 보호하지 못한다는 이유였다.
  • 2023년 아일랜드 데이터보호위원회는 메타가 이 판결 뒤에도 유럽 사용자 데이터를 미국으로 계속 옮겼다며 12억 유로 과징금을 부과했다.

정리: 둘 다 데이터 저장 위치와 기업·사용자 국적이 달라서 각 나라 법이 충돌한 경우다. 데이터가 외부 클라우드에 있어도 보안과 무결성의 최종 책임은 소비자에게 있으니까, 클라우드를 쓸 때는 데이터가 어느 나라에 저장되고 어느 나라 법을 적용받는지 미리 확인해야 한다.

참고: SCOTUSblog, "Justices officially declare Microsoft email case moot" (2018-04-17), CJEU C-311/18 (Schrems II, 2020-07-16)

Ch3-3. 가장 빠른 슈퍼컴퓨터는 얼마나 빠른가

2026년 6월 Top500 1위는 중국 선전 국가슈퍼컴퓨팅센터의 LineShine이다. HPL(LINPACK)에서 초당 2.198 엑사플롭스(Rmax)를 기록했다.

  • 단위: 플롭스(FLOPS)는 1초에 하는 실수 계산(더하기, 곱하기 등) 횟수고, 엑사는 10의 18제곱, 즉 100경이다. LineShine은 1초에 약 219경 8천조 번 계산한다.
  • 전 인류와 비교: 지구의 약 82억 명이 전부 1초에 한 번씩 쉬지 않고 계산해도, LineShine이 1초 동안 하는 계산을 끝내려면 약 2억 6,800만 초, 즉 8년 6개월쯤 걸린다.
  • 한 사람과 비교: 한 사람이 1초에 한 번씩 계산하면 약 696억 년이 걸린다. 우주 나이(약 138억 년)의 5배쯤이다.

이 컴퓨터는 약 1,379만 개 코어를 전용 고속 네트워크로 묶은 거다. 수많은 코어가 빠른 네트워크로 통신하면서 하나의 큰 문제를 빠르게 푸는 HPC 구조다.

참고: TOP500, June 2026 list

Ch3-5. 작은 문제들이 완전히 독립적이지 않을 때

HTC는 작업이 서로 독립적이어야 아무 코어에서나 바로 실행하고 실패한 작업만 다시 돌릴 수 있다. 작업 사이에 의존 관계가 있으면 그 모양에 따라 다르게 처리한다.

  • 앞 작업 결과가 뒤 작업 입력인 경우: 의존 관계에 따라 단계로 묶는다. 같은 단계 안 작업끼리는 독립이니까 HTC로 동시에 돌리고, 앞 단계가 다 끝나면 다음 단계를 돌린다. 과제 표절 검사라면 과제 100개 전처리 → 4,950개 쌍 비교 → 결과 취합의 세 단계가 되고, 가운데 4,950개 비교는 서로 독립이다. HTCondor에서는 이 순서를 DAGMan으로 자동화한다.
  • 공통 데이터가 필요한 경우: 공통 데이터를 먼저 만들고 각 작업의 입력 파일로 나눠 준다. 작업끼리 직접 주고받지 않고 HTCondor 입력 파일 전송으로 같은 데이터를 받으면 다시 독립 작업이 된다.
  • 실행 중에 서로 자주 주고받아야 하는 경우: 쪼개면 통신 비용이 더 커지니까 강하게 묶인 작업은 하나로 합친다. 그래도 너무 크면 HTC가 아니라 HPC 방식(MPI, 인피니밴드 같은 빠른 네트워크)으로 처리한다. HTCondor에도 MPI 작업용 parallel universe가 있다.

정리하면 의존 관계를 분석해서 독립인 부분은 HTC로 최대한 나눠 돌리고, 의존하는 부분은 실행 순서를 제어하거나 작업을 합친다. 두 방식을 섞어 쓸 수도 있다.

Ch3-7. 인피니밴드의 연결 방식과 동작

인피니밴드(InfiniBand)는 HPC에서 "빠르고 비싼 네트워크"의 대표다. 슈퍼컴퓨터와 데이터센터에서 서버끼리 연결하는 데 쓰고, Mellanox(현재 NVIDIA)가 대표 장비 회사다.

연결 방식

  • 스위치 패브릭(switched fabric): 모든 노드가 스위치에 점대점(point-to-point)으로 연결되고, 스위치끼리는 fat-tree 같은 구조로 이어진다. 두 노드 사이 경로가 여러 개라 노드가 늘어도 전체 대역폭이 같이 는다.
  • 구성 요소: 서버마다 꽂는 어댑터 HCA(Host Channel Adapter), 스위치, 네트워크 전체 주소와 경로를 정하는 서브넷 매니저(Subnet Manager).

동작 방식

  • RDMA(Remote Direct Memory Access): 한 노드의 HCA가 다른 노드 메모리에 직접 읽고 쓴다. TCP/IP는 커널이 데이터를 여러 번 복사하고 CPU가 처리하지만, RDMA는 커널과 CPU를 안 거쳐서 지연이 짧고 CPU를 계산에만 쓸 수 있다.
  • 큐 기반 통신: 프로그램이 송신 큐와 수신 큐 쌍(Queue Pair)에 요청을 넣으면 HCA가 하드웨어로 보내고, 끝나면 완료 큐(Completion Queue)에 알린다.
  • 무손실 전송: 받는 쪽 버퍼에 여유가 있을 때만 보내는 크레딧 기반 흐름 제어라 패킷이 버려지지 않는다. 재전송이 거의 없어서 지연이 일정하다.

HPC는 모든 코어가 하나의 문제를 같이 풀면서 MPI로 노드끼리 계속 메시지를 주고받는다. 한 노드만 늦어도 전체가 기다리니까 지연이 짧고 일정한 인피니밴드가 필요하다. 독립 작업을 처리하는 HTC에는 꼭 필요하진 않다.

Ch4-2. SSH 서버와 클라이언트의 연결 과정

SSH는 원격 접속 내용을 암호화하는 프로토콜이고 기본 포트는 22번이다. 클라이언트(ssh)가 서버(sshd)에 접속하면 이 순서로 연결된다.

  1. TCP 연결과 버전 교환: 클라이언트가 서버 22번 포트로 TCP 연결을 맺고, 양쪽이 SSH 프로토콜 버전(SSH-2.0)과 소프트웨어 이름을 주고받는다.
  2. 알고리즘 협상: 양쪽이 지원하는 키 교환, 서버 키, 암호화, 무결성 검사(MAC) 알고리즘 목록을 보내고 둘 다 지원하는 것 중 하나씩 고른다.
  3. 키 교환: Diffie-Hellman(또는 ECDH)으로 양쪽이 각자 비밀 값을 만들고 공개 값만 교환해서 같은 공유 비밀을 계산한다. 공유 비밀 자체는 네트워크로 안 간다. 이 값으로 이후 통신에 쓸 대칭키(세션 키)를 만든다.
  4. 서버 인증: 서버가 키 교환 내용에 자기 호스트 개인키로 서명해 보내고, 클라이언트는 서버 공개키로 서명을 확인한다. 그리고 그 공개키가 ~/.ssh/known_hosts에 저장된 키와 같은지 본다. 처음 접속할 땐 저장된 키가 없어서 "The authenticity of host ... can't be established"가 나오고, yes를 치면 저장된다. 이후 서버 키가 바뀌면 경고가 나와서 중간에서 서버를 가장하는 공격을 막는다.
  5. 사용자 인증: 이제 암호화된 채널 안에서 사용자를 확인한다. 비밀번호 인증은 비밀번호를 암호화된 채널로 보낸다. 공개키 인증은 클라이언트가 세션 정보에 개인키로 서명하고, 서버가 ~/.ssh/authorized_keys의 공개키로 확인한다. HW2에서 ssh-copy-id 후 비밀번호 없이 접속한 게 공개키 인증이다.
  6. 세션 사용: 인증이 끝나면 하나의 연결 안에 채널을 열어 셸, 명령 실행, scp 파일 전송 등을 한다. 모든 데이터는 3번의 세션 키로 암호화되고 MAC으로 변조 여부를 검사한다.

Ch4-3. 공개키 암호의 동작 원리

공개키 암호는 키를 한 쌍으로 만든다. 공개키는 누구에게나 공개하고 개인키는 주인만 가진다. RSA의 경우 한쪽 키로 처리한 건 짝이 되는 다른 키로만 풀 수 있고, 공개키로 개인키를 알아내는 건 현실적으로 불가능하다. RSA는 큰 수의 소인수분해가, 타원곡선 방식은 타원곡선 위 이산로그 문제가 어렵다는 점을 이용한다.

  • 암호화: 받는 사람의 공개키로 암호화하면 받는 사람의 개인키로만 풀 수 있다. 같은 키를 미리 몰래 나눠 가져야 하는 대칭키 방식과 달리 키 전달 문제가 없다.
  • 전자서명: 메시지 해시를 자기 개인키로 서명하면 누구나 공개키로 확인할 수 있다. 개인키를 가진 사람만 서명을 만들 수 있으니 보낸 사람과 내용이 안 바뀌었음을 같이 확인한다.
  • 실제 사용: 공개키 연산은 느려서, 공개키로 상대를 확인하고 대칭키를 안전하게 정한 다음 실제 데이터는 빠른 대칭키로 암호화한다. 위의 SSH가 이 방식이다.

Ch04-Extra 슬라이드에서 ssh-keygen이 만든 cloud.key가 개인키, cloud.key.pub이 공개키다. 공개키를 VM의 authorized_keys에 넣어 두면 접속할 때 클라이언트가 개인키로 서명하고 서버가 공개키로 확인한다. 개인키는 네트워크로 안 가고 유출되면 안 되니까 권한을 -rw-------(600)로 둬서 주인만 읽게 한다.

Ch4-9. Master 노드에 root로 접속할 수 있나

교재의 Master 노드는 이 환경의 main(192.168.56.101)이다. 일반 계정으로 main에 접속해서 SSH 서버가 실제로 적용 중인 설정과 root 계정 상태를 확인했다.

sudo sshd -T | grep -i -E "^permitrootlogin|^passwordauthentication"
permitrootlogin without-password
passwordauthentication yes
sudo ls -l /etc/ssh/sshd_config.d/
-rw-------. 1 root root 412 May 19 09:00 40-redhat-crypto-policies.conf
-rw-------. 1 root root 307 May 19 09:00 50-redhat.conf
sudo passwd -S root
root P never 0 99999 7 -1

PermitRootLogin은 root의 SSH 로그인 허용 여부다.

값의미
yes비밀번호, 키 인증 모두 허용
prohibit-password키 인증만 허용
noroot 로그인 모두 거부

main의 값 without-password는 prohibit-password의 예전 이름이고 OpenSSH 기본값이다. sshd_config.d/에도 이걸 바꾸는 파일은 없었다. passwd -S의 P는 root에 비밀번호가 있다는 뜻이니까, 계정은 쓸 수 있지만 SSH 비밀번호 로그인은 막힌 상태다.

Ubuntu 호스트에서 root 비밀번호를 넣어 봐도 실제로 거부됐다.

ssh root@192.168.56.101
root@192.168.56.101's password:
Permission denied, please try again.
root 접속 거부

기본 설정(permitrootlogin without-password): 호스트에서 root 접속 거부

접근이 안 되니까 되게 바꿨다. sshd_config는 같은 설정이 여러 번 나오면 처음 읽은 값을 쓰고, sshd_config.d/의 파일은 이름순으로 맨 앞에서 읽는다. 그래서 기존 파일(40-, 50-)보다 먼저 읽히도록 00- 파일에 넣었다.

echo "PermitRootLogin yes" | sudo tee /etc/ssh/sshd_config.d/00-root-login.conf
sudo sshd -t && echo syntax OK
syntax OK
sudo systemctl restart sshd
sudo sshd -T | grep -i ^permitrootlogin
permitrootlogin yes

다시 ssh root@192.168.56.101을 치니 root 비밀번호로 접속돼서 프롬프트가 [root@main ~]#으로 바뀌었다. 접속 메시지의 "1 failed login attempt"는 바꾸기 전에 거부된 시도다.

root 접속 성공

PermitRootLogin yes 적용 후 호스트에서 root 접속 성공

root 원격 로그인은 비밀번호 추측 공격 대상이 되니까, 확인이 끝난 뒤 추가한 파일을 지우고 원래대로 돌렸다.

sudo rm /etc/ssh/sshd_config.d/00-root-login.conf
sudo systemctl restart sshd
sudo sshd -T | grep -i ^permitrootlogin
permitrootlogin without-password

Ch5-2. CPU 수와 슬롯 수의 관계

교재의 Slave1, Slave2는 work1, work2다. 두 VM은 이미 vCPU가 2개씩이라, CPU 2개 상태의 condor_status는 위의 클러스터 확인 화면과 같다. 슬롯은 slot1@work1.cloud.org, slot1@work2.cloud.org 두 줄이고 Total은 2다.

그런데 이 Total 2는 슬롯 수, 즉 노드 수지 CPU 수가 아니다. 노드별 CPU 수는 condor_status -af Name Cpus Memory로 따로 봤다. 아래 화면은 Ch5-5에서 main에도 실행 역할을 추가한 뒤에 찍어서 main까지 세 줄이 나오지만, work1·work2의 Cpus는 모두 2다. CPU가 노드마다 2개인데 슬롯은 노드마다 하나씩만 보인다.

condor_status -af

condor_status -af Name Cpus Memory: 노드마다 Cpus 2, Memory 1696MB, 슬롯은 slot1 하나

  • Partitionable 슬롯: HTCondor 23.0부터는 기본 설정에서 노드의 CPU와 메모리 전체가 하나의 Partitionable 슬롯(slot1)이 된다. 작업이 오면 이 슬롯에서 요청한 만큼(이번 실습은 CPU 1개, 메모리 128MB)을 떼어 Dynamic 슬롯(slot1_1, slot1_2)을 만든다.
  • 동시에 도는 작업 수: 그래서 condor_status 줄 수는 노드 수와 같지만, 동시에 도는 작업 수는 CPU 수를 따른다. 작업 3에서 CPU 4개로 작업이 4개씩 돈 게 그 결과다.
  • 정적 슬롯: 23.0 이전 기본 설정이나, 지금 버전에서 use FEATURE : StaticSlots를 켜면 CPU 하나에 슬롯 하나를 만든다. 이러면 CPU 2개 노드에 slot1, slot2가 생기고 노드마다 두 줄이 나온다.

정리하면 슬롯은 작업 하나가 실행되는 자리고, 작업이 CPU를 1개씩 요청하면 CPU 1개가 슬롯 1개에 대응한다. 정적 슬롯이면 슬롯 수 = CPU 수, Partitionable 슬롯이면 대기 중에는 노드마다 1개로 보이지만 작업이 들어오면 최대 CPU 수만큼 Dynamic 슬롯이 생긴다.

Ch5-5. Master도 작업을 처리하게 하기

main에는 central manager와 submit 역할만 있어서 작업을 실행하는 condor_startd가 없다. 그래서 슬롯이 work1·work2의 2개뿐이다. main에 execute 역할을 추가하면 startd가 돌면서 슬롯이 3개가 된다.

먼저 work1 설정에서 execute 역할이 어떤 줄로 지정됐는지 확인했다.

grep -r "use role" /etc/condor/config.d/
/etc/condor/config.d/01-execute.config:use role:get_htcondor_execute

같은 줄을 submit 역할 추가할 때처럼 main 설정 파일에 덧붙이고 condor를 재시작했다.

cd /etc/condor/config.d
echo "use role:get_htcondor_execute" | sudo tee -a 01-central-manager.config
sudo systemctl restart condor
CONDOR_HOST = main.cloud.org
# For details, run condor_config_val use role:get_htcondor_central_manager
use role:get_htcondor_central_manager
use role:get_htcondor_submit
use role:get_htcondor_execute

재시작 후 main에는 collector, negotiator, schedd와 함께 condor_startd가 떴다. 재시작 직후 condor_status에는 slot1@main.cloud.org 하나만 보였는데, collector가 다시 시작되면서 work1·work2 정보가 사라졌기 때문이다. 실행 노드는 주기적으로 자기 상태를 collector에 다시 보고하니까 약 2분 뒤 세 노드가 다 나타나서 Total 3이 됐다.

슬롯 3개

main에 execute 역할 추가 후 condor_status: slot1@main, slot1@work1, slot1@work2, Total 3

Ch5-6. GPG의 동작 방식

GPG(GNU Privacy Guard)는 OpenPGP 표준을 구현한 공개 소프트웨어로, 공개키 암호로 파일과 메시지를 암호화하고 서명한다.

  • 키 관리: gpg --full-generate-key로 공개키·개인키 쌍을 만든다. 공개키는 키 서버나 웹사이트로 배포하고, 다른 사람 공개키는 받아서 키링(keyring)에 저장한다. 키는 지문(fingerprint)으로 구별한다.
  • 암호화: 무작위 대칭키(세션 키)를 만들어 내용은 빠른 대칭키로 암호화하고, 세션 키만 받는 사람 공개키로 암호화해서 붙인다. 받는 사람은 자기 개인키로 세션 키를 꺼내 내용을 푼다.
  • 서명: 파일 해시를 만들어 자기 개인키로 서명한다. 받는 사람은 서명자 공개키로 서명을 확인하고 해시를 다시 계산해 비교하니까, 누가 만들었는지와 파일이 안 바뀌었는지를 같이 확인한다.
  • 신뢰 확인: 받은 공개키가 정말 그 사람 건지는 지문을 직접 대조하거나, 이미 믿는 사람이 서명해 준 키를 믿는 방식(Web of Trust)으로 판단한다.

5장에서 dnf로 HTCondor를 설치할 때도 GPG가 쓰였다. RPM 패키지에는 배포자의 GPG 서명이 붙어 있고, /etc/yum.repos.d/ 저장소 설정에 gpgcheck=1과 gpgkey=가 있으면 dnf가 배포자 공개키를 가져와 설치 전에 서명을 확인한다. 서명이 안 맞으면 설치를 거부하니까 받은 패키지가 중간에 바뀌지 않았음을 보장한다.

Ch6-2. 체크포인트와 리모트 시스템 콜

둘 다 standard universe의 기능이다. 프로그램을 condor_compile로 다시 링크하면 HTCondor 라이브러리가 같이 들어가서 쓸 수 있다.

체크포인트(Checkpoint)

  • 실행 중인 프로그램 상태(메모리, CPU 레지스터, 열린 파일과 읽던 위치 등)를 통째로 파일에 저장하는 것이다.
  • HTCondor는 쉬는 컴퓨터를 빌려 쓰는 시스템("cycle scavenger")이라, 주인이 돌아오거나 우선순위 높은 작업이 오면 실행 중인 작업이 중단될 수 있다. 체크포인트가 있으면 처음부터 다시 안 하고 저장된 지점부터 다른 기계에서 이어서 돌린다.
  • 주기적으로 저장해 두면 기계가 고장 나도 마지막 체크포인트부터 다시 시작할 수 있어서 오래 걸리는 작업일수록 효과가 크다.

리모트 시스템 콜(Remote System Call)

  • 작업이 파일 열기·읽기·쓰기 같은 시스템 콜을 하면, 실행 노드에서 처리하지 않고 제출 노드로 보내 처리하는 방식이다.
  • 작업에 링크된 HTCondor 라이브러리가 시스템 콜을 가로채 네트워크로 보내고, 제출 노드의 condor_shadow 프로세스가 대신 실행해서 결과를 돌려준다.
  • 그래서 작업은 어느 기계에서 돌든 제출 노드 파일을 그대로 쓰는 것처럼 동작하고, 실행 노드에 사용자 계정이나 공유 파일 시스템이 없어도 된다. 체크포인트로 다른 기계로 옮겨져도 파일 접근이 안 끊긴다.

다만 standard universe와 condor_compile은 HTCondor 9.0에서 삭제돼서 이번에 설치한 25.x에서는 못 쓴다. 그래서 이번 실습은 vanilla universe를 썼다. vanilla에서는 리모트 시스템 콜 대신 앞에서 본 파일 전송 방식을 쓰고, 체크포인트도 자동으로 안 된다. 대신 프로그램이 스스로 상태를 파일에 저장하고 정해 둔 종료 코드(checkpoint_exit_code)로 끝나면, HTCondor가 그 파일을 보관했다가 이어서 다시 실행하는 self-checkpointing을 쓸 수 있다.

Ch6-9. DAGMan

DAGMan(Directed Acyclic Graph Manager)은 서로 의존하는 여러 HTCondor 작업을 정해진 순서대로 실행해 주는 도구다. 작업을 노드로, "이 작업이 끝나야 저 작업을 시작한다"는 관계를 방향 있는 간선으로 나타낸 그래프를 쓴다. 순환이 있으면 어느 작업도 먼저 시작할 수 없으니까 순환 없는(Acyclic) 그래프만 허용한다.

example.dag
JOB A a.jds
JOB B b.jds
JOB C c.jds
JOB D d.jds
PARENT A CHILD B C
PARENT B C CHILD D
condor_submit_dag example.dag

A가 끝나면 B와 C를 동시에 제출하고, 둘 다 끝나면 D를 제출한다. 각 노드의 jds는 지금까지 쓴 작업명세서와 같다. condor_submit_dag을 실행하면 DAGMan 자체가 하나의 HTCondor 작업으로 제출 노드에서 돌면서, 각 작업 log 파일을 보고 끝난 작업의 다음 작업을 제출한다.

유용성

  • 순서 자동화: 사람이 앞 작업이 끝났는지 보고 다음 걸 제출할 필요가 없다. "단계 안에서는 독립이고 단계 사이에는 의존하는" 작업을 그대로 표현할 수 있다.
  • 병렬성 유지: 서로 의존하지 않는 노드는 동시에 제출되니까 HTC 장점을 안 잃는다.
  • 실패 처리: RETRY로 실패한 노드를 자동으로 다시 돌린다. 그래도 실패하면 이미 성공한 노드를 기록한 rescue DAG 파일을 만들어서, 다시 제출할 때 실패한 지점부터 이어서 실행한다.
  • 전처리와 후처리: 노드마다 실행 전후 스크립트(SCRIPT PRE, SCRIPT POST)를 붙여 입력을 준비하거나 결과를 검사할 수 있다.
  • 사용 예: 데이터 전처리 → 많은 수의 독립 분석 → 결과 취합으로 이어지는 과학 계산 파이프라인에 쓴다. 과제 표절 검사도 전처리, 4,950개 비교, 결과 취합을 하나의 DAG로 만들 수 있다.