119 lines
7.4 KiB
Markdown
119 lines
7.4 KiB
Markdown
# 지원 데이터 소스 & 바인딩 env 주입
|
|
|
|
앱은 접속정보를 **하드코딩하지 말고**, 바인딩된 소스가 주입하는 아래 env로 읽는다.
|
|
매니페스트에서 `binds: [{ alias, source }]` 로 연결하면, `alias`(대문자화)가 env 프리픽스가 된다.
|
|
예: `alias: db` → `DB_URL`, `DB_HOST`, `DB_PORT`, `DB_USERNAME`, `DB_PASSWORD`, `DB_DB`.
|
|
|
|
## 지원 소스 (`requires[].type`)
|
|
| type | 소스 | 비고 |
|
|
|---|---|---|
|
|
| `postgresql` | PostgreSQL | 관계형 |
|
|
| `mysql` | MySQL | 관계형 |
|
|
| `mariadb` | MariaDB | 관계형(MySQL 와이어 호환) |
|
|
| `mongodb` | MongoDB | 도큐먼트 |
|
|
| `redis` | Redis | 인메모리 KV/캐시 |
|
|
| `minio` | MinIO | S3 호환 오브젝트 스토리지 |
|
|
| `rabbitmq` | RabbitMQ | 메시지 브로커(AMQP) |
|
|
| `solr` | Solr | 검색 엔진 |
|
|
| `oracle` | Oracle | 관계형(외부 연결) |
|
|
|
|
`plan` ∈ `{small, medium, large}`.
|
|
|
|
## 소스별 주입 env (예시 alias=`db`)
|
|
모든 타입 공통: **`<ALIAS>_HOST`**, **`<ALIAS>_PORT`**.
|
|
|
|
| type | 추가 env 키 | `<ALIAS>_URL` 형식 |
|
|
|---|---|---|
|
|
| `postgresql` | `_USERNAME` `_PASSWORD` `_DB` | `postgresql://user:pw@host:port/db` |
|
|
| `mysql` | `_USERNAME` `_PASSWORD` `_DB` | `mysql://user:pw@host:port/db` |
|
|
| `mariadb` | `_USERNAME` `_PASSWORD` `_DB` | `mysql://user:pw@host:port/db` |
|
|
| `mongodb` | `_USERNAME` `_PASSWORD` `_DB` | `mongodb://user:pw@host:port/db?authSource=db` |
|
|
| `redis` | `_USERNAME`(빈) `_PASSWORD` `_DB`(번호) | `redis://:pw@host:port/db` |
|
|
| `minio` | `_ACCESS_KEY` `_SECRET_KEY` `_ENDPOINT` `_BUCKET` `_REGION` `_USE_SSL` | `_URL`=`_ENDPOINT` |
|
|
| `rabbitmq` | `_USERNAME` `_PASSWORD` `_VHOST` `_MGMT_URL` | `amqp://user:pw@host:port/vhost` |
|
|
| `solr` | `_CORE` `_ENDPOINT` | `http://host:port/solr/core` |
|
|
| `oracle` | `_USERNAME` `_PASSWORD` `_SERVICE` `_JDBC_URL` `_DSN` | `oracle://user:pw@host:port/service` |
|
|
|
|
> 비밀번호·키는 인클러스터 Secret으로 주입되고 콘솔/브라우저에 노출되지 않는다. URL의 user/pw는 URL-인코딩됨.
|
|
|
|
## 로컬 개발 → 검증 → 운영, 같은 바인딩 계약
|
|
**로컬 개발(`yakcloud dev`, 로컬 kind)**: 선언한 소스를 로컬 컨테이너로 띄우고 위 `<ALIAS>_*` env를 관리형과
|
|
**동일하게** 주입한다 — 앱 코드는 dev/prod 구분 없이 같은 env로 접속(직선 파리티). 상위 환경(val/prod)은
|
|
아래 관리형 모드로 배포·승격된다.
|
|
|
|
관리형 데이터 소스는 두 가지 모드:
|
|
1. **인클러스터(local)**: 클러스터 안에서 실제로 프로비저닝(StatefulSet). 개발 클러스터에 배포하면 그 클러스터의 소스가
|
|
`<ALIAS>_*` 로 주입되고, 상위 환경으로 승격하면 그 환경 클러스터의 소스가 주입된다 — 각 환경이 자체 데이터 계층을 가진다.
|
|
2. **공유 외부(shared)**: 소용량(S) 클러스터용. 매니페스트 `requires` 에 `{ name, type, mode: shared }` 로 선언(shared 지원 타입은 아래 '운영 소스 모드 결정' 표 참조)
|
|
(또는 `yakcloud source add <name> mongodb --shared`; 콘솔/API 등록도 가능). 배포 시 백엔드가 클러스터별 격리 DB/계정을
|
|
만들어, 모든 환경이 같은 외부 소스 이름으로 환경별 격리 접속(인클러스터 StatefulSet 불필요).
|
|
환경 간 데이터 백업·싱크는 별도(추후).
|
|
|
|
> **원격 클러스터의 기본은 인클러스터(local)가 아니라 외부/공유(shared/remote) 소스다.** 인클러스터 전용
|
|
> 인스턴스(`mode: local`)는 정말 필요할 때만 옵트인한다.
|
|
|
|
## 환경별 실제 소스 이름 매핑 (`clusterName`)
|
|
로컬(dev)에서 쓰는 소스 이름과 운영(prod)에서 붙는 **실제 소스 이름이 다를 수 있다.** 예를 들어 dev 는 논리 이름으로
|
|
로컬 소스를 새로 띄우지만, prod 는 이미 존재하는 (이름이 다른) 외부/공유 소스에 붙여야 한다.
|
|
|
|
`requires[].clusterName` 으로 **논리 이름(`name`)** 과 **실제 클러스터 소스 이름(`clusterName`)** 을 분리한다.
|
|
- `name` = 논리 이름 — `binds[].source` 가 가리키는 안정 키. 환경이 바뀌어도 앱/바인딩은 불변.
|
|
- `clusterName` = 대상 클러스터에서의 실제 소스 이름. 생략하면 `name` 과 같다. 매칭·프로비저닝·상태 조회는 이 값 기준.
|
|
|
|
주로 `environments.<env>` 오버레이에서 환경별로만 덮어쓴다(base 는 논리 이름 그대로). 오버레이는 **base 하고만 병합**되며(`requires` 는 `name` 매칭 병합), dev↔val↔prod 끼리는 서로 상속하지 않는다. `type` 은 base 또는 해당 환경에 반드시 있어야 하고, 없거나 매칭이 안 맞으면 **배포 전 검증 오류**로 걸러진다. 예:
|
|
```yaml
|
|
requires:
|
|
- { name: appdb, type: postgresql } # dev: 실제 소스명 = appdb (논리 이름)
|
|
|
|
environments:
|
|
dev: { cluster: my-dev }
|
|
prod:
|
|
cluster: my-prod
|
|
requires:
|
|
- { name: appdb, clusterName: shared-prod-pg } # prod: 기존 외부 소스 'shared-prod-pg' 에 매핑(type 은 상속)
|
|
|
|
workloads:
|
|
- name: api
|
|
binds:
|
|
- { alias: db, source: appdb } # 항상 논리 이름 참조 — 환경 무관
|
|
```
|
|
결과: dev 는 `appdb` 소스를, prod 는 `shared-prod-pg` 소스를 쓰지만 앱은 두 환경 모두 `DB_URL` 등 동일 env 로 접속한다.
|
|
`yakcloud project info` / `datasource ls` 는 현재 환경 기준으로 `논리 → 실제` 매핑을 함께 보여준다.
|
|
|
|
## 운영 소스 모드 결정 (shared / remote / local)
|
|
로컬(dev)은 도커로 논리 이름 그대로 뜨므로 결정할 게 없다. **운영(prod/val)은 소스마다 세 모드 중 하나를 고른다:**
|
|
|
|
| 모드 | 언제 | 매니페스트 |
|
|
|---|---|---|
|
|
| **shared** | 이 배포에 그 타입의 공유 서버가 있을 때(격리 DB 민팅) | `requires: [{ name, type, mode: shared }]` (+`clusterName` 으로 특정 소스 지정 가능) |
|
|
| **remote** | 이미 있는 외부 서버에 붙일 때 | 접속정보는 **매니페스트/git 금지**(자격 격리) → 콘솔/API로 등록 후 `clusterName` 으로 이름 참조 |
|
|
| **local** | 전용 인스턴스를 클러스터 안에 새로 만들 때 | `requires: [{ name, type, mode: local, plan: small }]` |
|
|
|
|
타입별 지원 모드: pg·mysql·mariadb·mongodb·rabbitmq·solr = `local/remote/shared`, redis·minio = `local/remote`, **oracle = remote 전용**.
|
|
|
|
**결정 정보 조회(에이전트용):**
|
|
```sh
|
|
yakcloud datasource options postgresql --env prod --json
|
|
# → { "modes":["local","remote","shared"], "sharedAvailable": true|false, "existing":[…], "existingError": null|"<사유>" }
|
|
# sharedAvailable=이 배포에 공유 서버가 실제로 구성됐는지(자격 미노출, 존재 여부만).
|
|
# existingError=기존 소스 조회 실패 사유(빈 existing 이 '없음'인지 '조회 실패'인지 구분).
|
|
yakcloud datasource ls --env prod --json # 그 클러스터의 기존 소스. --cluster <id> 로 클러스터 직접 지정도 가능
|
|
```
|
|
`sharedAvailable:false` 인데 `mode: shared` 로 배포하면 `503 공유 백킹 미구성` 으로 거부된다 — 위 조회로 미리 확인하라.
|
|
|
|
## 앱 코드 예시
|
|
```python
|
|
# Python — alias=db (postgres)
|
|
import os, psycopg2
|
|
conn = psycopg2.connect(os.environ["DB_URL"])
|
|
```
|
|
```js
|
|
// Node — alias=mongo
|
|
const client = new MongoClient(process.env.MONGO_URL);
|
|
```
|
|
```js
|
|
// MinIO(S3) — alias=files
|
|
const s3 = new S3Client({ endpoint: process.env.FILES_ENDPOINT, region: process.env.FILES_REGION,
|
|
credentials: { accessKeyId: process.env.FILES_ACCESS_KEY, secretAccessKey: process.env.FILES_SECRET_KEY } });
|
|
```
|