Published on

Azure VM 부팅 실패 OSProvisioningTimedOut 해결 가이드

Authors

서버를 새로 띄우거나(프로비저닝), 재배포/스케일링을 걸었는데 Azure Portal에 OSProvisioningTimedOut가 뜨면 대부분 “VM은 하이퍼바이저 레벨에서 켜졌지만, 게스트 OS가 Azure 에이전트/프로비저닝 단계를 정해진 시간 내 완료하지 못했다”는 의미입니다. 특히 커스텀 이미지(골든 이미지), cloud-init, VM Extension, 초기 부팅 시 디스크/네트워크 문제, 또는 에이전트 손상 같은 요인으로 발생합니다.

이 글은 원인 분류 → 증거 수집(로그) → 복구(단기) → 재발 방지(장기) 흐름으로 정리합니다. 운영 환경에서는 “원인 추정”보다 “증거 확보 후 최소 변경으로 복구”가 훨씬 중요합니다.

OSProvisioningTimedOut가 의미하는 것

Azure VM 프로비저닝은 대략 아래 단계를 거칩니다.

  1. Compute 리소스 할당(호스트/하이퍼바이저)
  2. OS 부팅(커널/부트로더)
  3. Azure 에이전트(Windows: Guest Agent, Linux: waagent) 및 cloud-init 실행
  4. 네트워크 설정, SSH/RDP 준비, 확장(Extensions) 적용
  5. Azure가 “OS Provisioning 성공”으로 상태 전환

OSProvisioningTimedOut는 2~4 구간에서 VM이 “살아는 있는데” Azure가 성공 신호를 못 받는 경우가 많습니다. 즉, 부팅은 했지만 로그인 불가/네트워크 불가/에이전트 불가/확장 실패 등의 형태로 나타납니다.

먼저 할 일: 관측 포인트(증거) 확보

타임아웃은 원인이 다양하므로, 아래 4가지를 먼저 확보하면 진단 속도가 크게 올라갑니다.

1) Boot diagnostics(부트 진단) 스크린샷/직렬 로그

Portal → VM → Boot diagnostics에서 스크린샷과 Serial log를 봅니다.

  • 커널 패닉/드라이버 로딩 실패
  • 디스크 마운트 실패(unable to mount root fs)
  • cloud-init 단계에서 멈춤

2) Serial Console(직렬 콘솔)로 실제 부팅 상태 확인

Serial Console이 켜져 있다면 가장 빠릅니다.

  • Linux: journalctl -b, systemctl status, cloud-init status --long
  • Windows: SAC/EMS 콘솔로 부팅 단계 확인

3) Azure Activity log / Resource health

  • VM 생성/확장 적용 시점에 어떤 작업이 실패했는지
  • 플랫폼 이슈인지(호스트 장애/스토리지 이슈) 확인

4) Extensions 상태

Portal → VM → Extensions + applications에서 실패한 확장이 있는지 확인합니다.

특히 Custom Script Extension, DSC(Windows), AAD Login, Monitoring Agent 계열이 부팅 후 네트워크/권한 문제로 타임아웃을 유발할 수 있습니다.

대표 원인 7가지와 빠른 판별법

1) cloud-init/user-data가 무한 대기 또는 실패

증상:

  • 부트 진단에서 로그인 프롬프트는 보이는데 Azure는 성공 처리 못 함
  • cloud-init statusrunning에서 끝나지 않음

확인(Serial Console):

cloud-init status --long
sudo tail -n 200 /var/log/cloud-init.log
sudo tail -n 200 /var/log/cloud-init-output.log

해결:

  • user-data에서 **네트워크 의존 작업(apt/yum, curl)**을 부팅 초기에 과도하게 수행하지 않기
  • 외부 저장소/프록시/방화벽으로 패키지 설치가 막히면 cloud-init이 길게 대기
  • 장기 작업은 systemd timer/후속 구성 관리로 분리

2) Linux Azure Agent(waagent) 손상/비활성

증상:

  • SSH는 되는데 Portal에서 프로비저닝 완료가 안 됨
  • 확장 설치가 계속 실패

확인:

systemctl status walinuxagent
journalctl -u walinuxagent -b --no-pager | tail -n 200
sudo waagent -version

해결(배포판별 패키지명은 다를 수 있음):

