- Published on
Azure VM 부팅 실패 OSProvisioningTimedOut 해결 가이드
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버를 새로 띄우거나(프로비저닝), 재배포/스케일링을 걸었는데 Azure Portal에 OSProvisioningTimedOut가 뜨면 대부분 “VM은 하이퍼바이저 레벨에서 켜졌지만, 게스트 OS가 Azure 에이전트/프로비저닝 단계를 정해진 시간 내 완료하지 못했다”는 의미입니다. 특히 커스텀 이미지(골든 이미지), cloud-init, VM Extension, 초기 부팅 시 디스크/네트워크 문제, 또는 에이전트 손상 같은 요인으로 발생합니다.
이 글은 원인 분류 → 증거 수집(로그) → 복구(단기) → 재발 방지(장기) 흐름으로 정리합니다. 운영 환경에서는 “원인 추정”보다 “증거 확보 후 최소 변경으로 복구”가 훨씬 중요합니다.
OSProvisioningTimedOut가 의미하는 것
Azure VM 프로비저닝은 대략 아래 단계를 거칩니다.
- Compute 리소스 할당(호스트/하이퍼바이저)
- OS 부팅(커널/부트로더)
- Azure 에이전트(Windows: Guest Agent, Linux: waagent) 및 cloud-init 실행
- 네트워크 설정, SSH/RDP 준비, 확장(Extensions) 적용
- 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 status가running에서 끝나지 않음
확인(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해서 고칩니다.
대략적인 절차:
- 문제 VM Stop(deallocate)
- OS 디스크를 detach(또는 스냅샷에서 새 디스크 생성)
- 복구 VM에 data disk로 attach
- 마운트 후
/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/확장 상태 세 축으로 증거를 먼저 모으고, 가장 영향이 작은 조치(확장 제거, 네트워크 임시 완화)부터 적용해 복구한 뒤, 최종적으로는 골든 이미지와 프로비저닝 스크립트를 단순화하는 방향으로 재발을 막는 것이 정석입니다.