Durable Functions의 신뢰할 수 있는 실행 모델에서는 오케스트레이션이 결정적이어야 한다는 점 때문에 업데이트를 배포할 때 어려움이 발생합니다. 수정된 작업 함수 서명 또는 변경된 오케스트레이터 논리 등의 호환성이 손상되는 변경이 배포에 포함된 경우, 진행 중이던 오케스트레이션 인스턴스가 실패합니다. 이 상황은 특히 장기 실행 오케스트레이션의 문제이며, 이는 작업 시간 또는 일 수를 나타낼 수 있습니다.
메모
이 문서의 전략은 Durable Functions 기본 Azure Storage 공급자를 사용 중이라고 가정합니다. 다른 스토리지 공급자를 사용하는 경우 지침이 적용되지 않을 수 있습니다. 오케스트레이션 버전 관리 전략은 예외이며 모든 스토리지 백 엔드에서 작동합니다. 스토리지 공급자 옵션에 대한 자세한 내용은 Durable Functions 스토리지 공급자 참조하세요.
다음 표에서는 제로 가동 중지 시간 배포를 달성하기 위한 네 가지 전략을 비교합니다. 워크로드와 가장 일치하는 전략을 선택합니다.
| 전략 | 사용 시기 | 장점 | Cons |
|---|---|---|---|
| 오케스트레이션 버전 관리 (권장) | 여러 오케스트레이션 버전이 동시에 실행이 필요한 주요 변경이 있는 애플리케이션 | 호환성이 손상되는 변경이 적용된 가동 중지 시간이 없는 배포를 사용하도록 설정합니다. 최소한의 구성이 필요한 기본 제공 기능입니다. 모든 스토리지 백 엔드에서 작동합니다. |
버전 호환성을 위해 신중하게 오케스트레이터 코드를 수정해야 합니다. |
| 이름 기반 버전 관리 | 간결성이 선호되는 드물게 호환성이 손상되는 변경이 있는 애플리케이션. | 구현이 간편합니다. | 메모리의 함수 앱 크기와 함수 개수가 증가합니다. 코드가 중복됩니다. |
| 슬롯으로 상태 검사 | 수명이 짧은 오케스트레이션(24시간 미만) 및 실행 간의 예측 가능한 간격이 있는 시스템입니다. | 코드 베이스가 간단합니다. 추가적인 함수 앱 관리가 필요하지 않습니다. |
추가 스토리지 계정 또는 작업 허브 관리가 필요합니다. 오케스트레이션이 실행되지 않는 기간이 필요합니다. |
| 애플리케이션 라우팅 | 지속적으로 오케스트레이션을 실행하거나(24시간 이상) 유휴 기간 없이 자주 겹치는 실행이 있는 시스템입니다. | 호환성이 손상되는 변경 사항이 있는 오케스트레이션을 지속적으로 실행하는 새 버전의 시스템을 처리합니다. | 지능형 애플리케이션 라우터가 필요합니다. 구독에서 허용하는 함수 앱 수를 최대로 초과할 수 있습니다(기본값은 100). |
오케스트레이션 버전 관리
오케스트레이션 버전 관리 기능은 제로 다운타임 배포에서 호환성을 깨뜨리는 변경에 대한 권장 전략입니다. 이를 통해 서로 다른 버전의 오케스트레이션이 충돌 없이 공존하고 동시에 실행할 수 있습니다.
오케스트레이션 버전 관리:
- 각 오케스트레이션 인스턴스는 생성될 때 영구적으로 설정된 버전을 갖게 됩니다.
- 최신 오케스트레이터 버전을 실행하는 작업자는 이전 버전 인스턴스를 계속 실행할 수 있습니다.
- 이전 오케스트레이션 버전을 실행하는 작업자는 최신 버전 인스턴스를 실행할 수 없습니다 .
- 오케스트레이터 함수는 그에 따라 해당 버전 및 분기 실행을 검사할 수 있습니다.
이 접근 방식은 다양한 버전의 애플리케이션을 실행하는 작업자가 안전하게 공존할 수 있는 롤링 업그레이드를 용이하게 합니다. 이 문서의 다른 전략과 달리 오케스트레이션 버전 관리는 백 엔드에 구애받지 않으며 스토리지 공급자와 함께 작동합니다.
버전 관리를 구성하고, 오케스트레이터 코드에서 버전 분기를 처리하고, 롤링 업그레이드를 관리하는 방법을 비롯한 전체 구현 단계는 오케스트레이션 버전 관리를 참조하세요.
나머지 전략은 오케스트레이션 버전 관리가 적합하지 않은 시나리오의 대안입니다.
이름 기반 버전 관리
이 전략을 사용하면 동일한 함수 앱에서 이전 버전과 함께 함수의 새 버전을 만듭니다. 각 함수의 버전은 해당 이름의 일부가 됩니다(예: MyOrchestrator_v1, MyOrchestrator_v2). 이전 버전은 유지되므로 진행 중인 오케스트레이션 인스턴스는 계속 참조할 수 있습니다. 새 오케스트레이션 인스턴스에 대한 요청은 오케스트레이션 클라이언트 함수가 앱 설정에서 참조할 수 있는 최신 버전을 호출합니다. 다음 다이어그램에서는 이 방법을 보여 줍니다.
이 전략에서는 모든 함수를 복사하고 다른 함수에 대한 참조를 업데이트해야 합니다. 스크립트를 작성하면 이 작업을 더 쉽게 수행할 수 있습니다. 마이그레이션 스크립트를 사용하는 샘플 프로젝트는 다음과 같습니다.
메모
이 전략은 배포 중 가동 중지 시간을 방지하기 위해 배포 슬롯을 사용합니다. 새 배포 슬롯을 만들고 사용하는 방법에 대한 자세한 내용은 Azure Functions 배포 슬롯 참조하세요.
슬롯으로 상태 검사
프로덕션 슬롯에서 현재 버전의 함수 앱이 실행되는 동안 새 버전의 함수 앱을 스테이징 슬롯에 배포합니다. 프로덕션과 스테이징 슬롯을 교환하기 전에 실행 중인 오케스트레이션 인스턴스가 있는지 확인하세요. 모든 오케스트레이션 인스턴스를 완료한 후에 교환을 수행할 수 있습니다. 이 전략은 실행 중인 오케스트레이션 인스턴스가 없을 때 예측 가능한 기간이 있는 경우에 적합합니다. 오케스트레이션이 장기 실행되지 않고 오케스트레이션 실행이 자주 겹치지 않는 경우에 가장 효과적인 방식입니다.
함수 앱 구성
다음 절차에 따라 이 시나리오를 설정합니다.
스테이징 및 프로덕션을 위해 함수 앱에 배포 슬롯을 추가합니다.
각 슬롯에 대해 AzureWebJobsStorage 애플리케이션 설정을 공유 스토리지 계정의 연결로 설정합니다. 이 스토리지 계정 연결은 Azure Functions 런타임에서 함수의 액세스 키 안전하게 저장하는 데 사용됩니다. 최고 수준의 보안을 위해서는 스토리지 계정에 대해 관리 ID 연결을 사용해야 합니다.
각 슬롯에 대해 새 앱 설정(예:
DurableManagementStorage)을 만듭니다. 해당 값을 다양한 스토리지 계정의 연결 문자열으로 설정하세요. 이러한 스토리지 계정은 Durable Functions 확장에서 신뢰할 수 있는 실행 사용됩니다. 각 슬롯에 대해 별도의 스토리지 계정을 사용합니다. 해당 설정을 배포 슬롯 설정으로 표시하지 마세요. 다시 말하지만 관리 ID 기반 연결이 가장 안전합니다.함수 앱의 host.json 파일의 durableTask 섹션에서
connectionStringName(Durable 2.x) 또는azureStorageConnectionStringName(Durable 1.x)를 3단계에서 만든 앱 설정의 이름으로 지정합니다.
다음 다이어그램에서는 배포 슬롯과 스토리지 계정의 구성에 대한 설명을 보여줍니다. 이 잠재적 배포 전 시나리오에서, 함수 앱의 버전 2는 프로덕션 슬롯에서 실행되고 버전 1은 스테이징 슬롯에 남아 있습니다.
host.json 예제
다음 JSON 조각은 host.json 파일의 연결 문자열 설정을 보여줍니다.
{
"version": 2.0,
"extensions": {
"durableTask": {
"hubName": "MyTaskHub",
"storageProvider": {
"connectionStringName": "DurableManagementStorage"
}
}
}
}
메모
레거시 Functions 1.x 앱의 경우, storageProvider.connectionStringName 섹션 대신 durableTask 섹션에서 azureStorageConnectionStringName 속성을 직접 사용합니다.
CI/CD 파이프라인 구성
함수 앱에 보류 중이거나 실행 중인 오케스트레이션 인스턴스가 없는 경우에만 배포하도록 CI/CD 파이프라인을 구성합니다. Azure Pipelines 사용하는 경우 다음 C# 예제와 같이 이러한 조건을 확인하는 함수를 만들 수 있습니다. 동일한 패턴이 다른 언어에도 적용됩니다. Pending 또는 Running 상태를 가진 오케스트레이션 인스턴스를 쿼리하고, 존재 여부를 반환합니다.
[FunctionName("StatusCheck")]
public static async Task<IActionResult> StatusCheck(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient client,
ILogger log)
{
var runtimeStatus = new List<OrchestrationRuntimeStatus>();
runtimeStatus.Add(OrchestrationRuntimeStatus.Pending);
runtimeStatus.Add(OrchestrationRuntimeStatus.Running);
var result = await client.ListInstancesAsync(new OrchestrationStatusQueryCondition() { RuntimeStatus = runtimeStatus }, CancellationToken.None);
return (ActionResult)new OkObjectResult(new { HasRunning = result.DurableOrchestrationState.Any() });
}
다음으로, 오케스트레이션이 실행되지 않을 때까지 대기하도록 스테이징 게이트를 구성합니다. 자세한 내용은 게이트를 통한 릴리스 배포 제어를 참조하세요.
Azure Pipelines 배포가 시작되기 전에 함수 앱에서 오케스트레이션 인스턴스를 실행하는지 확인합니다.
이제 새 버전의 함수 앱을 스테이징 슬롯에 배포해야 합니다.
마지막으로 슬롯을 교환합니다.
배포 슬롯 설정으로 표시되지 않은 애플리케이션 설정도 교환되므로 버전 2 앱은 스토리지 계정 A에 대한 참조를 유지합니다. 오케스트레이션 상태는 스토리지 계정에서 추적되므로 버전 2 앱에서 실행되는 오케스트레이션은 중단 없이 새 슬롯에서 계속 실행됩니다.
두 슬롯에 동일한 스토리지 계정을 사용하려면 작업 허브의 이름을 변경하면 됩니다. 이 경우 슬롯의 상태와 앱의 HubName 설정을 관리해야 합니다. 자세한 내용은
애플리케이션 라우팅
이 전략은 가장 복잡하지만 슬롯 교환을 위한 유휴 창이 없는 오케스트레이션을 지속적으로 실행하는 시스템의 유일한 옵션입니다.
이 전략의 경우 Durable Functions 앞에 적용 라우터(예: HTTP 트리거가 있는 Azure 함수 또는 버전 헤더를 기반으로 라우팅되는 API Management 인스턴스)를 만듭니다. 라우터는 다음을 담당합니다.
- 함수 앱을 배포하기
- 활성 상태인 앱의 버전을 관리합니다.
- 버전에 따라 오케스트레이션 요청을 올바른 함수 앱으로 라우팅합니다.
오케스트레이션 요청이 처음 수신될 때 라우터는 다음 작업을 수행합니다.
- Azure 새 함수 앱을 만듭니다.
- Azure 새 함수 앱에 함수 앱의 코드를 배포합니다.
- 오케스트레이션 요청을 새 앱으로 전달합니다.
라우터는 앱 코드 버전이 Azure 함수 앱에 배포되는 상태를 관리합니다.
라우터는 요청과 함께 전송된 버전에 따라 적절한 함수 앱에 배포 및 오케스트레이션 요청을 보냅니다. 패치 버전은 무시합니다.
호환성이 손상되는 변경 없이 새 버전의 앱을 배포하는 경우 패치 버전을 높일 수 있습니다. 라우터가 기존 함수 앱에 배포하고 코드의 이전 버전 및 새 버전에 대한 요청을 보내면 동일한 함수 앱으로 라우팅됩니다.
호환성이 손상되는 변경으로 새 버전의 앱을 배포할 때 주 버전 또는 부 버전을 높일 수 있습니다. 그런 다음 애플리케이션 라우터는 Azure 새 함수 앱을 만들고, 배포하고, 새 버전의 앱에 대한 요청을 해당 앱으로 라우팅합니다. 다음 다이어그램에서는 1.0.1 버전의 앱에서 실행 중인 오케스트레이션은 계속 실행되지만 1.1.0 버전에 대한 요청은 새 함수 앱으로 라우팅됩니다.
라우터는 1.0.1 버전에서 오케스트레이션의 상태를 모니터링하고 모든 오케스트레이션이 완료되면 앱을 삭제합니다.
추적 저장 설정
각 함수 앱은 가급적 별도의 스토리지 계정으로 별도의 일정 큐를 사용해야 합니다. 모든 버전의 애플리케이션에서 모든 오케스트레이션 인스턴스를 쿼리하려면 함수 앱에서 인스턴스 및 기록 테이블을 공유할 수 있습니다. 테이블을 공유하려면 모두 동일한 값을 사용하도록 trackingStoreConnectionStringName 파일의 trackingStoreNamePrefix 및 설정을 구성하면 됩니다.
자세한 내용은