본문 바로가기

Technical architecture/Kubernetes

Kubernetes로 대용량 오픈소스 웹 상용화하기 ③: Helm chart로 Kubernetes에 오픈 소스 웹 배포하기

Kubernetes로 대용량 오픈소스 웹 상용화하기 시리즈 목차

  1. 대용량 트래픽을 고려한 오픈소스 선정 및 분석
  2. 컨테이너화와 Kubernetes 리소스 관리 (Pod, Deployment, StatefulSet)
  3. Helm chart로 Kubernetes에 오픈 소스 웹 배포하기
  4. Kubernetes 서비스(Service) 및 Ingress 관리 (HTTP 및 gRPC 프로토콜 이해)
  5. 보안 강화를 위한 인증서(Certificate) 관리
  6. 서비스 안정성을 위한 튜닝(성능테스트, HA 구성, 리소스 최적화)

이전 글: [Technical architecture/Kubernetes] - Kubernetes로 오픈소스 상용화하기 ②: 컨테이너화와 Kubernetes 리소스 관리

 

Kubernetes로 오픈소스 상용화하기 ②: 컨테이너화와 Kubernetes 리소스 관리

Kubernetes로 대용량 오픈소스 웹 상용화하기 시리즈 목차대용량 트래픽을 고려한 오픈소스 선정 및 분석컨테이너화와 Kubernetes 리소스 관리 (Pod, Deployment, StatefulSet)Helm chart로 Kubernetes에 오픈 소스

develiro.tistory.com

이전 글에서는 오픈소스 웹 배포 선정 과정과 배포 리소스를 어떻게 구성하고 관리하는지를 중심으로 다뤘습니다. 이번 글에서는 Helm Chart를 활용해 오픈소스 웹 애플리케이션(Langfuse)을 실제로 배포하고, 실전 운영 중 마주했던 주요 이슈와 그 해결 경험을 공유해보려고 합니다.

 

왜 Helm Chart로 배포할까?

Helm은 Kubernetes의 패키지 매니저로, 복잡한 리소스 구성을 템플릿화하고 재사용 가능한 배포 단위로 관리할 수 있게 해줍니다. 특히 다음과 같은 장점이 있습니다:

  • 반복 가능한 배포
  • 환경별 설정 분리
  • 업그레이드 및 롤백의 용이함
  • 커뮤니티 차트 활용 가능

Langfuse는 공식 Helm Chart를 제공하고 있으며, https://langfuse.com/self-hosting/kubernetes-helm

이를 기반으로 운영 환경에 맞춰 아래 구성으로 커스터마이징했습니다.

+------------------+         +-------------------+
|    Ingress       +-------->    langfuse-web     |
+------------------+         +--------+----------+
                                      |
                         +------------v-------------+
                         |    langfuse-worker       |
                         +------------+-------------+
                                      |
                  +-------------------v---------------------+
                  |                 Redis                   |
                  +-------------------+---------------------+
                                      |
                  +-------------------v---------------------+
                  |     PostgreSQL (Azure Flexible Server)  |
                  +-------------------+---------------------+
                                      |
                  +-------------------v---------------------+
                  |     ClickHouse (Logging, Tracing)       |
                  +-------------------+---------------------+
                                      |
                  +-------------------v---------------------+
                  |     Azure Storage Account (Logs, Files) |
                  +-----------------------------------------+

 

핵심 구성 요소 설정

1. PostgreSQL: Azure Flexible Server 사용

postgresql:
  enabled: false

env:
  - name: DIRECT_URL
    value: postgresql://<user>:<password>@<db_host>.postgres.database.azure.com:5432/<db_name>
  - name: DATABASE_URL
    value: postgresql://<user>:<password>@<db_host>.postgres.database.azure.com:5432/<db_name>
  - name: SHADOW_DATABASE_URL
    value: postgresql://<user>:<password>@<db_host>.postgres.database.azure.com:5432/<db_name>

2. Object Storage: Azure Storage Account 연동

