Azure에서 Helm으로 배포(Deploy on Azure with Helm)

Azure에서 Helm으로 배포(Deploy on Azure with Helm)

인프라가 준비되면, Terraform 출력값을 사용해 confident-ai Helm 차트를 설치해요. 차트는 Confident AI 레지스트리에서 이미지를 가져오고 앱과 클러스터 내부 ClickHouse를 설치해요. Azure에서는 config.isAzureEnvironment: true로 설정하고 Blob 스토리지에는 연결 문자열로 접근해요.

출처: 문서

본문

권장 설정은 앱 시크릿을 Azure Key Vault에 두고 (External Secrets Operator가 동기화) Redis를 Azure Managed Redis에서 실행하는 거예요. 둘 다 Terraform 모듈이 프로비저닝해요. 클러스터 내부 Redis와 Kubernetes Secret은 더 간단한 대안으로 지원되며, 더 간단한 옵션을 참고하세요.

Enterprise 라이선스와 함께 Confident AI에서 두 가지를 받아요:

  • 이미지 풀 자격 증명: 클러스터가 퍼스트파티 이미지를 가져올 수 있게 하는 AWS access key ID와 시크릿. 차트가 이 자격 증명으로 풀 시크릿을 자동으로 만들고 갱신해요.
  • 라이선스 키 (CONFIDENT_LICENSE_KEY): 플랜의 기능을 활성화하는 서명된 키.

OPENAI_API_KEY에 대해: Confident AI의 내장 평가 제공자가 OpenAI에서 실행되는데, 이를 뒷받침해요. 선택 사항이에요. 생략하면 자체 모델 제공자를 연결하거나, 앱의 AI Connections에서 프로젝트별 LLM 게이트웨이를 연결하면 돼요.

네임스페이스 생성

kubectl create namespace confident-ai

Key Vault에 시크릿 넣기

각 값을 Key Vault 시크릿으로 저장해요. Key Vault 이름은 _를 포함할 수 없으므로 -를 사용하고, 차트가 들어갈 때 -를 _로 되돌려 써요 (예: DATABASE-URL → DATABASE_URL). 스토리지 연결 문자열도 여기에 포함해요. Key Vault가 전체 시크릿 세트를 소유하기 때문이에요:

KV_URI=$(terraform output -raw key_vault_uri)
KV_NAME=$(echo "$KV_URI" | sed -E 's#https://([^.]+).*#\1#')

az keyvault secret set --vault-name "$KV_NAME" --name DATABASE-URL                     --value "$(terraform output -raw database_url)"
az keyvault secret set --vault-name "$KV_NAME" --name AZURE-STORAGE-CONNECTION-STRING  --value "$(terraform output -raw storage_connection_string)"
az keyvault secret set --vault-name "$KV_NAME" --name BETTER-AUTH-SECRET               --value "$(openssl rand -hex 32)"
az keyvault secret set --vault-name "$KV_NAME" --name OPENAI-API-KEY                   --value "sk-..."
az keyvault secret set --vault-name "$KV_NAME" --name CONFIDENT-LICENSE-KEY            --value "..."

이것은 confident_create_key_vault = true로 Terraform이 만든 볼트를 사용해요. 활성화하지 않았다면 켜고 다시 적용하거나, 더 간단한 옵션을 쓰세요.

페더레이션 자격 증명으로 ESO의 아이덴티티 연결

Terraform이 ESO용 관리 아이덴티티를 만들지만, external-secrets-sa Kubernetes 계정으로 동작하게 하는 페더레이션 자격 증명은 만들지 않아요. AKS는 이미 Workload Identity를 활성화하므로, 연결만 추가하면 돼요.

클러스터의 OIDC 발급자와 Terraform이 만든 ESO 아이덴티티를 확인해요:

RESOURCE_GROUP=confident-prod-rg
CLUSTER_NAME=$(terraform output -raw cluster_name)
OIDC_ISSUER_URL=$(az aks show -g $RESOURCE_GROUP -n $CLUSTER_NAME --query oidcIssuerProfile.issuerUrl -o tsv)
ESO_IDENTITY_NAME=$(az identity list -g $RESOURCE_GROUP --query "[?ends_with(name,'eso-identity')].name | [0]" -o tsv)
ESO_CLIENT_ID=$(az identity show -g $RESOURCE_GROUP -n "$ESO_IDENTITY_NAME" --query clientId -o tsv)

아이덴티티를 서비스 계정에 바인딩하는 페더레이션 자격 증명을 만들어요:

