From c7da54179badd665566329778f0b64f7f9a0d995 Mon Sep 17 00:00:00 2001 From: hiondal Date: Sun, 15 Jun 2025 14:15:05 +0000 Subject: [PATCH] release --- .gitignore | 58 ++++++++ vector/app/config/settings.py | 6 +- vector/deployment/container/Dockerfile | 77 +++++----- vector/deployment/container/Dockerfile-base | 39 ++--- vector/deployment/manifest/configmap.yaml | 67 ++++++--- vector/deployment/manifest/deployment.yaml | 156 ++++++++++++-------- vector/setup.sh | 24 ++- 7 files changed, 281 insertions(+), 146 deletions(-) diff --git a/.gitignore b/.gitignore index 2a4a0d1..2e2ab44 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,16 @@ ENV/ env.bak/ venv.bak/ +# Poetry +# πŸ“ Note: poetry.lock은 버전 μ œμ–΄μ— 포함해야 함 +.cache/ # Poetry μΊμ‹œ 디렉토리 (ν™ˆ 디렉토리 μ‚¬μš© μ‹œ) +.venv/ # Poetryκ°€ ν”„λ‘œμ νŠΈ 내에 κ°€μƒν™˜κ²½ 생성 μ‹œ +dist/ # Poetry build κ²°κ³Όλ¬Ό +.pytest_cache/ + +# Poetry κ°€μƒν™˜κ²½ (κΈ€λ‘œλ²Œ μœ„μΉ˜μ— μƒμ„±λ˜λŠ” 경우 - 일반적으둜 Git에 ν¬ν•¨λ˜μ§€ μ•ŠμŒ) +# ~/.cache/pypoetry/venvs/ + # IDE .vscode/ .idea/ @@ -81,12 +91,20 @@ logs/ # Vector DB and ML Models vector_db/ +vectordb/ # μΆ”κ°€: ν™ˆ 디렉토리 μ‚¬μš© μ‹œ Vector DB 디렉토리 *.pkl *.model *.bin embeddings/ checkpoints/ +# AI/ML μΊμ‹œ 디렉토리듀 (ν™ˆ 디렉토리 μ‚¬μš© μ‹œ) +.cache/huggingface/ +.cache/transformers/ +.cache/sentence_transformers/ +.cache/torch/ +.cache/pypoetry/ # Poetry μΊμ‹œ + # Data files data/ *.csv @@ -117,3 +135,43 @@ yarn-error.log* # Backup files *.bak *.backup + +# Jupyter Notebooks (μΆ”κ°€) +.ipynb_checkpoints/ +*.ipynb + +# macOS specific (μΆ”κ°€) +.AppleDouble +.LSOverride + +# Linux specific (μΆ”κ°€) +*~ + +# Windows specific (μΆ”κ°€) +Desktop.ini +$RECYCLE.BIN/ +*.cab +*.msi +*.msix +*.msm +*.msp + +# Coverage reports (μΆ”κ°€) +htmlcov/ +.coverage.* +coverage.xml + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + diff --git a/vector/app/config/settings.py b/vector/app/config/settings.py index e5a59bb..1a07d34 100644 --- a/vector/app/config/settings.py +++ b/vector/app/config/settings.py @@ -16,7 +16,7 @@ class Settings: LOG_LEVEL = os.getenv("LOG_LEVEL", "info") # Restaurant API μ„€μ • - RESTAURANT_API_HOST = os.getenv("RESTAURANT_API_HOST", "4.217.217.207") + RESTAURANT_API_HOST = os.getenv("RESTAURANT_API_HOST", "0.0.0.0") RESTAURANT_API_PORT = os.getenv("RESTAURANT_API_PORT", "18000") @property @@ -24,7 +24,7 @@ class Settings: return f"http://{self.RESTAURANT_API_HOST}:{self.RESTAURANT_API_PORT}" # Review API μ„€μ • - REVIEW_API_HOST = os.getenv("REVIEW_API_HOST", "4.217.217.207") + REVIEW_API_HOST = os.getenv("REVIEW_API_HOST", "0.0.0.0") REVIEW_API_PORT = os.getenv("REVIEW_API_PORT", "19000") @property @@ -36,7 +36,7 @@ class Settings: CLAUDE_MODEL = os.getenv("CLAUDE_MODEL", "claude-sonnet-4-20250514") # Vector DB μ„€μ • - VECTOR_DB_PATH = os.getenv("VECTOR_DB_PATH", "/app/vectordb") + VECTOR_DB_PATH = os.getenv("VECTOR_DB_PATH", "./vectordb") VECTOR_DB_COLLECTION = os.getenv("VECTOR_DB_COLLECTION", "restaurant_reviews") EMBEDDING_MODEL = os.getenv("EMBEDDING_MODEL", "sentence-transformers/all-MiniLM-L6-v2") diff --git a/vector/deployment/container/Dockerfile b/vector/deployment/container/Dockerfile index 18613d5..fe195fa 100644 --- a/vector/deployment/container/Dockerfile +++ b/vector/deployment/container/Dockerfile @@ -1,5 +1,5 @@ # deployment/container/Dockerfile -# Poetry 기반 Vector DB API Service Image - PVC 마운트 좩돌 ν•΄κ²° +# Poetry 기반 Vector DB API Service Image - ν™ˆ 디렉토리 μ‚¬μš© (μ•ˆμ „ν•œ 방식) # Base Imageμ—μ„œ 상속 (Poetry ν™˜κ²½ 포함) ARG BASE_IMAGE=vector-api-base:latest @@ -7,66 +7,61 @@ FROM ${BASE_IMAGE} # 메타데이터 LABEL maintainer="admin@example.com" -LABEL version="1.0.2" -LABEL description="Vector DB API Service with Poetry - PVC Mount Fixed" +LABEL version="1.0.3" +LABEL description="Vector DB API Service with Poetry - Home Directory Safe" -# ν™˜κ²½ λ³€μˆ˜ μ„€μ • - Poetry κ°€μƒν™˜κ²½ 경둜 μœ μ§€ +# ν™˜κ²½ λ³€μˆ˜ μ„€μ • - Poetry κ°€μƒν™˜κ²½ 경둜 μœ μ§€ (ν™ˆ 디렉토리) ENV HOME=/home/appuser \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ POETRY_VENV_IN_PROJECT=false \ POETRY_VIRTUALENVS_CREATE=true \ - POETRY_VIRTUALENVS_PATH=/opt/pypoetry/venvs \ - POETRY_CACHE_DIR=/opt/pypoetry/cache \ + POETRY_VIRTUALENVS_PATH=/home/appuser/.cache/pypoetry/venvs \ + POETRY_CACHE_DIR=/home/appuser/.cache/pypoetry/cache \ POETRY_NO_INTERACTION=1 \ - PATH="/home/appuser/.local/bin:/opt/pypoetry/venvs/vector-api/bin:/usr/local/bin:/usr/bin:/bin" + PATH="/home/appuser/.local/bin:/home/appuser/.cache/pypoetry/venvs/vector-api/bin:/usr/local/bin:/usr/bin:/bin" # root둜 μ „ν™˜ (파일 볡사 및 κΆŒν•œ μ„€μ •μš©) USER root # πŸ”§ Poetry μ„€μ • νŒŒμΌλ“€ 볡사 (μ˜μ‘΄μ„± 정보) -COPY pyproject.toml poetry.lock* /app/ +COPY pyproject.toml poetry.lock* /home/appuser/ # πŸš€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ†ŒμŠ€ μ½”λ“œ 볡사 -COPY app/ /app/app/ +COPY app/ /home/appuser/app/ -# πŸ“¦ Poetry μ˜μ‘΄μ„± μ„€μΉ˜ (κ°€μƒν™˜κ²½μ΄ /opt에 생성됨) -RUN cd /app && \ +# πŸ“¦ Poetry μ˜μ‘΄μ„± μ„€μΉ˜ (κ°€μƒν™˜κ²½μ΄ ν™ˆ 디렉토리에 생성됨) +RUN cd /home/appuser && \ # Poetry μ„€μ • 확인 및 μž¬μ„€μ • - poetry config virtualenvs.in-project false && \ - poetry config virtualenvs.create true && \ - poetry config virtualenvs.path /opt/pypoetry/venvs && \ - poetry config cache-dir /opt/pypoetry/cache && \ - echo "πŸ”§ Poetry μ„€μ • 확인:" && \ - poetry config --list && \ - echo "πŸ“¦ μ˜μ‘΄μ„± μ„€μΉ˜ μ‹œμž‘..." && \ - poetry install --no-dev --no-interaction && \ - echo "βœ… μ˜μ‘΄μ„± μ„€μΉ˜ μ™„λ£Œ" && \ - # μ„€μΉ˜λœ νŒ¨ν‚€μ§€ 확인 - poetry show | head -10 && \ - # κ°€μƒν™˜κ²½ μœ„μΉ˜ 확인 - poetry env info && \ + su - appuser -c "cd /home/appuser && \ + poetry config virtualenvs.in-project false && \ + poetry config virtualenvs.create true && \ + poetry config virtualenvs.path /home/appuser/.cache/pypoetry/venvs && \ + poetry config cache-dir /home/appuser/.cache/pypoetry/cache && \ + echo 'πŸ”§ Poetry μ„€μ • 확인:' && \ + poetry config --list && \ + echo 'πŸ“¦ μ˜μ‘΄μ„± μ„€μΉ˜ μ‹œμž‘...' && \ + poetry install --no-dev --no-interaction && \ + echo 'βœ… μ˜μ‘΄μ„± μ„€μΉ˜ μ™„λ£Œ' && \ + poetry show | head -10 && \ + poetry env info" && \ # μΊμ‹œ 정리 - rm -rf $POETRY_CACHE_DIR/cache && \ rm -rf /tmp/* # πŸ“ 데이터 디렉토리 생성 및 κΆŒν•œ μ„€μ • -RUN mkdir -p /app/data /app/logs /app/vectordb \ - && chmod -R 755 /app/data /app/logs /app/vectordb +RUN mkdir -p /home/appuser/data /home/appuser/logs /home/appuser/vectordb \ + && chmod -R 755 /home/appuser/data /home/appuser/logs /home/appuser/vectordb # πŸ‘€ μ‚¬μš©μž 및 κΆŒν•œ μ„€μ • -RUN if id "appuser" &>/dev/null; then \ - chown -R appuser:appuser /app; \ - chown -R appuser:appuser /opt/pypoetry; \ - else \ - echo "appuserκ°€ μ—†μ–΄μ„œ root둜 μ‹€ν–‰λ©λ‹ˆλ‹€"; \ - fi +RUN chown -R appuser:appuser /home/appuser # πŸ”§ μ‹€ν–‰ 슀크립트 생성 (Poetry κ°€μƒν™˜κ²½ μžλ™ ν™œμ„±ν™”) -RUN cat > /app/start.sh << 'EOF' +RUN cat > /home/appuser/start.sh << 'EOF' #!/bin/bash echo "πŸš€ Vector API μ‹œμž‘ 쀑..." echo "πŸ“ ν˜„μž¬ 디렉토리: $(pwd)" +echo "πŸ‘€ ν˜„μž¬ μ‚¬μš©μž: $(whoami)" +echo "🏠 ν™ˆ 디렉토리: $HOME" echo "🐍 Python μœ„μΉ˜: $(which python)" echo "πŸ“¦ Poetry μœ„μΉ˜: $(which poetry)" echo "πŸ”§ Poetry κ°€μƒν™˜κ²½ 정보:" @@ -75,26 +70,28 @@ echo "πŸ“‹ μ„€μΉ˜λœ νŒ¨ν‚€μ§€ (일뢀):" poetry show | head -5 echo "πŸ” dotenv λͺ¨λ“ˆ ν…ŒμŠ€νŠΈ:" poetry run python -c "from dotenv import load_dotenv; print('βœ… dotenv λͺ¨λ“ˆ 정상 λ‘œλ“œ')" +echo "πŸ” κ°€μƒν™˜κ²½ μœ„μΉ˜ 확인:" +ls -la ~/.cache/pypoetry/venvs/ echo "πŸš€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰..." exec poetry run python app/main.py EOF -RUN chmod +x /app/start.sh && \ - chown appuser:appuser /app/start.sh +RUN chmod +x /home/appuser/start.sh && \ + chown appuser:appuser /home/appuser/start.sh # πŸ₯ ν—¬μŠ€μ²΄ν¬ (μ˜μ‘΄μ„± 확인 포함) HEALTHCHECK --interval=30s --timeout=15s --start-period=60s --retries=3 \ - CMD poetry run python -c "from dotenv import load_dotenv; import app.main; print('βœ… μ•± ν—¬μŠ€μ²΄ν¬ 성곡')" || exit 1 + CMD su - appuser -c "cd /home/appuser && poetry run python -c 'from dotenv import load_dotenv; import app.main; print(\"βœ… μ•± ν—¬μŠ€μ²΄ν¬ 성곡\")'" || exit 1 # πŸš€ 포트 λ…ΈμΆœ EXPOSE 8000 -# πŸ“ μž‘μ—… 디렉토리 μ„€μ • -WORKDIR /app +# πŸ“ μž‘μ—… 디렉토리 μ„€μ • (ν™ˆ 디렉토리) +WORKDIR /home/appuser # πŸ‘€ μ‹€ν–‰ μ‚¬μš©μž μ„€μ • USER appuser # 🎯 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ - 슀크립트 μ‚¬μš© -CMD ["/app/start.sh"] +CMD ["./start.sh"] diff --git a/vector/deployment/container/Dockerfile-base b/vector/deployment/container/Dockerfile-base index deab09a..35d1163 100644 --- a/vector/deployment/container/Dockerfile-base +++ b/vector/deployment/container/Dockerfile-base @@ -19,9 +19,9 @@ ENV PYTHONDONTWRITEBYTECODE=1 \ POETRY_VIRTUALENVS_CREATE=true \ POETRY_VIRTUALENVS_PATH=/home/appuser/.cache/pypoetry/venvs \ POETRY_CACHE_DIR=/home/appuser/.cache/pypoetry/cache \ - HF_HUB_CACHE=/app/.cache/huggingface \ - TRANSFORMERS_CACHE=/app/.cache/transformers \ - SENTENCE_TRANSFORMERS_HOME=/app/.cache/sentence_transformers + HF_HUB_CACHE=/home/appuser/.cache/huggingface \ + TRANSFORMERS_CACHE=/home/appuser/.cache/transformers \ + SENTENCE_TRANSFORMERS_HOME=/home/appuser/.cache/sentence_transformers # πŸ”§ μ‹œμŠ€ν…œ νŒ¨ν‚€μ§€ μ„€μΉ˜ RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -86,36 +86,37 @@ RUN poetry --version && \ ls -la /home/appuser/.local/bin/poetry && \ which poetry -# πŸ—οΈ μž‘μ—… 디렉토리 μ„€μ • 및 κΆŒν•œ μ‘°μ • -WORKDIR /app +# πŸ—οΈ μž‘μ—… 디렉토리 μ„€μ • (ν™ˆ 디렉토리 μ‚¬μš©) +WORKDIR /home/appuser -# root둜 μ „ν™˜ν•˜μ—¬ 디렉토리 μ†Œμœ κΆŒ μ„€μ • +# μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 디렉토리 생성 USER root -RUN chown -R appuser:appuser /app +RUN mkdir -p /home/appuser/app && \ + chown -R appuser:appuser /home/appuser # πŸ“‹ Poetry μ„€μΉ˜ 슀크립트 볡사 및 κΆŒν•œ μ„€μ • -COPY setup.sh /app/setup.sh -RUN chmod +x /app/setup.sh && \ - chown appuser:appuser /app/setup.sh +COPY setup.sh /home/appuser/setup.sh +RUN chmod +x /home/appuser/setup.sh && \ + chown appuser:appuser /home/appuser/setup.sh # appuser둜 μ „ν™˜ν•˜μ—¬ Poetry ν™˜κ²½ μ„€μ • USER appuser # πŸš€ Poetry ν™˜κ²½ μ„€μ • 및 μ˜μ‘΄μ„± μ„€μΉ˜ -RUN cd /app && \ +RUN cd /home/appuser && \ export DEBIAN_FRONTEND=noninteractive && \ ./setup.sh --skip-poetry-install --skip-python311-check --force-reinstall # πŸ—‚οΈ ν•„μš”ν•œ 디렉토리 생성 및 κΆŒν•œ μ„€μ • USER root -RUN mkdir -p /app/.cache/huggingface \ - /app/.cache/transformers \ - /app/.cache/sentence_transformers \ - /app/vectordb \ - /app/data \ - /app/logs && \ - chmod -R 755 /app/.cache /app/vectordb /app/data /app/logs && \ - chown -R appuser:appuser /app && \ +RUN mkdir -p /home/appuser/.cache/huggingface \ + /home/appuser/.cache/transformers \ + /home/appuser/.cache/sentence_transformers \ + /home/appuser/vectordb \ + /home/appuser/data \ + /home/appuser/logs && \ + chmod -R 755 /home/appuser/.cache /home/appuser/vectordb /home/appuser/data /home/appuser/logs && \ + chown -R appuser:appuser /home/appuser && \ # Poetry κ°€μƒν™˜κ²½ 디렉토리 κΆŒν•œ μž¬ν™•μΈ chown -R appuser:appuser /home/appuser/.cache && \ chmod -R 755 /home/appuser/.cache diff --git a/vector/deployment/manifest/configmap.yaml b/vector/deployment/manifest/configmap.yaml index 1eea584..e19ae82 100644 --- a/vector/deployment/manifest/configmap.yaml +++ b/vector/deployment/manifest/configmap.yaml @@ -1,63 +1,92 @@ +# deployment/manifests/configmap.yaml - ν™ˆ 디렉토리 μ „ν™˜ 적용 apiVersion: v1 kind: ConfigMap metadata: name: vector-api-config + labels: + app: vector-api data: - # πŸ”§ κΈ°μ‘΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„€μ • (μœ μ§€) + # 🏠 ν™ˆ 디렉토리 기반 경둜 μ„€μ • + APP_ROOT: "/home/appuser" + + # πŸ”§ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„€μ • APP_TITLE: "μŒμ‹μ  Vector DB ꡬ좕 μ„œλΉ„μŠ€" APP_VERSION: "1.0.0" APP_DESCRIPTION: "μ†Œμƒκ³΅μΈμ„ μœ„ν•œ AI 기반 κ²½μŸμ—…μ²΄ 뢄석 및 μ•‘μ…˜ μΆ”μ²œ μ‹œμŠ€ν…œ" - # πŸ”§ κΈ°μ‘΄ μ„œλ²„ μ„€μ • (μœ μ§€) + # πŸ”§ μ„œλ²„ μ„€μ • HOST: "0.0.0.0" PORT: "8000" - LOG_LEVEL: "debug" # 디버깅을 μœ„ν•΄ debug둜 λ³€κ²½ + LOG_LEVEL: "info" - # πŸ”§ κΈ°μ‘΄ Restaurant API μ„€μ • (K8s ν™˜κ²½, μœ μ§€) + # 🏠 ν™ˆ 디렉토리 기반 파일 κ²½λ‘œλ“€ + VECTOR_DB_PATH: "/home/appuser/vectordb" + DATA_DIR: "/home/appuser/data" + LOG_DIR: "/home/appuser/logs" + + # πŸ”§ Restaurant API μ„€μ • (K8s ν™˜κ²½) RESTAURANT_API_HOST: "restaurant-api-service" RESTAURANT_API_PORT: "80" - # πŸ”§ κΈ°μ‘΄ Review API μ„€μ • (K8s ν™˜κ²½, μœ μ§€) + # πŸ”§ Review API μ„€μ • (K8s ν™˜κ²½) REVIEW_API_HOST: "kakao-review-api-service" REVIEW_API_PORT: "80" - # πŸ”§ κΈ°μ‘΄ Claude API μ„€μ • (μœ μ§€) + # πŸ”§ Claude API μ„€μ • CLAUDE_MODEL: "claude-sonnet-4-20250514" - # πŸ”§ κΈ°μ‘΄ Vector DB μ„€μ • (μœ μ§€) - VECTOR_DB_PATH: "/app/vectordb" + # πŸ”§ Vector DB μ„€μ • VECTOR_DB_COLLECTION: "restaurant_reviews" EMBEDDING_MODEL: "sentence-transformers/all-MiniLM-L6-v2" - # πŸ”§ κΈ°μ‘΄ 데이터 μˆ˜μ§‘ μ„€μ • (μœ μ§€) + # πŸ”§ 데이터 μˆ˜μ§‘ μ„€μ • MAX_RESTAURANTS_PER_CATEGORY: "50" MAX_REVIEWS_PER_RESTAURANT: "100" REQUEST_DELAY: "0.1" REQUEST_TIMEOUT: "600" - # πŸ†• ChromaDB μ΅œμ‹  버전 ν˜Έν™˜ μ„€μ • μΆ”κ°€ - CHROMA_DB_IMPL: "duckdb+parquet" # SQLite λŒ€μ‹  DuckDB μ‚¬μš© + # πŸ”§ ChromaDB μ„€μ • + CHROMA_DB_IMPL: "duckdb+parquet" ALLOW_RESET: "True" ANONYMIZED_TELEMETRY: "False" - # πŸ†• Python μ΅œμ ν™” μ„€μ • + # πŸ”§ Python μ΅œμ ν™” μ„€μ • PYTHONUNBUFFERED: "1" PYTHONDONTWRITEBYTECODE: "1" - # πŸ†• μΊμ‹œ 디렉토리 μ„€μ • - HF_HUB_CACHE: "/app/.cache/huggingface" - TRANSFORMERS_CACHE: "/app/.cache/transformers" + # 🏠 ν™ˆ 디렉토리 기반 μΊμ‹œ 디렉토리 μ„€μ • + HF_HUB_CACHE: "/home/appuser/.cache/huggingface" + TRANSFORMERS_CACHE: "/home/appuser/.cache/transformers" + SENTENCE_TRANSFORMERS_HOME: "/home/appuser/.cache/sentence_transformers" - # πŸ†• FastAPI μ„€μ • + # πŸ”§ Poetry μΊμ‹œ μ„€μ • + POETRY_CACHE_DIR: "/home/appuser/.cache/pypoetry/cache" + POETRY_VENV_PATH: "/home/appuser/.cache/pypoetry/venvs" + + # πŸ”§ FastAPI μ„€μ • FASTAPI_ENV: "production" - # πŸ†• Uvicorn μ„€μ • + # πŸ”§ Uvicorn μ„€μ • UVICORN_HOST: "0.0.0.0" UVICORN_PORT: "8000" - UVICORN_LOG_LEVEL: "debug" + UVICORN_LOG_LEVEL: "info" UVICORN_ACCESS_LOG: "true" - # πŸ†• νƒ€μž„μ•„μ›ƒ μ„€μ • + # πŸ”§ νƒ€μž„μ•„μ›ƒ μ„€μ • STARTUP_TIMEOUT: "300" # 5λΆ„ SHUTDOWN_TIMEOUT: "30" # 30초 + + # πŸ”§ λ©”λͺ¨λ¦¬ 및 μ„±λŠ₯ μ„€μ • + TORCH_NUM_THREADS: "2" + OMP_NUM_THREADS: "2" + TOKENIZERS_PARALLELISM: "false" + + # πŸ”§ λ³΄μ•ˆ μ„€μ • + DISABLE_TELEMETRY: "true" + NO_PROXY: "localhost,127.0.0.1" + + # πŸ”§ λ‘œκΉ… μ„€μ • + LOG_FORMAT: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + LOG_MAX_BYTES: "10485760" # 10MB + LOG_BACKUP_COUNT: "5" diff --git a/vector/deployment/manifest/deployment.yaml b/vector/deployment/manifest/deployment.yaml index 7306d73..bb2febc 100644 --- a/vector/deployment/manifest/deployment.yaml +++ b/vector/deployment/manifest/deployment.yaml @@ -1,12 +1,21 @@ -# deployment/manifests/deployment.yaml.fixed +# deployment/manifests/deployment.yaml - κ°„μ†Œν™”λœ 버전 (initContainer 제거) apiVersion: apps/v1 kind: Deployment metadata: name: vector-api labels: app: vector-api + version: v1.0.0 + annotations: + deployment.kubernetes.io/revision: "1" + description: "Vector DB API with Simplified Home Directory Structure" spec: replicas: 1 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 selector: matchLabels: app: vector-api @@ -14,55 +23,53 @@ spec: metadata: labels: app: vector-api + version: v1.0.0 + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8000" + prometheus.io/path: "/metrics" spec: - # πŸ”§ λ³Όλ₯¨ κΆŒν•œ 섀정을 μœ„ν•œ initContainer - initContainers: - - name: volume-permissions - image: busybox:1.35 - command: - - /bin/sh - - -c - - | - echo "=== λ³Όλ₯¨ κΆŒν•œ μ„€μ • μ‹œμž‘ ===" - mkdir -p /app/vectordb - chown -R 1000:1000 /app/vectordb - chmod -R 755 /app/vectordb - echo "=== λ³Όλ₯¨ κΆŒν•œ μ„€μ • μ™„λ£Œ ===" - volumeMounts: - - name: vector-db-storage - mountPath: /app/vectordb - securityContext: - runAsUser: 0 - + # 🚫 initContainer 제거 - ν™ˆ 디렉토리 μ‚¬μš©μœΌλ‘œ λΆˆν•„μš” + containers: - name: vector-api image: acrdigitalgarage03.azurecr.io/vector-api:latest imagePullPolicy: Always + + # πŸ”§ μ»¨ν…Œμ΄λ„ˆ 포트 ports: - - containerPort: 8000 + - name: http + containerPort: 8000 + protocol: TCP - # πŸ”§ λ³΄μ•ˆ μ»¨ν…μŠ€νŠΈ + # πŸ”§ λ³΄μ•ˆ μ»¨ν…μŠ€νŠΈ (appuser μ‚¬μš©) securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 allowPrivilegeEscalation: false readOnlyRootFilesystem: false + capabilities: + drop: + - ALL # πŸ”§ λ¦¬μ†ŒμŠ€ μ„€μ • resources: requests: memory: "4Gi" cpu: "1000m" + ephemeral-storage: "2Gi" limits: memory: "8Gi" cpu: "2000m" + ephemeral-storage: "5Gi" # πŸ₯ ν—¬μŠ€μ²΄ν¬ μ„€μ • livenessProbe: httpGet: path: /health - port: 8000 + port: http + scheme: HTTP initialDelaySeconds: 120 periodSeconds: 30 timeoutSeconds: 15 @@ -71,66 +78,85 @@ spec: readinessProbe: httpGet: path: /health - port: 8000 + port: http + scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 10 failureThreshold: 3 - # πŸ“‚ λ³Όλ₯¨ 마운트 + # πŸš€ μ‹œμž‘ ν”„λ‘œλΈŒ (초기 μ‹œμž‘ μ‹œκ°„ κ³ λ €) + startupProbe: + httpGet: + path: /health + port: http + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 30 # μ΅œλŒ€ 5λΆ„ λŒ€κΈ° + successThreshold: 1 + + # πŸ“‚ λ³Όλ₯¨ 마운트 (ν™ˆ 디렉토리 기반) volumeMounts: - name: vector-db-storage - mountPath: /app/vectordb + mountPath: /home/appuser/vectordb # βœ… PVC 마운트 + - name: tmp-volume + mountPath: /tmp + - name: cache-volume + mountPath: /home/appuser/.cache + subPath: "vector-api" - # ConfigMap ν™˜κ²½ λ³€μˆ˜ + # 🌍 ν™˜κ²½λ³€μˆ˜ μ„€μ • - ConfigMapμ—μ„œ λͺ¨λ“  κ°’ κ°€μ Έμ˜€κΈ° envFrom: - configMapRef: name: vector-api-config - - # 🌍 ν™˜κ²½λ³€μˆ˜ μ„€μ • (인증 ν•„λ“œ 제거) + + # πŸ” Secretμ—μ„œ λ―Όκ°ν•œ 정보 κ°€μ Έμ˜€κΈ° env: - - name: PYTHONUNBUFFERED - value: "1" - - name: PYTHONDONTWRITEBYTECODE - value: "1" - # πŸ”§ ChromaDB κΈ°λ³Έ μ„€μ • (인증 ν•„λ“œ 제거) - - name: ANONYMIZED_TELEMETRY - value: "False" - - name: CHROMA_DB_IMPL - value: "duckdb+parquet" - - name: ALLOW_RESET - value: "True" - # πŸ”§ 둜그 레벨 - - name: LOG_LEVEL - value: "info" - # πŸ”§ Claude API (ConfigMapμ—μ„œ κ°€μ Έμ˜€κΈ°) - name: CLAUDE_API_KEY valueFrom: secretKeyRef: name: vector-api-secret key: CLAUDE_API_KEY - - name: CLAUDE_MODEL - valueFrom: - configMapKeyRef: - name: vector-api-config - key: CLAUDE_MODEL - # πŸ”§ 기타 μ„€μ • (ConfigMapμ—μ„œ κ°€μ Έμ˜€κΈ°) - - name: APP_TITLE - valueFrom: - configMapKeyRef: - name: vector-api-config - key: APP_TITLE - - name: APP_VERSION - valueFrom: - configMapKeyRef: - name: vector-api-config - key: APP_VERSION + + # πŸ”§ λŸ°νƒ€μž„ ν™˜κ²½λ³€μˆ˜ + - name: PYTHONPATH + value: "/home/appuser" + - name: HOME + value: "/home/appuser" + - name: USER + value: "appuser" + + # πŸ”§ μ„±λŠ₯ μ΅œμ ν™” ν™˜κ²½λ³€μˆ˜ + - name: MALLOC_ARENA_MAX + value: "2" + - name: MALLOC_MMAP_THRESHOLD_ + value: "131072" + + # πŸ”§ μ»¨ν…Œμ΄λ„ˆ 생λͺ…μ£ΌκΈ° 관리 + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -c + - | + echo "Gracefully shutting down Vector API..." + curl -X POST http://localhost:8000/shutdown || true + sleep 10 # πŸ“¦ λ³Όλ₯¨ μ„€μ • volumes: - name: vector-db-storage persistentVolumeClaim: claimName: vector-db-pvc + - name: tmp-volume + emptyDir: + sizeLimit: 1Gi + - name: cache-volume + emptyDir: + sizeLimit: 2Gi # πŸ” 이미지 Pull Secret imagePullSecrets: @@ -146,6 +172,7 @@ spec: value: "aipool" effect: "NoSchedule" + # πŸ”§ Pod 배치 μ •μ±… affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: @@ -159,6 +186,15 @@ spec: - vector-api topologyKey: kubernetes.io/hostname + # πŸ”§ Pod μ„€μ • restartPolicy: Always dnsPolicy: ClusterFirst + terminationGracePeriodSeconds: 60 + + # πŸ”§ λ³΄μ•ˆ μ»¨ν…μŠ€νŠΈ (Pod 레벨) + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 diff --git a/vector/setup.sh b/vector/setup.sh index 502da6d..88afa93 100755 --- a/vector/setup.sh +++ b/vector/setup.sh @@ -71,6 +71,9 @@ echo "========================================================" echo "πŸš€ Poetry 기반 Vector DB API μ˜μ‘΄μ„± μ„€μΉ˜ (ν™ˆ 디렉토리)" echo "========================================================" echo "μ„€μΉ˜ μ‹œμž‘: $(date)" +echo "μž‘μ—… 디렉토리: $(pwd)" +echo "ν™ˆ 디렉토리: $HOME" +echo "μ‚¬μš©μž: $(whoami)" echo "" INSTALL_START=$(date +%s) @@ -147,7 +150,10 @@ fi if [ ! -f "pyproject.toml" ]; then log_info "Poetry ν”„λ‘œμ νŠΈ μ΄ˆκΈ°ν™” 쀑..." - # λΉ„λŒ€ν™”ν˜• μ΄ˆκΈ°ν™” + # ν˜„μž¬ μž‘μ—… 디렉토리 확인 + log_info "ν˜„μž¬ μž‘μ—… 디렉토리: $(pwd)" + + # λΉ„λŒ€ν™”ν˜• μ΄ˆκΈ°ν™” (ν™ˆ 디렉토리 κΈ°μ€€) cat > pyproject.toml << 'EOF' [tool.poetry] name = "vector-api" @@ -164,9 +170,9 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" EOF - log_success "pyproject.toml 생성 μ™„λ£Œ" + log_success "pyproject.toml 생성 μ™„λ£Œ (μœ„μΉ˜: $(pwd)/pyproject.toml)" else - log_success "κΈ°μ‘΄ pyproject.toml μ‚¬μš©" + log_success "κΈ°μ‘΄ pyproject.toml μ‚¬μš© (μœ„μΉ˜: $(pwd)/pyproject.toml)" fi # ============================================================================= @@ -206,6 +212,8 @@ poetry env use python3.11 # ν™˜κ²½ 정보 확인 POETRY_ENV_INFO=$(poetry config virtualenvs.path) log_success "Poetry κ°€μƒν™˜κ²½ κΈ°λ³Έ 경둜: $POETRY_ENV_INFO" +log_info "ν˜„μž¬ μž‘μ—… 디렉토리: $(pwd)" +log_info "μ•± 디렉토리 확인: $([ -d "app" ] && echo "βœ… app/ 디렉토리 쑴재" || echo "❌ app/ 디렉토리 μ—†μŒ")" # ============================================================================= # 6단계: μ†ŒμŠ€ μš°μ„ μˆœμœ„ 사전 μ„€μ • (μ€‘μš”!) @@ -341,13 +349,15 @@ echo "⏱️ 총 μ„€μΉ˜ μ‹œκ°„: ${MINUTES}λΆ„ ${SECONDS}초" echo "πŸ“¦ μ„€μΉ˜λœ νŒ¨ν‚€μ§€ 수: $(poetry show | wc -l)" echo "🐍 Python ν™˜κ²½: $(poetry run python --version)" echo "πŸ“ ν™˜κ²½ 경둜: $(poetry env info --path)" +echo "🏠 μž‘μ—… 디렉토리: $(pwd)" +echo "🏠 ν™ˆ 디렉토리: $HOME" echo "" echo "πŸš€ λ‹€μŒ 단계:" echo " 1. κ°€μƒν™˜κ²½ ν™œμ„±ν™”:" echo " poetry shell" echo "" -echo " 2. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰:" +echo " 2. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ (ν™ˆ 디렉토리 κΈ°μ€€):" echo " poetry run python app/main.py" echo "" echo " 3. 개발 μ„œλ²„ μ‹€ν–‰:" @@ -360,15 +370,19 @@ echo " - poetry show --tree # μ˜μ‘΄μ„± 트리 확인" echo " - poetry add [νŒ¨ν‚€μ§€λͺ…] # μƒˆ νŒ¨ν‚€μ§€ μΆ”κ°€" echo " - poetry update # νŒ¨ν‚€μ§€ μ—…λ°μ΄νŠΈ" echo " - poetry env info # ν™˜κ²½ 정보 확인" +echo " - pwd # ν˜„μž¬ μž‘μ—… 디렉토리 확인" +echo " - ls -la ~/.cache/pypoetry/venvs/ # Poetry κ°€μƒν™˜κ²½ 확인" echo "" # μžλ™ μ‹€ν–‰ μ˜΅μ…˜ if [ "$RUN_AFTER_INSTALL" = true ]; then if [ -f "app/main.py" ]; then - log_info "μ•± μžλ™ μ‹€ν–‰ 쀑..." + log_info "μ•± μžλ™ μ‹€ν–‰ 쀑... (μž‘μ—… 디렉토리: $(pwd))" poetry run python app/main.py else log_warning "app/main.py 파일이 μ—†μ–΄ μžλ™ 싀행을 κ±΄λ„ˆλœλ‹ˆλ‹€." + log_info "ν˜„μž¬ 디렉토리: $(pwd)" + log_info "파일 λͺ©λ‘: $(ls -la)" fi fi