API management
API 관리 솔루션을 찾고 싶어하게 만드는 문제는 무엇입니까? 여러분은 아마도 다음과 같은 과제를 가지고 있을 것입니다.
- 크기 조정, API(들)은 전 세계 여러 지역의 많은 클라이언트에서 사용되며 사용 가능하고 응답성이 있는지 확인해야 합니다.
- 보안, API가 안전하고 승인된 클라이언트만 액세스할 수 있는지 확인해야 합니다.
- 오류 관리, API에서 오류를 적절하게 처리할 수 있는지 확인해야 합니다.
- 모니터링, API를 모니터링하여 예상대로 수행되는지 확인해야 합니다.
- 복원력, API가 복원력이 있고 오류를 적절하게 처리할 수 있는지 확인해야 합니다.
이러한 각 과제에 대해 포인트 솔루션을 선택할 수 있지만 관리하기가 어려울 수 있습니다. 또한 API가 서로 다른 기술 스택에 빌드될 수 있습니다. 즉, 위의 과제에 대한 솔루션은 각 API에 대해 서로 다른 솔루션이 필요하다는 것을 의미할 수 있습니다. 이러한 모든 과제가 있는 경우 Azure API Management와 같은 중앙 집중식 API 관리 솔루션을 고려해야 합니다.
몇 가지 과제에 대해 자세히 알아보고 Azure API Management와 같은 중앙 집중식 API 관리 솔루션이 과제를 해결하는 데 어떻게 도움이 되는지 알아보겠습니다.
코드형 인프라, IaC
Azure Portal을 사용하여 Azure 리소스를 만들어도 괜찮지만 인프라가 증가함에 따라 관리하기가 더 어려워집니다. 직면하는 문제 중 하나는 인프라를 다른 환경에서 쉽게 복제할 수 없다는 것입니다.
인프라에 대한 모든 변경 내용을 추적하기도 어렵습니다. IaC(코드형 인프라)가 필요한 상황입니다. IaC는 코드를 사용하여 인프라를 관리하는 관행입니다. Azure에서 IaC를 적용하려면 몇 가지 옵션이 있으며, 그 중 하나는 Bicep입니다. Bicep은 Azure 리소스를 선언적으로 배포하기 위한 DSL(도메인 특정 언어)입니다. 클라우드 리소스를 관리하는 좋은 방법입니다. 다음은 Bicep이 어떤 모습인지에 대한 간단한 예입니다.
param location string = 'eastus'
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
name: 'mystorageaccount'
location: location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
}
앞의 예제에서는 Bicep을 사용하여 스토리지 계정을 정의했습니다. 스토리지 계정의 위치, 스토리지 계정의 종류 및 SKU(Stock Keeping Unit)를 정의했습니다. 위치는 Bicep 파일을 배포할 때 전달할 수 있는 매개 변수입니다. 제공된 파일을 배포하기 위해 다음과 같이 Azure CLI를 사용합니다.
az deployment group create --resource-group myResourceGroup --template-file main.bicep
이전 명령은 스토리지 계정을 리소스 그룹 myResourceGroup
에 배포하고 Bicep 파일 main.bicep
을(를) 사용하여 파일에 리소스를 만듭니다.
부하 분산 장치를 통한 부하 처리
API가 요청에 의해 과부하가 발생하는 경우 부하 분산 구조를 추가하는 것이 해결책입니다. 부하 분산 장치는 API의 여러 인스턴스에 부하를 분산하는 데 도움이 될 수 있습니다.
Azure API Management 서비스에서 부하 분산은 백 엔드라는 개념을 정의하여 구현됩니다. 이 아이디어는 API 엔드포인트에 해당하는 많은 백 엔드를 설정한 다음 이러한 백 엔드에 부하를 분산하는 부하 분산 장치를 만드는 것입니다. 아키텍처의 모습은 다음과 같습니다.
이전 아키텍처에서 발생하는 일은 다음과 같습니다.
- 클라이언트는 API Management 인스턴스에 요청을 보냅니다.
- 요청이 인증되고 권한이 부여됩니다.
- 그런 다음 요청이 부하 분산 장치로 전송됩니다.
- 부하 분산 장치는 백 엔드 중 하나에 요청을 배포합니다(선택한 Azure OpenAI API는 굵게 표시됨).
백 엔드는 요청을 처리하고 클라이언트에 응답을 다시 보냅니다.
부하 분산 장치 정의
Azure API Management에서 부하 분산 장치를 설정하려면 다음 부분을 수행해야 합니다.
- 백 엔드, 부하를 분산하려는 만큼의 백 엔드.
- 부하 분산 장치, 부하를 분산하려는 백 엔드가 포함된 부하 분산 장치입니다.
- 수신 호출을 부하 분산 장치로 전달하는 정책입니다.
백 엔드 만들기
Azure API Management에서 백 엔드를 만들려면 백 엔드 엔터티를 정의해야 합니다. Bicep에서 백 엔드를 정의하는 방법은 다음과 같습니다.
resource backend2 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
parent: apimService
name: 'backend2'
properties: {
url: '${openai2Endpoint}openai'
protocol: 'http'
circuitBreaker: {
rules: [
{
failureCondition: {
count: 3
errorReasons: [
'Server errors'
]
interval: 'P1D'
statusCodeRanges: [
{
min: 500
max: 599
}
]
}
name: 'myBreakerRule'
tripDuration: 'PT1H'
}
]
}
}
앞의 Bicep 코드에서 백 엔드는 API 엔드포인트 URL에 해당하도록 정의되어 있으며, 이름 backend2
에 주목하세요. 이 이름은 나중에 사용할 수 있습니다. 각 백 엔드에 대해 이전의 bicep 코드와 같이 인코딩을 해야 합니다.
참고 항목
백 엔드가 여러 개 있을 수 있으므로 원하는 만큼 백 엔드를 정의할 수 있습니다.
백 엔드 풀 만들기
다음으로 부하를 분산할 백 엔드를 설정하는 백 엔드 풀을 만들고자 합니다. 다음과 같이 이 백 엔드 풀을 백 엔드 엔터티로 인코딩할 수 있습니다.
resource loadBalancing 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
parent: apimService
name: 'LoadBalancer'
properties: {
description: 'Load balancer for multiple backends'
type: 'Pool'
pool: {
services: [
{
id: '/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ApiManagement/service/${apimService.name}/backends/${backend1.id}'
}
{
id: '/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ApiManagement/service/${apimService.name}/backends/${backend2.id}'
}
]
}
}
}
이전에 만든 백 엔드인 backend2
은(는) 다른 백 엔드 backend1
와 함께 참조됩니다(후자는 간결성을 위해 생략했습니다).
services
목록의 각 항목에 대한 priority
및 weight
속성을 포함하여 부하 분산 장치가 부하를 분산하는 방법을 결정할 수도 있습니다. 각 백 엔드의 우선 순위와 가중치를 설정하는 방법은 다음과 같습니다.
services: [
{
id: '/subscriptions/<subscriptionID>/resourceGroups/<resourceGroupName>/providers/Microsoft.ApiManagement/service/<APIManagementName>/backends/backend-1'
priority: 1
weight: 3
}
{
id: '/subscriptions/<subscriptionID>/resourceGroups/<resourceGroupName>/providers/Microsoft.ApiManagement/service/<APIManagementName>/backends/backend-2'
priority: 1
weight: 1
}
]
앞의 예제에서 부하 분산 장치는 부하를 backend-2
보다 backend-1
에 3배 이상 분산합니다.
직접 수신 통화
마지막으로 수신 통화를 이 부하 분산 백 엔드로 전달해야 합니다. 방향 명령은 다음 API 엔터티를 통해 생성됩니다.
resource api1 'Microsoft.ApiManagement/service/apis@2020-06-01-preview' = {
parent: apimService
name: apiName
properties: {
displayName: apiName
apiType: 'http'
path: apiSuffix
format: 'openapi+json-link'
value: 'https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/preview/2024-03-01-preview/inference.json'
subscriptionKeyParameterNames: {
header: 'api-key'
}
}
정책 구성
이제 마지막으로 앞에서 설명한 API에서 정책을 설정하고 수신 통화를 부하 분산 장치에 전달할 수 있습니다.
// policy.xml
<policies>
<inbound>
<base />
<set-backend-service id="apim-generated-policy" backend-id="{0}" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
var headerPolicyXml = format(loadTextContent('./policy.xml'), loadBalancing.name, 5000)
// Create a policy for the API, using the headerPolicyXml variable
resource apiPolicy 'Microsoft.ApiManagement/service/apis/policies@2020-06-01-preview' = {
parent: api1
name: 'policy'
properties: {
format: 'rawxml'
value: headerPolicyXml
}
}
수행한 작업은 수신 통화를 부하 분산 장치로 전달하는 정책을 만드는 것이었습니다. set-backend-service
정책은 수신 호출을 부하 분산 장치로 전달하는 데 사용됩니다. backend-id
속성은 이전에 만든 부하 분산 장치의 이름으로 설정됩니다.
이러한 모든 이동 부분이 제자리에 배치되면 이제 API Management 인스턴스의 부하가 분산됩니다. 이제 부하 분산 장치에 더 많은 백 엔드를 추가하여 API 크기를 조정할 수 있습니다.
회로 차단기
회로 차단기는 요청에 의해 API가 과부하되지 않도록 보호하려는 경우에 사용하는 것입니다. 작동 방식은 충족되는 경우 회로 차단기가 백 엔드에 대한 요청 전송을 트리거하고 중지하는 일련의 규칙을 사용자가 정의하는 것입니다. Azure API Management에서 백 엔드를 설정하고 회로 차단기 규칙을 정의하여 회로 차단기를 정의할 수 있습니다. 그 방법은 다음과 같습니다.
resource backend2 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
parent: apimService
name: 'backend2'
properties: {
url: '${openai2Endpoint}openai'
protocol: 'http'
circuitBreaker: {
rules: [
{
failureCondition: {
count: 3
errorReasons: [
'Server errors'
]
interval: 'P1D'
statusCodeRanges: [
{
min: 500
max: 599
}
]
}
name: 'myBreakerRule'
tripDuration: 'PT1H'
}
]
}
}
}
이전 백 엔드 정의에는 회로 차단기가 이동해야 하는 시점을 정의하는 속성 failureCondition
이(가) 있습니다. 이 경우 하루에 세 번의 서버 오류가 있는 경우 회로 차단기가 이동합니다. tripDuration
속성은 회로 차단기가 다시 닫히기 전에 열려 있어야 하는 기간을 정의합니다. API Management 인스턴스에 있는 각 백 엔드에 대해 회로 차단기를 정의하는 것이 좋습니다.
관리 ID
해결하고자 하는 또 다른 문제는 보안입니다. API가 안전하고 승인된 클라이언트만 액세스할 수 있는지 확인하고자 합니다. API를 보호하는 방법은 관리 ID를 사용하는 것입니다. 관리 ID는 다른 Azure 서비스에 대해 API를 인증하는 방법입니다. Azure API Management에서는 관리 ID를 다음과 같은 여러 위치에 적용해야 합니다.
APIM 인스턴스 수준, 다음과 같이
identity
속성을SystemAssigned
에 설정하여 APIM 인스턴스에서 관리 ID를 사용하도록 설정할 수 있습니다.resource apimService 'Microsoft.ApiManagement/service@2023-09-01-preview' = { name: name location: location tags: union(tags, { 'azd-service-name': name }) sku: { name: sku capacity: (sku == 'Consumption') ? 0 : ((sku == 'Developer') ? 1 : skuCount) } properties: { publisherEmail: publisherEmail publisherName: publisherName // Custom properties are not supported for Consumption SKU } identity: { type: 'SystemAssigned' } }
이 작업을 수행하면 나중에 APIM 인스턴스를 Azure OpenAI 인스턴스 등에 사용할 수 있는 APIM 인스턴스에 대한 관리 ID가 생성됩니다.
API 수준, API 인스턴스의 경우 정책과 연결할 수 있습니다. 해당 정책에서 관리 ID가 작동하도록 필요한 지침을 추가할 수 있습니다.
<policies> <inbound> <base /> <authentication-managed-identity resource="https://cognitiveservices.azure.com" output-token-variable-name="managed-id-access-token" ignore-error="false" /> <set-header name="Authorization" exists-action="override"> <value>@("Bearer " + (string)context.Variables["managed-id-access-token"])</value> </set-header> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>
authentication-managed-identity
및set-header
에 대한 이전 호출을 참조하세요. 이러한 지침은 관리 ID가 API에 적용되는지 확인합니다.백 엔드 수준, 마지막으로 백 엔드가 Azure OpenAI 인스턴스를 가리키도록 합니다. APIM 인스턴스를 Azure OpenAI 인스턴스와 연결해야 합니다. 이 연결을 위한 Bicep 지침은 다음과 같습니다.
resource role 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(subscription().id, resourceGroup().id, principalId, roleDefinitionId) properties: { principalId: principalId principalType: "ServicePrincipal" roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId) } }
위의 Bicep 명령을 사용하는 아이디어는 APIM 인스턴스와 Azure OpenAI 인스턴스 간에 역할 할당을 만드는 것입니다. 이 경우 다음과 같습니다.
principalId
은(는) APIM 인스턴스의 ID ID입니다.roleDefinitionId
은(는) 특정 사용자입니다. 이 경우 Azure OpenAI 인스턴스에 대한 액세스 권한이 있는 사용자인 "Cognitive Services User"라고 하는 사용자입니다.name
, 이 속성은 역할 할당이 올바른 범위에 적용되도록 합니다. 이 경우 특정 구독 및 리소스 그룹입니다. (Azure OpenAI 인스턴스와 동일한 리소스 그룹이어야 합니다.)