az identity federated-credential create --name eso-confident \
  --identity-name "$ESO_IDENTITY_NAME" --resource-group "$RESOURCE_GROUP" \
  --issuer "$OIDC_ISSUER_URL" \
  --subject system:serviceaccount:confident-ai:external-secrets-sa \
  --audience api://AzureADTokenExchange

External Secrets Operator 설치

helm repo add external-secrets https://charts.external-secrets.io && helm repo update
helm install external-secrets external-secrets/external-secrets \
  -n external-secrets --create-namespace --set installCRDs=true

kubectl create serviceaccount external-secrets-sa -n confident-ai
kubectl annotate serviceaccount external-secrets-sa -n confident-ai \
  azure.workload.identity/client-id=$ESO_CLIENT_ID

인그레스 설정 (HTTPS용)

관리형 NGINX 인그레스 컨트롤러를 실행하는 AKS 애플리케이션 라우팅 애드온을 켜요:

az aks approuting enable --resource-group confident-prod-rg --name <cluster_name>

아래 values 파일은 className: webapprouting.kubernetes.io를 사용하고 네 개의 서브도메인(app., api., evals., otel.)을 모두 노출해요. 네 개를 모두 커버하는 Kubernetes 시크릿이나 cert-manager로 TLS를 추가해요.

그냥 시험해 보는 중이라면 values 파일에서 ingress.enabled: false로 두고 kubectl port-forward -n confident-ai svc/confident-frontend 3000:3000로 앱에 접근하세요.

values 파일 작성

values.azure.yaml로 저장해요. 대괄호 값들은 Terraform 출력값과 Confident AI가 준 자격 증명으로 채우세요.

# The chart mints and refreshes the ECR pull secret from these credentials.
imagePullSecrets:
  - name: ecr-registry-credentials
imagePullSecretRefresh:
  enabled: true
  region: us-east-1
  awsAccessKeyId: "<from Confident AI>"
  awsSecretAccessKey: "<from Confident AI>"

config:
  cloudProvider: AZURE
  isAzureEnvironment: true
  frontendUrl: https://app.yourdomain.com
  backendUrl: https://api.yourdomain.com
  subdomain: yourdomain.com

serviceAccount:
  create: true

storage:
  testCasesBucket: <test_cases_container>
  payloadsBucket: <payloads_container>
  azure:
    storageAccountName: <storage_account_name>

# Recommended: all app secrets (including the storage connection string) come
# from Azure Key Vault via ESO.
secrets:
  externalSecrets:
    enabled: true
    provider: azurekv
    createStore: true
    serviceAccountRef:
      name: external-secrets-sa
    azure:
      vaultUrl: <key_vault_uri>
      tenantId: <your-tenant-id>

clickhouse:
  internal: true
  password: "<choose-a-password>"

# Recommended: managed Redis (Azure Managed Redis) from Terraform.
redis:
  internal: false
  externalUrl: <redis_url>

# Required for code-based and transformer metrics (Azure Function sandbox from Terraform).
codeExecutor:
  provider: AZURE_FUNCTIONS
  azure:
    functionUrl: <code_executor_function_url>/api/execute

ingress:
  enabled: true
  className: webapprouting.kubernetes.io
  hosts:
    evals: evals.yourdomain.com
    otel: otel.yourdomain.com

차트 설치

차트는 OCI 아티팩트로 GHCR에 게시돼요:

helm install confident-ai \
  oci://ghcr.io/confident-ai/charts/confident-ai \
  --version 0.2.0 \
  -n confident-ai \
  -f values.azure.yaml

kubectl get pods -n confident-ai -w

ClickHouse 오퍼레이터가 먼저 시작되고, 마이그레이션 작업이 실행된 다음 앱 파드가 올라와요. 몇 분 걸려요.

검증

kubectl get externalsecret -n confident-ai   # STATUS should be SecretSynced
kubectl get svc -n app-routing-system        # note the EXTERNAL-IP

그 IP에 app., api., evals., otel. DNS 레코드를 만들고, https://app.yourdomain.com을 열어 로그인하세요.

더 간단한 옵션: 클러스터 내부 Redis와 Kubernetes Secret

Key Vault나 관리형 Redis를 운영하고 싶지 않다면, 차트가 Kubernetes Secret에 시크릿을 담고 Redis를 클러스터 안에서 실행할 수 있어요. 프로덕션 하드닝은 덜 되지만(시크릿이 클러스터 안에 있고 Redis에 관리형 백업이 없음), Key Vault, 페더레이션 자격 증명, ESO 단계를 없애요. 위의 2~4단계는 건너뛰고 values 파일의 secrets와 redis 블록을 이렇게 바꿔 주세요:

