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

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

인프라가 준비되면, Terraform 출력값을 사용해 confident-ai Helm 차트를 설치해요. 차트는 Confident AI 레지스트리에서 이미지를 가져오고 앱과 클러스터 내부 ClickHouse를 설치해요. 앱이 EKS Pod Identity를 사용하므로 ServiceAccount에 어노테이션이 필요 없어요.

출처: 문서

본문

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

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

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

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

네임스페이스 생성

kubectl create namespace confident-ai

Secrets Manager에 시크릿 넣기

DATABASE_URL은 Terraform에서 바로 나와요. 이 JSON 객체의 각 키는 앱 시크릿이 돼요:

SECRET_NAME=$(terraform output -raw secrets_manager_secret_name)
REGION=$(terraform output -raw region)

aws secretsmanager put-secret-value --secret-id "$SECRET_NAME" --region "$REGION" \
  --secret-string "{
    \"DATABASE_URL\":\"$(terraform output -raw database_url)\",
    \"BETTER_AUTH_SECRET\":\"$(openssl rand -hex 32)\",
    \"OPENAI_API_KEY\":\"sk-...\",
    \"CONFIDENT_LICENSE_KEY\":\"...\"
  }"

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

External Secrets Operator 설치

confident-ai 네임스페이스에 external-secrets-sa 계정으로 설치해요. Terraform이 읽기 역할을 부여한 바로 그 계정이에요. ESO는 키 없이 Pod Identity를 통해 AWS 접근을 상속받죠:

helm repo add external-secrets https://charts.external-secrets.io && helm repo update
helm install external-secrets external-secrets/external-secrets \
  -n confident-ai \
  --set installCRDs=true \
  --set serviceAccount.name=external-secrets-sa

ALB 인그레스 설정 (HTTPS용)

도메인에서 HTTPS로 앱을 제공하려면 AWS Load Balancer Controller를 설치하고 (Ingress에서 ALB 프로비저닝), 리전에서 yourdomain.com의 네 개 서브도메인 app., api., evals., otel.을 커버하는 ACM 인증서를 요청해요 (와일드카드 *.yourdomain.com도 동작해요). 아래 values 파일에서 인증서 ARN을 참조하게 됩니다.

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

values 파일 작성

values.aws.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: AWS
  frontendUrl: https://app.yourdomain.com
  backendUrl: https://api.yourdomain.com
  subdomain: yourdomain.com

serviceAccount:
  create: true          # Pod Identity is already wired to this SA, no annotation needed

storage:
  testCasesBucket: <test_cases_bucket>
  payloadsBucket: <payloads_bucket>
  aws:
    region: <region>

# Recommended: app secrets come from AWS Secrets Manager via ESO.
secrets:
  externalSecrets:
    enabled: true
    provider: aws
    createStore: true
    remoteKey: <secrets_manager_secret_name>
    aws:
      region: <region>

clickhouse:
  internal: true
  password: "<choose-a-password>"
  storageClass: gp3
  keeper:
    storageClass: gp3

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

# Required for code-based and transformer metrics (Lambda sandbox from Terraform).
codeExecutor:
  provider: AWS_LAMBDA
  aws:
    lambdaFunctionName: <code_executor_function_name>
    lambdaRegion: <region>

ingress:
  enabled: true
  className: alb
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/group.name: confident
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    alb.ingress.kubernetes.io/certificate-arn: <your-acm-cert-arn>
  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.aws.yaml

kubectl get pods -n confident-ai -w

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

검증

kubectl get externalsecret -n confident-ai   # STATUS should be SecretSynced
kubectl get ingress -n confident-ai          # ADDRESS is the ALB hostname

app., api., evals., otel. DNS 레코드(CNAME 또는 Route 53 별칭)를 ALB 호스트네임을 가리키도록 만들고, https://app.yourdomain.com을 열어 로그인하세요.

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

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

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

redis:
  internal: true
  storageClass: gp3

ClickHouse 백업 (권장)

프로덕션에서는 매일 밤 ClickHouse를 S3로 백업하세요. 백업 버킷을 프로비저닝하고 (confident_clickhouse_backup_bucket_enabled = true), 백업 파드가 Pod Identity로 쓰므로 serviceAccountName을 그 버킷에 쓸 수 있는 역할을 가진 서비스 계정으로 설정해요. 자세한 내용은 Disaster Recovery 페이지에 있어요. 기존 clickhouse: 블록 아래에 추가하고 helm upgrade로 적용하세요:

clickhouse:
  backup:
    enabled: true
    provider: s3
    schedule: "0 2 * * *"          # nightly at 02:00 UTC
    serviceAccountName: confident
    s3:
      bucket: <clickhouse_backup_bucket>
      region: <region>

문제 해결(Troubleshooting)

증상 원인과 조치
externalsecret가 SecretSynced에 도달하지 못함 ESO가 confident-ai 네임스페이스에서 external-secrets-sa로 실행되어야 Pod Identity 읽기 역할을 상속받아요. helm install 플래그와 confident_create_secrets_manager = true를 다시 확인하세요.
파드가 Pending에 갇히고, PVC가 바인딩되지 않음 EKS에는 기본 StorageClass가 없어요. 인프라 페이지에서 gp3 기본값을 만들고, values 파일이 ClickHouse에 storageClass: gp3를 설정했는지 확인하세요.
앱 이미지에서 ImagePullBackOff 이미지가 별도 ECR 계정에 있어 노드 IAM으로 가져올 수 없어요. imagePullSecretRefresh가 활성화됐고 Confident AI의 AWS 키가 올바른지 확인하세요.
Ingress가 ADDRESS를 얻지 못함 AWS Load Balancer Controller가 설치되지 않았거나 서브넷이 태그되지 않았어요. 공개 서브넷은 kubernetes.io/role/elb=1이 필요하며 네트워크 단계가 태그를 붙여줘요.
프론트엔드가 ENOTFOUND confident-backend로 500을 반환 프론트엔드가 차트 접두사(prefix) 이름으로 백엔드 서비스를 확인해요. fullnameOverride: confident(차트 기본값)를 유지하세요. 바꾸지 마세요.
앱에서 S3 접근 거부 Pod Identity가 연결되지 않았어요. serviceAccount.create: true를 기본 이름으로 유지해 Terraform이 만든 연결과 일치시키세요.
ClickHouse Keeper가 Not authenticated 로그 이전 실패한 설치의 오래된 PersistentVolumeClaim이에요. helm uninstall, kubectl delete pvc -n confident-ai --all, 그 다음 재설치하세요.
kubectl port-forward 중 broken pipe 오류 무해한 연결 재설정이에요. port-forward를 다시 실행하세요.

업데이트와 제거

  • 앱 변경: values.aws.yaml를 편집한 뒤 helm upgrade confident-ai oci://ghcr.io/confident-ai/charts/confident-ai --version 0.2.0 -n confident-ai -f values.aws.yaml.
  • 시크릿 회전: aws secretsmanager put-secret-value를 다시 실행하세요. ESO가 다시 동기화하고, 파드를 재시작해 변경사항을 반영해요(시크릿을 환경 변수로 보유하다가 재시작할 때까지): kubectl rollout restart deployment -n confident-ai.
  • 인프라 변경: Terraform 설정을 편집하고 terraform apply.
  • 모두 제거: helm uninstall confident-ai -n confident-ai, 그 다음 terraform destroy, Terraform이 소유하지 않았다면 Infrastructure 페이지에서 네트워크를 삭제하세요.

더 알아보기