# Ubuntu/Debian 계열 예시
sudo apt-get update
sudo apt-get install --reinstall -y walinuxagent
sudo systemctl enable --now walinuxagent

커스텀 이미지라면 에이전트 버전/설정이 이미지에 고정되어 문제가 반복될 수 있습니다.

3) VM Extension 실패(네트워크/권한/리포지토리)

증상:

  • Extensions에 Provisioning failed가 보임
  • Custom Script가 외부 URL 다운로드에서 멈춤

확인(Azure CLI):

az vm extension list -g <rg> --vm-name <vm> -o table
az vm extension show -g <rg> --vm-name <vm> -n <extName> -o jsonc

즉시 조치:

  • 실패 확장을 삭제 후 부팅 성공 여부 확인
  • Custom Script는 짧고 멱등하게, 긴 작업은 VM 내부에서 후속 실행

> 확장 기반 자동화가 잦다면, VMSS에서도 비슷한 패턴의 장애가 반복됩니다. 확장/업데이트 충돌은 Azure VM 확장셋 업데이트 중 409 Conflict 해결도 함께 참고하면 좋습니다.

4) 네트워크 초기화 실패(UDR/NSG/DNS)

증상:

  • 부팅은 되는데 확장/에이전트가 Azure 엔드포인트에 접근 못 함
  • 사설 DNS/프록시 환경에서 특히 빈번

체크리스트:

  • NSG에서 아웃바운드가 막혀 있지 않은가
  • UDR이 0.0.0.0/0을 방화벽으로 보내는데 예외 경로가 없는가
  • DNS가 Azure 서비스 도메인을 해석 못 하는가

VM 내부에서:

# DNS 확인
resolvectl status || cat /etc/resolv.conf

# Azure 메타데이터(IMDS) 접근(네트워크 기본 확인)
curl -s -H Metadata:true "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | head

5) OS 디스크/파일시스템 문제

증상:

  • 부트 진단에 fsck 요구, 마운트 실패
  • 커널이 root disk를 못 찾음

대응:

  • Serial Console로 들어가 fsck 수행(가능한 경우)
  • 안 되면 OS 디스크를 다른 복구 VM에 attach해서 오프라인 복구

6) 커스텀 이미지 일반화(Sysprep/waagent -deprovision) 누락

증상:

  • 동일 이미지로 만든 VM이 반복적으로 OSProvisioningTimedOut
  • 호스트명/SSH 키/에이전트 상태가 꼬임

핵심:

  • Linux: 이미지 만들기 전 waagent -deprovision+user 수행
  • Windows: Sysprep 일반화 후 캡처

이 케이스는 “한 번 고쳐도 다음 배포에서 재발”하는 전형입니다.

7) 부팅 시간 자체가 과도(대용량 초기화/암호화/업데이트)

증상:

  • 결국은 부팅되지만 Azure 타임아웃 전에 완료 못 함

해결:

  • 초기 부팅에서 대규모 업데이트/디스크 초기화 작업 제거
  • 필요 시 프로비저닝 타임아웃 관점에서 설계를 변경(후속 구성으로 분리)

실전 복구 플로우(가장 많이 통하는 순서)

운영에서 “빨리 살리는” 관점의 추천 순서입니다.

1) 재시도 전에 상태 고정: 스냅샷/복제

문제 디스크를 건드리기 전, OS 디스크 스냅샷을 떠두면 롤백이 쉽습니다.

# OS 디스크 ID 확인
az vm show -g <rg> -n <vm> --query "storageProfile.osDisk.managedDisk.id" -o tsv

# 스냅샷 생성(Managed Disk 기준)
az snapshot create -g <rg> -n <snapName> --source <osDiskId>

2) 부트 진단 + Serial Console로 로그 확인

  • cloud-init/waagent/확장 로그에서 “막히는 지점”을 찾습니다.

Linux에서 많이 보는 로그:

sudo journalctl -b --no-pager | tail -n 200
sudo journalctl -u walinuxagent -b --no-pager | tail -n 200
sudo tail -n 200 /var/log/waagent.log

3) 확장 실패면: 확장 제거 후 부팅 확인

특히 Custom Script가 외부 다운로드에서 멈추는 경우가 흔합니다.

az vm extension delete -g <rg> --vm-name <vm> -n <extName>

