[MLOps] 재부팅 후 MIG 모드와 인스턴스 자동 복원하기

MIG 모드와 인스턴스의 재부팅 동작을 구분하고, 호스트에서 분할 구성을 자동 복원하는 systemd와 kubelet 설정을 설명합니다.

개요

MIG로 GPU를 분할한 뒤 서버를 재부팅하면 생성했던 장치가 사라질 수 있습니다.
다시 말해 재부팅 후 같은 분할 구성을 사용하려면 부팅 과정에 복원 명령을 넣어야 합니다.

이 글에서는 호스트에 정상 분할 구성을 저장하고 MIG 복원을 마친 뒤 kubelet을 시작하도록 구성하는 방법을 설명합니다.

아래 내용은 호스트에서 MIG를 관리하는 구성 예제입니다.
실제 서버에서 재부팅과 GPU 작업 복귀를 시험하지 않았으므로 적용할 장비에서 확인이 필요합니다.

재부팅 시 초기화되는 MIG 상태

MIG 모드와 MIG 인스턴스는 구분해서 살펴봐야 합니다.
모드가 켜져 있어도 작업을 실행할 인스턴스가 없으면 CUDA 작업을 실행할 수 없습니다.

NVIDIA의 GPU Reset on Hopper+ GPUs는 다음과 같이 명시합니다.

MIG mode is no longer persistent across system reboots.

Hopper부터 MIG 모드는 드라이버 커널 모듈이 로드된 동안만 유지됩니다.
재부팅하거나 모듈을 unload/reload하면 MIG 모드가 해제됩니다.
Hopper는 MIG 모드를 활성화할 때 GPU reset이 필요하지 않습니다.

GPU 세대재부팅 후 MIG 모드재부팅 후 GPU·Compute 인스턴스
Hopper, H100/H200 등해제되므로 다시 활성화다시 생성
Ampere, A100/A30 등InfoROM에 저장되어 유지다시 생성

Creating GPU Instances는 생성한 MIG 장치가 재부팅 후 유지되지 않는다고 설명합니다.
A100에서 MIG 모드가 유지되더라도 인스턴스는 다시 만들어야 합니다.
-mig 1로 모드만 활성화하는 명령을 부팅 시 실행해서는 복원이 끝나지 않습니다.

호스트에서 자동 복원하는 흐름

nvidia-mig-parted는 원하는 MIG 구성을 YAML 파일로 저장하고 재적용하는 도구입니다.
부팅할 때 이 파일을 읽어 모드와 인스턴스를 복원하도록 systemd 서비스를 구성합니다.

  1. 드라이버 준비: GPU를 조회할 수 있는 상태인지 확인합니다.
  2. MIG 복원: apply로 저장한 분할 구성을 재적용합니다.
  3. 복원 검증: assert로 실제 구성이 저장한 구성과 같은지 확인합니다.
  4. Kubernetes 시작: 검증이 성공한 뒤 kubelet을 시작합니다. device plugin을 사용하는 환경에서는 복원된 장치를 인식하도록 합니다.

이 순서를 적용하려면 복원 서비스 등록과 kubelet 의존성 설정이 함께 필요합니다.
도구와 실행 환경을 확인한 뒤 정상 MIG 구성을 저장합니다.

적용 환경 확인

아래 명령은 대상 GPU 노드에서 실행합니다.
이 예제는 다음 조건을 전제로 합니다.

nvidia-smi --query-gpu=index,name,uuid,mig.mode.current --format=csv
nvidia-smi -L
command -v nvidia-mig-parted
systemctl cat kubelet.service
systemctl is-enabled nvidia-mig-manager.service
systemctl is-active nvidia-mig-manager.service

조회 결과로 GPU 모델과 현재 MIG 장치를 확인합니다.
드라이버가 Kubernetes Pod에서만 제공되는 환경은 kubelet을 먼저 시작해야 할 수 있으므로 이 부팅 순서를 그대로 적용하지 않습니다.

