Published on

Azure VM 확장셋 업데이트 중 409 Conflict 해결

Authors

서론

Azure VM Scale Set(VMSS)을 운영하다 보면 이미지 교체, 확장(Scale-out/in), 인스턴스 리이미징, 확장 기능(Extensions) 업데이트 같은 작업을 자주 수행합니다. 문제는 이런 작업들이 VMSS 내부적으로는 장시간 실행되는 비동기 오퍼레이션으로 처리된다는 점입니다. 그 결과, 이전 작업이 아직 끝나지 않았거나(혹은 백엔드에서 잠금이 유지되는 동안) 다음 업데이트를 시도하면 409 Conflict가 발생합니다.

이 글에서는 VMSS 업데이트 중 발생하는 409의 핵심 원인을 분류하고, **진단(현재 진행 중인 작업 확인) → 충돌 제거(대기/취소/순서 조정) → 재발 방지(배포 파이프라인 설계)**까지 실전 위주로 정리합니다. 비슷한 성격의 “요청은 정상인데 서버 측 상태/락 때문에 실패” 문제를 다룬 글로는 OpenAI Responses API 502 Bad Gateway 원인과 해결도 참고할 만합니다.

409 Conflict가 VMSS에서 발생하는 대표 패턴

Azure Resource Manager(ARM) 계열 API에서 409는 보통 다음 중 하나입니다.

  1. 동일 리소스에 대한 동시 업데이트(Write 충돌)
    • 예: 파이프라인 A가 VMSS 모델 업데이트 중인데, 파이프라인 B가 인스턴스 업그레이드/확장 기능 변경을 동시에 수행
  2. 장기 실행 오퍼레이션(LRO) 진행 중
    • 예: rolling upgrade, reimage, upgrade policy 변경, automatic repairs 연동 작업이 진행 중
  3. 확장 기능(Extensions) 설치/업데이트 충돌
    • 예: Custom Script Extension이 실행 중인데 또 다른 extension 변경이 들어옴
  4. 인스턴스 상태 전이 중(프로비저닝/업그레이드 중)
    • 예: 특정 인스턴스가 Updating/Creating 상태인데 전체 모델 업데이트 또는 인스턴스 업데이트를 강행

Azure 포털에서는 대개 “Another operation is in progress”, “Conflict”, “Operation is not allowed” 같은 메시지로 뭉뚱그려 보이지만, CLI/REST로 보면 원인 힌트가 더 잘 드러납니다.

1) 먼저: 어떤 작업이 진행 중인지 확인하기

409을 해결하는 가장 빠른 길은 지금 VMSS에 걸려있는 작업(오퍼레이션/락)을 확인하는 것입니다.

Activity Log로 충돌 원인 파악

가장 신뢰도가 높은 1차 진단은 Activity Log입니다.

# 최근 1시간 VMSS 관련 이벤트 조회
az monitor activity-log list \
  --resource-group <RG> \
  --resource-id $(az vmss show -g <RG> -n <VMSS> --query id -o tsv) \
  --offset 1h \
  -o table

여기서 Status, OperationName, SubStatus를 보면 “Update Virtual Machine Scale Set”, “Upgrade Virtual Machine Scale Set Instances”, “Create or Update Extension” 등이 겹쳐 있는지 확인할 수 있습니다.

VMSS 인스턴스 프로비저닝 상태 확인

특정 인스턴스가 업데이트 중이면 전체 작업이 꼬일 수 있습니다.

az vmss list-instances \
  -g <RG> -n <VMSS> \
  --query "[].{id:instanceId, provisioning:provisioningState, power:powerState}" \
  -o table

provisioningStateUpdating, Creating, Failed로 오래 유지되는 인스턴스가 있다면, 그 인스턴스가 충돌의 원인일 가능성이 큽니다.

(중요) 최신 모델 vs 인스턴스 적용 상태 확인

VMSS는 “모델(model)”과 “인스턴스(instance)”가 분리되어 있습니다. 모델만 바뀌고 인스턴스가 아직 업그레이드되지 않은 상태에서 또 업데이트를 걸면 충돌이 자주 납니다.

# VMSS 업그레이드 정책 확인
az vmss show -g <RG> -n <VMSS> --query "upgradePolicy" -o jsonc

