배포
JamJet을 프로덕션에 배포하세요 — PostgreSQL을 사용한 자체 호스팅 또는 호스팅 서비스로 제공됩니다.
배포
JamJet은 로컬에서는 SQLite를, 프로덕션에서는 PostgreSQL을 사용합니다. 동일한 워크플로우 코드가 두 환경 모두에서 변경 없이 실행됩니다.
구성
프로덕션 설정은 jamjet.toml에 있습니다:
[runtime]
port = 7700
workers = 8 # concurrent worker threads
[database]
url = "postgresql://user:password@db:5432/jamjet"
pool_size = 10
max_overflow = 20
[telemetry]
enabled = true
service_name = "my-agent"
[telemetry.otlp]
endpoint = "http://otel-collector:4317"
[auth]
enabled = true
method = "api_key" # api_key | mtls | jwt모든 값은 환경 변수로 재정의할 수 있습니다:
JAMJET_DATABASE_URL=postgresql://...
JAMJET_RUNTIME_PORT=7700
JAMJET_RUNTIME_WORKERS=16
JAMJET_AUTH_API_KEY=sk-...Docker
FROM python:3.11-slim
RUN pip install jamjet
COPY jamjet.toml .
COPY workflow.yaml .
EXPOSE 7700
CMD ["jamjet", "serve"]docker build -t my-agent .
docker run -p 7700:7700 \
-e JAMJET_DATABASE_URL=postgresql://... \
-e ANTHROPIC_API_KEY=YOUR_ANTHROPIC_API_KEY \
my-agentDocker Compose (전체 스택)
version: "3.9"
services:
runtime:
image: my-agent
ports:
- "7700:7700"
environment:
JAMJET_DATABASE_URL: postgresql://jamjet:secret@db:5432/jamjet
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: jamjet
POSTGRES_PASSWORD: secret
POSTGRES_DB: jamjet
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U jamjet"]
interval: 5s
timeout: 5s
retries: 5
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
volumes:
- ./otel-config.yaml:/etc/otel/config.yaml
command: ["--config=/etc/otel/config.yaml"]
volumes:
pg_data:Kubernetes
-
자격 증명을 위한 Secret 생성:
kubectl create secret generic jamjet-secrets \ --from-literal=database-url="postgresql://..." \ --from-literal=anthropic-api-key="YOUR_ANTHROPIC_API_KEY" -
런타임 배포:
apiVersion: apps/v1 kind: Deployment metadata: name: jamjet-runtime spec: replicas: 3 selector: matchLabels: app: jamjet-runtime template: metadata: labels: app: jamjet-runtime spec: containers: - name: runtime image: my-agent:latest ports: - containerPort: 7700 env: - name: JAMJET_DATABASE_URL valueFrom: secretKeyRef: name: jamjet-secrets key: database-url - name: ANTHROPIC_API_KEY valueFrom: secretKeyRef: name: jamjet-secrets key: anthropic-api-key resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "1Gi" cpu: "2" -
Service로 노출:
apiVersion: v1 kind: Service metadata: name: jamjet-runtime spec: selector: app: jamjet-runtime ports: - port: 80 targetPort: 7700 type: ClusterIP
데이터베이스 마이그레이션
런타임 시작 전 마이그레이션 실행:
jamjet db migrate또는 시작 시 자동 실행 (간단한 배포용):
[database]
auto_migrate = true워커 스케일링
JamJet 런타임은 수평 확장 가능 — 동일한 PostgreSQL 데이터베이스에 대해 여러 인스턴스를 실행:
# 인스턴스 1
jamjet serve --port 7700
# 인스턴스 2 (동일한 DB, 다른 포트)
jamjet serve --port 7701분산 스케줄러는 데이터베이스 수준의 락을 사용하여 노드의 중복 실행을 방지하므로, 메시지 브로커 없이도 여러 인스턴스가 안전하게 조정됩니다.
note: 높은 처리량(수천 개의 동시 실행)이 필요한 경우, 전용 메시지 큐(NATS 또는 Kafka)가 데이터베이스 기반 큐를 대체할 수 있습니다. 이는 v2에서 구성 옵션으로 제공됩니다.
헬스 체크
# Liveness
curl http://localhost:7700/health
# Readiness (DB 연결 확인)
curl http://localhost:7700/ready{ "status": "ok", "version": "0.1.0", "db": "connected" }보안 체크리스트
JAMJET_AUTH_API_KEY를 설정하고 모든 API 호출에 필수로 요구- 로드 밸런서에서 TLS 종료 사용 (또는 mTLS 직접 구성)
- API 키 정기적으로 교체
- PostgreSQL 사용자를
jamjet데이터베이스로만 제한 - PII가 포함된 경우 프로덕션에서 전체 상태를 로그에 남기지 않음 —
logging.redact_state = true사용 - 가능한 경우 모델 API 키를 최소 권한 범위로 제한
환경 변수 참조
| 변수 | 기본값 | 설명 |
|---|---|---|
JAMJET_DATABASE_URL | .jamjet/dev.db (SQLite) | 데이터베이스 연결 문자열 |
JAMJET_RUNTIME_PORT | 7700 | HTTP 포트 |
JAMJET_RUNTIME_WORKERS | 4 | 워커 스레드 개수 |
JAMJET_AUTH_API_KEY | (없음) | 인증용 API 키 |
JAMJET_LOG_LEVEL | info | 로그 레벨 |
JAMJET_LOG_FORMAT | json | 로그 형식 |
ANTHROPIC_API_KEY | (없음) | Claude 모델용 |
OPENAI_API_KEY | (없음) | GPT 모델용 |