nvidia-mig-parted가 없으면 NVIDIA 공식 릴리스에서 OS와 CPU 아키텍처에 맞는 패키지를 설치합니다.
이 예제에서는 /usr/bin/nvidia-mig-parted와 /usr/bin/nvidia-smi를 사용합니다.
실제 경로가 다르면 뒤에 나오는 서비스의 ExecStartPre, ExecStart, ExecStartPost를 변경해야 합니다.

공식 패키지는 nvidia-mig-manager.service도 설치합니다.
기본 목표 구성은 all-disabled이므로 새 복원 서비스와 중복 실행하지 않도록 확인합니다.

sudo systemctl disable nvidia-mig-manager.service

두 서비스가 서로 다른 목표 구성을 적용하면 복원 결과가 달라질 수 있습니다.
부팅 시 MIG 구성을 적용할 서비스는 하나로 정합니다.

정상 MIG 구성 저장

nvidia-smi -L에서 원하는 프로필과 수량이 보이는 상태를 저장합니다.
초기화된 상태를 export하면 빈 구성도 그대로 저장됩니다.
이미 초기화됐다면 기존 분할 명령으로 원하는 구성을 먼저 복구해야 합니다.

아래 명령은 임시 파일에 구성을 저장합니다.
현재 구성과 일치하는지 검증한 뒤 /etc/nvidia-mig/config.yaml로 옮깁니다.

bash <<'BASH'
set -euo pipefail
MIG_CONFIG_TMP=$(mktemp)
trap 'rm -f "$MIG_CONFIG_TMP"' EXIT
sudo nvidia-mig-parted export > "$MIG_CONFIG_TMP"
cat "$MIG_CONFIG_TMP"
sudo nvidia-mig-parted assert -f "$MIG_CONFIG_TMP" -c current
sudo install -D -m 0644 "$MIG_CONFIG_TMP" /etc/nvidia-mig/config.yaml
BASH

export나 검증이 실패하면 기존 설정 파일을 덮어쓰지 않습니다.
export에는 노드 전체 GPU의 구성이 들어가므로 출력의 mig-enabled와 mig-devices가 원하는 값인지 확인합니다.

export한 YAML의 구성 이름은 current입니다.
복원 서비스에서도 같은 이름을 선택합니다.

부팅 복원 서비스 구성

저장한 YAML을 읽어 MIG를 복원하는 서비스를 만듭니다.
/etc/systemd/system/nvidia-mig-restore.service에 아래 내용을 저장합니다.
이 예제에는 공식 manager의 hooks를 추가하지 않습니다.

sudo tee /etc/systemd/system/nvidia-mig-restore.service >/dev/null <<'EOF'
[Unit]
Description=Restore NVIDIA MIG configuration before kubelet
After=systemd-modules-load.service nvidia-persistenced.service nvidia-fabricmanager.service
Before=kubelet.service

[Service]
Type=oneshot
RemainAfterExit=yes
TimeoutStartSec=480
ExecStartPre=/usr/bin/nvidia-smi
ExecStart=/usr/bin/nvidia-mig-parted apply -f /etc/nvidia-mig/config.yaml -c current
ExecStartPost=/usr/bin/nvidia-mig-parted assert -f /etc/nvidia-mig/config.yaml -c current

[Install]
WantedBy=multi-user.target
EOF

서비스가 실행하는 명령은 세 단계입니다.

  1. ExecStartPre: nvidia-smi로 GPU를 조회합니다.
  2. ExecStart: apply로 MIG 모드와 인스턴스 구성을 재적용합니다.
  3. ExecStartPost: assert로 저장한 구성과 실제 구성을 비교합니다.

RemainAfterExit=yes는 복원 성공 후 서비스의 활성 상태를 유지합니다.
첫 복원이 성공한 뒤 kubelet을 재시작할 때마다 MIG 복원이 반복되는 것을 피할 수 있습니다.
다음으로 kubelet이 이 서비스의 성공을 기다리도록 연결합니다.