# 인스턴스가 최신 모델을 적용했는지(최신 모델 적용 여부는 환경/정책에 따라 해석 필요)
az vmss list-instances -g <RG> -n <VMSS> \
  --query "[].{id:instanceId, latestModel:latestModelApplied, provisioning:provisioningState}" \
  -o table

latestModelApplied=false가 많다면, 모델 업데이트 이후 인스턴스 롤링 업그레이드가 아직 진행 중이거나 대기 중일 수 있습니다.

2) 해결 전략 A: “대기”가 정답인 케이스

가장 흔한 409 원인은 단순히 이전 작업이 아직 끝나지 않은 것입니다. 특히 아래 작업은 시간이 길어 409를 유발하기 쉽습니다.

  • 이미지/OS 디스크 관련 변경
  • Rolling upgrade(특히 maxBatchInstancePercent가 낮을 때)
  • Extension 설치(스크립트 실행 포함)

이 경우 해결은 단순합니다.

  1. Activity Log에서 진행 중 작업 확인
  2. 완료될 때까지 대기
  3. 동일 업데이트 재시도

배포 파이프라인에서는 “재시도”를 코드로 넣는 편이 안전합니다.

Azure CLI 재시도(간단 예시)

set -e

for i in {1..10}; do
  echo "Attempt $i"
  if az vmss update -g <RG> -n <VMSS> --set tags.env=prod; then
    echo "Success"
    exit 0
  fi
  echo "Failed. Sleep 30s..."
  sleep 30

done

echo "Failed after retries"
exit 1

포인트는 409는 일시적 충돌일 수 있으므로(특히 LRO) 지수 백오프(예: 10s, 20s, 40s…)를 적용하면 훨씬 안정적입니다.

3) 해결 전략 B: “동시성 제거”가 필요한 케이스

CI/CD에서 흔한 실수는 다음입니다.

  • Terraform/ARM/Bicep 배포가 VMSS 모델 업데이트를 수행
  • 동시에 스케일 작업(autoscale/수동 scale)이 발생
  • 동시에 az vmss extension set 같은 별도 작업이 실행

이때는 단순 대기만으로는 “계속 재발”합니다. 해결은 업데이트를 직렬화하는 것입니다.

권장 순서(안전한 직렬화)

  1. (가능하면) Autoscale 일시 중지 또는 배포 윈도우 확보
  2. VMSS 모델 업데이트(이미지/태그/설정)
  3. 인스턴스 업그레이드(수동 정책일 때)
  4. 확장 기능 업데이트(필요 시)

특히 upgradePolicy.mode=Manual이면 모델 업데이트 후 반드시 인스턴스 업그레이드를 별도로 수행해야 합니다.

# (Manual 정책 가정) 모델 업데이트 후 인스턴스 업그레이드
az vmss update -g <RG> -n <VMSS> --set tags.release=2026-02-23

# 전체 인스턴스 업그레이드
az vmss update-instances -g <RG> -n <VMSS> --instance-ids "*"

파이프라인 락(간단한 아이디어)

  • GitHub Actions: concurrency 그룹 사용
  • Azure DevOps: environment lock/approvals
  • 자체 락: Storage Blob lease, Redis lock 등

409은 기술적으로는 API 충돌이지만, 운영 관점에서는 “동일 리소스에 대한 동시 배포” 문제인 경우가 많습니다.

4) 해결 전략 C: Extension 충돌(특히 Custom Script) 정리

VMSS Extension은 설치/업데이트가 LRO로 동작하고, 실행 중인 스크립트가 길면 다음 변경이 409로 막히기 쉽습니다.

현재 확장 기능 상태 확인

az vmss extension list -g <RG> --vmss-name <VMSS> -o table

확장 기능 업데이트는 모델 업데이트와 분리

가능하면 “모델 업데이트(이미지/네트워크/태그)”와 “확장 기능 업데이트”를 같은 배포에서 동시에 하지 말고, 단계 분리로 충돌을 줄입니다.

# 예: Custom Script Extension 업데이트(예시)
az vmss extension set \
  -g <RG> \
  --vmss-name <VMSS> \
  --name CustomScript \
  --publisher Microsoft.Azure.Extensions \
  --version 2.1 \
  --settings @settings.json

