> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nora.my/llms.txt
> Use this file to discover all available pages before exploring further.

# Kubernetes (Helm)

> nora-onprem Helm 차트로 Kubernetes 클러스터에 Nora 를 배포합니다. 인그레스, TLS, 프라이빗 레지스트리, 라이선스 오버라이드.

`nora-onprem` Helm 차트는 [Docker Compose](/ko/local-app/deploy/compose) 와 같은 다섯 개 서비스를 Kubernetes 클러스터에 배포합니다. 차트는 플랫폼 레포의 `infra/onprem/helm/nora-onprem` 에 있습니다.

## 설치

새 설치에서 필수 값은 `postgres.password` 하나뿐입니다.

```bash theme={null}
helm install nora ./nora-onprem \
  --namespace nora --create-namespace \
  --set postgres.password='CHANGE_ME' \
  --set publicUrl='http://nora.example.internal'
```

차트는 릴리스 이름 아래 Deployment, StatefulSet, Service 를 프로비저닝합니다. 정확한 리소스 목록은 아래 [차트가 만드는 것](#차트가-만드는-것) 을 참고하세요.

## 흔한 오버라이드

### 인그레스와 TLS 켜기

```bash theme={null}
--set ingress.enabled=true \
--set ingress.host=nora.example.internal \
--set ingress.className=nginx \
--set ingress.tlsSecret=nora-tls
```

`ingress.tlsSecret` 을 세팅하면 `NORA_COOKIE_SECURE=1` 이 자동으로 켜집니다. 브라우저는 TLS 위의 세션 쿠키에 `Secure` 속성을 요구합니다.

### 프라이빗 레지스트리 사용 (에어갭)

tarball 이미지를 자체 레지스트리에 load 한 뒤 각 repository 를 오버라이드합니다. tarball 은 [에어갭 tarball](/ko/local-app/deploy/airgap) 을 참고하세요.

```bash theme={null}
--set image.server.repository=registry.internal/nora-server \
--set image.server.tag=1.0.0 \
--set image.llmBridge.repository=registry.internal/nora-llm-bridge \
--set image.llmBridge.tag=1.0.0 \
--set imagePullSecrets[0].name=my-registry-secret
```

### 에어갭 부팅 프로브 켜기

```bash theme={null}
--set deploy.airgap=true
```

프로브 타겟(기본 `1.1.1.1:443`) 이 여전히 도달 가능하면 서버가 부팅 시점에 exit 78 로 종료합니다. 운영자의 egress 격리에 대한 스모크 테스트입니다.

### 오프라인 라이선스 첨부

```bash theme={null}
kubectl -n nora create secret generic nora-license \
  --from-file=license.json=./license.json

helm upgrade nora ./nora-onprem -n nora \
  --set license.fileSecret=nora-license --reuse-values
```

차트가 이 시크릿을 `/etc/nora/license.json` 에 마운트하고 서버에 `NORA_LICENSE_FILE` 을 지정합니다.

### 검색을 Qdrant 로 스위치

```bash theme={null}
--set vectorStore.backend=qdrant
```

기본은 `pgvector` (Postgres pod 내장) 입니다. 벡터 검색을 전용 pod 에서 돌리고 싶을 때 `qdrant` 로 바꿉니다.

## 차트가 만드는 것

| 리소스 | 타입 | 용도 |
| - | - | - |
| `<release>-nora-onprem-server` | Deployment + Service | Rust API 와 SPA (포트 8090) |
| `<release>-nora-onprem-llm-bridge` | Deployment + Service | LLM 서브프로세스 브릿지 (포트 8091) |
| `<release>-nora-onprem-postgres` | StatefulSet + Service | pgvector 붙은 Postgres (레플리카당 PVC) |
| `<release>-nora-onprem-redis` | Deployment + Service | 캐시 |
| `<release>-nora-onprem-qdrant` | StatefulSet + Service | 벡터 스토어 (선택) |
| `<release>-nora-onprem-secrets` | Secret | DB 비밀번호와 라이선스 키 |
| `<release>-nora-onprem` | Ingress | `ingress.enabled=true` 일 때만 |

## 아직 지원하지 않는 것

* **서버 멀티 레플리카.** LLM 서브프로세스의 HOME 격리가 아직 미착륙이라 서버 pod 는 `concurrency=1` 로 돕니다.
* **HPA 와 오토스케일링.** 위 항목에 의존합니다.
* **백업 · 복원 job.** StatefulSet 의 PVC 에 표준 Postgres 도구를 사용하세요.
* **cert-manager Issuer 배선.** 차트는 `ingress.tlsSecret` 이 가리키는 `Secret` 만 소비하므로 Issuer 는 여러분이 준비하세요.

## 업그레이드

```bash theme={null}
helm upgrade nora ./nora-onprem -n nora \
  --set image.server.tag=1.2.0 \
  --set image.llmBridge.tag=1.2.0 \
  --reuse-values
```

새 서버 pod 의 첫 부팅에서 마이그레이션이 자동으로 실행됩니다 (`NORA_RUN_MIGRATIONS=1`).

<Warning>
  마이그레이션은 additive-only 입니다. 스키마가 앞선 상태를 넘어 다운그레이드하려면 매칭되는 DB 스냅샷을 준비해 두세요.
</Warning>

## 언인스톨

```bash theme={null}
helm uninstall nora -n nora
kubectl delete namespace nora   # PVC 까지 함께 삭제
```

`helm uninstall` 만 실행하면 PVC 는 남습니다. 실수로 삭제하는 경우에도 데이터가 살아남도록 하기 위해서입니다. 확실할 때 네임스페이스를 지우세요.

## 관련

<CardGroup cols={2}>
  <Card title="Docker Compose" icon="docker" href="/ko/local-app/deploy/compose">
    같은 다섯 개 서비스를 호스트 한 대에.
  </Card>

  <Card title="에어갭 tarball" icon="box-archive" href="/ko/local-app/deploy/airgap">
    프라이빗 레지스트리에 push 할 이미지를 담는 아카이브.
  </Card>
</CardGroup>