kubelet 시작 순서 연결

Before=kubelet.service는 실행 순서를 지정합니다.
복원이 실패했을 때 kubelet의 시작도 막으려면 kubelet 쪽에 의존성을 추가해야 합니다.

/etc/systemd/system/kubelet.service.d/20-mig-restore.conf를 만들고 복원 서비스를 활성화합니다.

sudo mkdir -p /etc/systemd/system/kubelet.service.d
sudo tee /etc/systemd/system/kubelet.service.d/20-mig-restore.conf >/dev/null <<'EOF'
[Unit]
Requires=nvidia-mig-restore.service
After=nvidia-mig-restore.service
EOF
sudo systemctl daemon-reload
sudo systemctl enable nvidia-mig-restore.service
sudo systemctl cat nvidia-mig-restore.service kubelet.service

두 설정을 함께 사용하면 복원 서비스가 실패했을 때 kubelet의 시작을 막습니다.
복원이 실패한 노드는 Ready로 복귀하지 않을 수 있으므로 서비스 로그를 확인해야 합니다.

enable은 다음 부팅을 위한 등록입니다.
위 명령은 현재 서비스를 시작하거나 서버를 재부팅하지 않습니다.

설정 반영 후 첫 재부팅 전에는 복원 서비스와 kubelet을 시작·재시작하지 않습니다.
복원 서비스가 아직 실행되지 않은 상태에서 kubelet을 시작하면 의존성에 따라 MIG 복원이 즉시 실행됩니다.
kubelet을 중지해도 기존 GPU 컨테이너가 계속 실행될 수 있으므로 작업과 충돌할 수 있습니다.

재부팅 후 복원 확인

다음 예정된 재부팅이 끝나면 GPU 노드에서 복원 서비스와 MIG 장치를 확인합니다.
서비스의 성공 상태와 실제 분할 구성을 함께 조회합니다.

systemctl status nvidia-mig-restore.service kubelet.service --no-pager
sudo journalctl -b -u nvidia-mig-restore.service --no-pager -n 100
sudo nvidia-mig-parted assert -f /etc/nvidia-mig/config.yaml -c current
nvidia-smi -L

확인할 항목은 다음과 같습니다.

Kubernetes에서 GPU를 할당하는 환경은 관리 터미널에서 노드의 자원도 조회합니다.
MIG_NODE를 실제 노드명으로 바꿔 실행합니다.

MIG_NODE='실제-GPU-노드명'
kubectl get node "$MIG_NODE" -o wide
kubectl describe node "$MIG_NODE"

device plugin을 사용한다면 Capacity와 Allocatable에 표시된 GPU/MIG 자원을 확인합니다.
plugin이나 DCGM Exporter가 실행된 뒤 MIG 구성을 변경했다면 해당 노드에서 장치를 다시 인식하는 절차가 필요합니다.
NVIDIA의 systemd hooks에도 관련 서비스와 컨테이너를 갱신하는 처리가 있습니다.

자동 복원의 범위

이 구성은 부팅 시 분할 구성을 복원하는 방법입니다.
MIG 구성을 다시 만드는 것과 실행 중인 작업 상태를 보존하는 것은 구분해야 합니다.

kubelet 의존성은 Kubernetes 쪽의 시작 순서를 제어합니다.
호스트에서 별도로 시작하는 GPU 작업까지 같은 순서로 실행되지는 않습니다.

자동 복원 해제

자동 복원을 해제하려면 kubelet에 추가한 의존성을 먼저 제거합니다.
그다음 복원 서비스의 부팅 활성화를 해제합니다.

sudo rm /etc/systemd/system/kubelet.service.d/20-mig-restore.conf
sudo systemctl daemon-reload
sudo systemctl disable nvidia-mig-restore.service

이 명령은 현재 MIG 분할을 삭제하지 않습니다.
공식 manager를 다시 활성화하려면 해당 manager의 목표 구성을 먼저 확인해야 합니다.

Reference