Azure Blob Storage를 사용하고, 시크릿 리소스를 생성해 키값을 보호해주었습니다. 물론 postgreSQL도 url에 user/password가 포함되어 있는 상태이기 때문에 추후에 시크릿으로 변경해야 합니다.

env:
  - name: LANGFUSE_USE_AZURE_BLOB
    value: 'true'
  - name: LANGFUSE_S3_EVENT_UPLOAD_ENABLED
    value: 'true'
  - name: LANGFUSE_S3_EVENT_UPLOAD_BUCKET
    value: 'langfusetest'
  - name: LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID
    valueFrom:
      secretKeyRef:
        name: storage-account-secret
        key: accessKeyId
  - name: LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY
    valueFrom:
      secretKeyRef:
        name: storage-account-secret
        key: secretAccessKey
  - name: LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT
    valueFrom:
      secretKeyRef:
        name: storage-account-secret
        key: endpoint

3. AKS에 Redis 설치 (Helm 기준, Bitnami 차트)

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# 3. Redis 설치
helm install langfuse-redis bitnami/redis \
  --namespace redis \
  --set auth.password=<your-password>

+ Redis는 직접 설치해야했기 때문에 기존 Langfuse 차트의 통신 부분을 변경해야하는 부분이 있었습니다.

 

4. ClickHouse: 로그 및 트레이싱 저장소로 사용

Langfuse는 내부 메트릭, 로그, 트레이싱 정보를 저장하는 데 ClickHouse를 사용합니다. 기본적으로 차트 내 clickhouse.enabled: true 설정으로 사용 가능하며, 별도의 클러스터로 분리해서 운영할 수도 있습니다.

Clickhouse는 설치가 간단했지만 실사용 시 메모리 부족에러가 많이 나게 됩니다.

처음부터 최소 8Gi 이상으로 잡아야할 것 같습니다.

대용량 트래픽을 고려한다면 리소스를 제일 많이 먹는 주범이 아닐까 생각됩니다.

clickhouse:
  deploy: true
  shards: 1 # Fixed. Langfuse does not support multi-shard clusters.
  replicaCount: 3
  # resourcesPreset: large
  resources:
    requests:
      cpu: '2'
      memory: '8Gi'
    limits:
      cpu: '3'
      memory: '12Gi'

5. 인증: Entra ID 연동

Langfuse의 인증 수단으로 Microsoft Entra ID를 연동했습니다.

Client Id 추가 작업을 해줘야 합니다.

langfuse:
  port: 3000
  nodeEnv: production
  next:
    healthcheckBasePath: ''
  nextauth:
    url: https://test.langfuse.com
    secret: changeme
    azureAd:
      clientId: ''
      clientSecret: ''
      tenantId: ''

실전 배포 중 마주한 이슈들

1. 통신 오류 디버깅을 위한 디버깅 Pod 활용

어쩔 수 없이 리소스 하나를 배포할 때마다 네트워크 통신을 확인해야 합니다.

그래서 langfuse-web, PostgreSQL, ClickHouse, Storage account 등등.. 연결 문제 발생 시 아래처럼 디버깅 전용 Pod를 띄워 curl, nc 등을 활용해 통신 여부를 점검했습니다.

kubectl run debug --rm -it --image=busybox -- /bin/sh
# apk add curl netcat-openbsd
curl -v langfuse-web:3000
nc -zv <postgres-host> 5432
nc -zv <clickhouse-host> 9000

2. Storage 접근 오류

SAS 토큰 만료, 엔드포인트 오타, 권한 부족 등으로 인해 Azure Storage 연동이 실패하는 사례가 있었습니다. 공식 문서 외에도 GitHub 이슈에서 유사 사례를 참고해 문제를 해결했습니다:


다음 글 예고

사실 배포만 해서는 통신만 되고 기능만 되는 POC일 뿐이지요. 아직 실 접속을 위한 Ingress 설정과 보안 강화를 위한 인증서 작업, 성능 테스트 및 리소스 최적화가 남아있습니다. 😂 다음 글에서는 외부 접속을 위한 Ingress 설정 방법을 공유해보겠습니다.