스크립트가 장시간 실행된다면, 확장 기능이 아니라 **이미지 bake(Packer/Azure Image Builder)**로 옮기는 것이 장기적으로 409를 크게 줄입니다.

5) 해결 전략 D: 특정 인스턴스가 “걸려서” 전체가 막히는 경우

어떤 인스턴스가 Failed/Updating에서 빠져나오지 못하면, 이후 업데이트가 연쇄적으로 409/실패를 만들 수 있습니다.

문제 인스턴스만 재이미징/재설치

# 특정 인스턴스 재이미징
az vmss reimage -g <RG> -n <VMSS> --instance-ids 3

# 또는 인스턴스 재시작
az vmss restart -g <RG> -n <VMSS> --instance-ids 3

최후의 수단: 인스턴스 교체

상태가 계속 꼬이면 해당 인스턴스를 삭제하고 재생성되게 하는 편이 더 빠를 때가 많습니다.

az vmss delete-instances -g <RG> -n <VMSS> --instance-ids 3

(운영 환경에서는 가용성/용량을 고려해 batch 크기와 순서를 조정하세요.)

6) IaC(ARM/Bicep/Terraform)에서 409을 줄이는 설계 팁

(1) 모델 업데이트와 인스턴스 업그레이드를 분리

  • Bicep/ARM 배포: VMSS 모델 정의
  • 별도 단계: update-instances 또는 rolling upgrade 트리거

이렇게 하면 “배포는 성공했는데 인스턴스 적용이 진행 중이라 다음 배포가 409” 같은 상황을 줄일 수 있습니다.

(2) 변경 빈도가 높은 속성은 별도 리소스로 분리

태그/진단 설정/확장 기능 등 자주 바뀌는 것과, 이미지/네트워크처럼 무거운 변경을 분리하면 충돌 가능성이 감소합니다.

(3) 재시도는 ‘조건부’로

모든 실패를 재시도하면 더 큰 장애를 만들 수 있습니다. 다음처럼 409/429/5xx만 재시도하는 방식이 안전합니다.

call_update() {
  az vmss update -g <RG> -n <VMSS> --set tags.build=$BUILD_ID 2>err.log
}

for i in {1..8}; do
  if call_update; then
    exit 0
  fi
  if grep -qE "\b409\b|Conflict|Another operation" err.log; then
    sleep $((i*15))
    continue
  fi
  cat err.log
  exit 1

done

cat err.log
exit 1

7) 운영 체크리스트(재발 방지)

  • 배포 파이프라인에서 VMSS 관련 작업은 동시에 1개만 실행되도록 락을 걸었는가?
  • 모델 업데이트 후 latestModelApplied가 모두 true가 될 때까지 업그레이드 진행을 관찰하는가?
  • 확장 기능(Custom Script 등) 실행 시간을 줄이거나 이미지 bake로 옮겼는가?
  • 문제 인스턴스가 Updating/Failed에 오래 머물면 자동으로 격리/교체하는가?

참고로, 장애 상황에서 “겉으로는 정상인데 내부 상태 때문에 실패”를 파고드는 디버깅 습관은 다른 영역에서도 그대로 통합니다. 예를 들어 쿠버네티스에서 원인별로 상태를 쪼개어 보는 방식은 Kubernetes CrashLoopBackOff 원인별 로그·Probe·리소스 디버깅 같은 접근과 유사합니다.

결론

Azure VMSS 업데이트 도중의 409 Conflict는 대개 “Azure가 틀렸다”기보다 현재 VMSS가 다른 변경을 처리 중인데 또 변경을 밀어 넣어서 생기는 충돌입니다. 해결의 핵심은 (1) Activity Log/인스턴스 상태로 진행 중 작업을 확인하고, (2) 업데이트를 직렬화하며, (3) 모델 업데이트와 인스턴스 적용/확장 기능 변경을 분리하는 것입니다.

이 3가지만 지켜도 409의 대부분은 사라지고, 남는 케이스는 특정 인스턴스 stuck/extension 장기 실행 같은 ‘구체적 원인’으로 좁혀져 훨씬 빨리 처리할 수 있습니다.