4) 네트워크 의심이면: 최소 규칙으로 검증

  • 임시로 NSG 아웃바운드 허용(또는 UDR 우회) 후 프로비저닝이 완료되는지 확인
  • 사설 DNS 환경이면 Azure 필수 도메인 해석/연결이 되는지 확인

5) OS 자체 문제면: 디스크 오프라인 복구

VM이 아예 로그인 불가라면 “복구 VM”을 하나 만든 뒤 OS 디스크를 attach해서 고칩니다.

대략적인 절차:

  1. 문제 VM Stop(deallocate)
  2. OS 디스크를 detach(또는 스냅샷에서 새 디스크 생성)
  3. 복구 VM에 data disk로 attach
  4. 마운트 후 /etc/fstab, 네트워크 설정, cloud-init 설정, 에이전트 파일 등을 수정

Linux에서 attach된 디스크 마운트 예시:

lsblk
sudo mkdir -p /mnt/rescue
sudo mount /dev/sdc2 /mnt/rescue

# 예: fstab 오류로 부팅이 멈추는 경우 확인
sudo cat /mnt/rescue/etc/fstab

재발 방지: 골든 이미지/프로비저닝 설계 팁

cloud-init는 “부팅 필수 작업”만

  • 패키지 설치/외부 API 호출/대규모 git clone은 실패 확률이 높습니다.
  • 부팅 필수는 SSH 사용자/키, 기본 에이전트, 로그 수집 정도로 제한
  • 나머지는 systemd service로 분리하고 재시도(backoff) 설계

확장(Custom Script)은 짧고 멱등하게

  • 같은 스크립트가 여러 번 실행돼도 안전하도록(파일 존재 체크, lock 사용)
  • 네트워크 실패 시 무한 대기 대신 제한된 재시도

간단한 재시도 예시(네트워크 다운로드):

#!/usr/bin/env bash
set -euo pipefail

url="https://example.com/bootstrap.sh"
out="/var/tmp/bootstrap.sh"

for i in {1..10}; do
  if curl -fsSL "$url" -o "$out"; then
    break
  fi
  sleep $((i*3))
done

bash "$out"

장애를 “로그로 남기는 구조”로

OSProvisioningTimedOut는 결과적으로 타임아웃이기 때문에, 원인 로그가 없으면 재현이 어렵습니다. 부팅 단계에서 아래를 남기면 좋습니다.

  • cloud-init output을 /var/log/cloud-init-output.log에 남기기
  • 부팅 스크립트 stdout/stderr를 파일로 리다이렉트
  • 확장 스크립트 내부에 타임스탬프/단계 로깅

타임아웃성 장애는 다른 영역에서도 같은 패턴

프로비저닝 타임아웃은 결국 “의존성(네트워크/리소스/권한) + 재시도 설계 부재”로 귀결되는 경우가 많습니다. 애플리케이션 레벨에서도 같은 문제가 반복되므로, 재시도/백오프 설계를 함께 점검하는 것이 좋습니다. 예를 들어 HTTP 클라이언트 재시도 설계는 Python httpx ReadTimeout·ConnectError 재시도 설계에서 원칙을 정리해두었습니다.

체크리스트(요약)

  • Boot diagnostics에서 커널/마운트/fsck 메시지 확인
  • Serial Console로 cloud-init, walinuxagent, waagent.log 확인
  • Extensions 실패 여부 확인 후 삭제로 빠른 우회
  • NSG/UDR/DNS로 Azure 엔드포인트 접근 가능 여부 확인
  • 커스텀 이미지라면 일반화(waagent deprovision/Sysprep) 재점검
  • 부팅 단계 작업을 최소화하고, 긴 작업은 후속 구성으로 분리

마무리

OSProvisioningTimedOut는 “Azure가 VM 내부 준비 완료 신호를 못 받았다”는 결과일 뿐, 원인은 OS/네트워크/에이전트/확장/이미지 품질로 넓게 퍼져 있습니다. 따라서 부트 진단/Serial Console/확장 상태 세 축으로 증거를 먼저 모으고, 가장 영향이 작은 조치(확장 제거, 네트워크 임시 완화)부터 적용해 복구한 뒤, 최종적으로는 골든 이미지와 프로비저닝 스크립트를 단순화하는 방향으로 재발을 막는 것이 정석입니다.