secrets:
  data:
    DATABASE_URL: "<database_url>"
    AZURE_STORAGE_CONNECTION_STRING: "<storage_connection_string>"
    BETTER_AUTH_SECRET: "<openssl rand -hex 32>"
    OPENAI_API_KEY: "sk-..."
    CONFIDENT_LICENSE_KEY: "<your license key>"

redis:
  internal: true

코드 실행기 키

Azure Function 샌드박스는 함수 키로 보호돼요. Terraform이 Function을 만든 뒤 Azure 포털에서 읽을 수 있어요. 앱이 샌드박스를 호출할 수 있게 시크릿으로 추가해요:

  • Key Vault (권장): az keyvault secret set --vault-name "$KV_NAME" --name CODE-EXECUTOR-AZURE-FUNCTION-KEY --value "<function key>"
  • 더 간단한 옵션: secrets.data에 CODE_EXECUTOR_AZURE_FUNCTION_KEY: "<function key>" 추가.

ClickHouse 백업 (권장)

프로덕션에서는 매일 밤 ClickHouse를 Blob 스토리지로 백업해요. 스토리지 연결 문자열로 인증해요. 백업 컨테이너를 프로비저닝하고 자격 증명에 대한 자세한 내용은 Disaster Recovery 페이지를 참고하세요. 기존 clickhouse: 블록 아래에 추가하고 helm upgrade로 적용하세요:

clickhouse:
  backup:
    enabled: true
    provider: azure
    schedule: "0 2 * * *"          # nightly at 02:00 UTC
    azure:
      container: <clickhouse_backup_container>

문제 해결(Troubleshooting)

증상 원인과 조치
externalsecret가 SecretSynced에 도달하지 못함 페더레이션 자격 증명 subject는 정확히 system:serviceaccount:confident-ai:external-secrets-sa여야 하고, external-secrets-sa 어노테이션이 ESO 아이덴티티의 client ID를 담아야 해요. 둘 다 다시 확인하세요.
Key Vault 시크릿이 앱에 도달하지 못함 Key Vault 이름은 -를 사용하고 차트가 다시 _로 매핑해요. 시크릿을 DATABASE_URL이 아니라 DATABASE-URL로 이름 지으세요.
Blob 스토리지 접근 실패 config.isAzureEnvironment: true와 AZURE-STORAGE-CONNECTION-STRING이 Key Vault에 있는지(더 간단한 옵션에서는 secrets.data에) 확인하세요.
Ingress가 EXTERNAL-IP를 얻지 못함 애플리케이션 라우팅 애드온이 활성화되지 않았어요. az aks approuting enable을 실행하고 className: webapprouting.kubernetes.io를 유지하세요.
프론트엔드가 ENOTFOUND confident-backend로 500을 반환 프론트엔드가 차트 접두사 이름으로 백엔드 서비스를 확인해요. fullnameOverride: confident(차트 기본값)를 유지하세요. 바꾸지 마세요.
ClickHouse Keeper가 Not authenticated 로그 이전 실패한 설치의 오래된 PersistentVolumeClaim이에요. helm uninstall, kubectl delete pvc -n confident-ai --all, 그 다음 재설치하세요.
앱 이미지에서 ImagePullBackOff imagePullSecretRefresh가 활성화됐고 Confident AI의 AWS 키가 올바른지 확인하세요.

업데이트와 제거

  • 앱 변경: values.azure.yaml를 편집한 뒤 helm upgrade confident-ai oci://ghcr.io/confident-ai/charts/confident-ai --version 0.2.0 -n confident-ai -f values.azure.yaml.
  • 시크릿 회전: Key Vault에 새 버전을 작성하세요. ESO가 다시 동기화하고, 파드를 재시작해 변경사항을 반영해요(시크릿을 환경 변수로 보유하다가 재시작할 때까지): kubectl rollout restart deployment -n confident-ai.
  • 인프라 변경: Terraform 설정을 편집하고 terraform apply.
  • 모두 제거: helm uninstall confident-ai -n confident-ai, helm uninstall external-secrets -n external-secrets, 그 다음 terraform destroy, 1단계 리소스를 지우고 싶으면 az group delete --name confident-prod-rg --yes.

더 알아보기