@@ -90,7 +90,7 @@ go build -o xdatabase-proxy cmd/proxy/main.go
9090| Variable | Description | Required | Default | Example Value | When to Use |
9191| ---------------- | -------------------------------------------------------------------------------------- | -------- | ------------ | --------------------------------------- | ----------- |
9292| DISCOVERY_MODE | Discovery strategy: ` kubernetes ` or ` static ` | No | kubernetes | static | Auto-set to ` static ` if ` STATIC_BACKENDS ` is provided |
93- | STATIC_BACKENDS | Static backend configuration (JSON array ) | Conditional | - | [ {"name":" db1","host":" 10.0.1.5","port" :5432} ] | ** Required** when not using Kubernetes discovery |
93+ | STATIC_BACKENDS | Static backend mapping ( ` deployment_id[.pool]=host:port ` comma-separated ) | Conditional | - | db1= 10.0.1.5:5432,db1.pool=10.0.1.5:6432 | ** Required** when not using Kubernetes discovery |
9494| KUBECONFIG | Path to kubeconfig file | Conditional | ~ /.kube/config | /path/to/config | ** Required** when ` DISCOVERY_MODE=kubernetes ` AND running outside cluster (VM/Container) |
9595| KUBE_CONTEXT | Kubernetes context name | No | - | production-cluster | Use for multi-cluster setups with kubeconfig |
9696
@@ -104,11 +104,16 @@ go build -o xdatabase-proxy cmd/proxy/main.go
104104** Configuration Rules:**
105105- ✅ ** In Kubernetes Pod** : ` DISCOVERY_MODE=kubernetes ` (default, uses in-cluster config)
106106- ✅ ** VM/Container → Remote K8s** : ` DISCOVERY_MODE=kubernetes ` + ` KUBECONFIG=/path/to/config `
107- - ✅ ** Static Backends** : ` STATIC_BACKENDS='[...] ' ` (auto-sets ` DISCOVERY_MODE=static ` )
107+ - ✅ ** Static Backends** : ` STATIC_BACKENDS='db1=host:5432,db1.pool=host:6432 ' ` (auto-sets ` DISCOVERY_MODE=static ` )
108108- ⚠️ ** Cannot mix** : Cannot use both ` STATIC_BACKENDS ` and ` DISCOVERY_MODE=kubernetes ` at same time
109109- ⚠️ ** KUBECONFIG required** : If ` DISCOVERY_MODE=kubernetes ` + not in cluster → must provide ` KUBECONFIG `
110110- ⚠️ ** NAMESPACE required** : If ` DISCOVERY_MODE=kubernetes ` → must provide ` NAMESPACE `
111111
112+ ** Static Backends Format:**
113+ - ` deployment_id=host:port ` → direct connections
114+ - ` deployment_id.pool=host:port ` → pooled connections (optional)
115+ - Multiple entries comma-separated, e.g. ` db1=10.0.1.5:5432,db1.pool=10.0.1.5:6432 `
116+
112117#### TLS/SSL Configuration
113118
114119| Variable | Description | Required | Default | Example Value | When to Use |
@@ -162,17 +167,42 @@ go build -o xdatabase-proxy cmd/proxy/main.go
162167| TLS_ENABLE_SELF_SIGNED | TLS_AUTO_GENERATE |
163168| POD_NAMESPACE | NAMESPACE |
164169
165- ### Kubernetes Labels
170+ ### Kubernetes Service Discovery
171+
172+ Labels act as a ** composite index** for service discovery. Proxy uses ` (xdatabase-proxy-deployment-id, xdatabase-proxy-database-type, xdatabase-proxy-pooled) ` as the lookup key.
173+
174+ ** Label Matching Strategy:**
175+ - Proxy searches for services matching the composite index
176+ - If multiple services match the same criteria, ** the first one is used** (like ` findFirst() ` in databases)
177+ - Extra labels are ignored (safe to add additional labels)
178+ - Missing optional labels are handled gracefully
166179
167- The following labels are required for services in Kubernetes discovery mode:
180+ | Label | Type | Description | Example Value | Index |
181+ | --------------------------------- | ------- | -------------------------------------------------- | --------------- | ----- |
182+ | ** xdatabase-proxy-deployment-id** | String | Database deployment ID (routing key) | db-deployment-1 | ✅ YES |
183+ | ** xdatabase-proxy-database-type** | String | Database type (filter) | postgresql | ✅ YES |
184+ | ** xdatabase-proxy-pooled** | Boolean | Pooled connections (true/false) | true | ✅ YES |
185+ | xdatabase-proxy-destination-port | Integer | Target port for the database connection | 5432 | — |
186+ | xdatabase-proxy-enabled | Boolean | (Deprecated) Whether service is managed by proxy | true | — |
168187
169- | Label | Description | Example Value |
170- | -------------------------------- | -------------------------------------------------- | --------------- |
171- | xdatabase-proxy-enabled | Whether the service should be managed by the proxy | true |
172- | xdatabase-proxy-deployment-id | Database deployment ID | db-deployment-1 |
173- | xdatabase-proxy-database-type | Database type | postgresql |
174- | xdatabase-proxy-pooled | Whether this is a connection pooling service | true/false |
175- | xdatabase-proxy-destination-port | Target port for the database connection | 5432 |
188+ ** Label Indexing Example:**
189+
190+ When proxy receives connection: ` postgres://user.db-prod.pool@proxy:5432/db `
191+ - Extracts: ` deployment_id=db-prod ` , ` pooled=true `
192+ - Searches: services with ` deployment_id=db-prod ` AND ` pooled=true `
193+ - Returns: ** first matching service** (even if multiple exist)
194+
195+ ```
196+ Cluster Services:
197+ 1. Service: db-prod-1 (deployment_id=db-prod, pooled=true) → ✅ MATCHED & USED
198+ 2. Service: db-prod-2 (deployment_id=db-prod, pooled=true) → ⏭️ SKIPPED (duplicate)
199+ 3. Service: db-prod-pool (deployment_id=db-prod, pooled=false) → ⏭️ SKIPPED (diff pooled)
200+ 4. Service: db-staging (deployment_id=db-staging, pooled=true)→ ⏭️ SKIPPED (diff id)
201+ ```
202+
203+ ** Connection String Routing:**
204+ - ` postgres://user.db-prod@proxy:5432/db ` → uses ` deployment_id=db-prod, pooled=false `
205+ - ` postgres://user.db-prod.pool@proxy:5432/db ` → uses ` deployment_id=db-prod, pooled=true `
176206
177207## Usage Examples
178208
@@ -206,7 +236,7 @@ docker run -d \
206236export DATABASE_TYPE=postgresql
207237export RUNTIME=vm
208238export DISCOVERY_MODE=static
209- export STATIC_BACKENDS=' [{"name":" db1","host":" 10.0.1.5","port" :5432},{"name":"db2","host":" 10.0.1.6","port" :5432}] '
239+ export STATIC_BACKENDS=' db1= 10.0.1.5:5432,db1.pool=10.0.1.5:6432,db2= 10.0.1.6:5432'
210240export TLS_AUTO_GENERATE=true
211241export TLS_AUTO_RENEW=true
212242
@@ -262,21 +292,45 @@ postgresql://myuser.db-deployment-1.pool@localhost:5432/mydb
262292## Architecture
263293
264294```
265- ┌─────────────────────────────────────────────────────────────┐
266- │ XDatabase Proxy │
267- │ │
268- │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
269- │ │ Config │ │ Factory │ │ Orchestrator │ │
270- │ │ Management │→ │ Pattern │→ │ (main.go) │ │
271- │ └──────────────┘ └──────────────┘ └──────────────┘ │
272- │ │
273- │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
274- │ │ Discovery │ │ TLS │ │ Proxy │ │
275- │ │ (K8s/Static)│ │ Provider │ │ Handler │ │
276- │ └──────────────┘ └──────────────┘ └──────────────┘ │
277- └─────────────────────────────────────────────────────────────┘
295+ ┌───────────────────────────────────────────────────────────────┐
296+ │ xdatabase-proxy │
297+ │ │
298+ │ ┌──────────────────┐ ┌──────────────────────┐ │
299+ │ │ Config & Runtime │ │ Orchestrator (app.go)│ │
300+ │ │ env -> types │ → │ wires factories │ │
301+ │ └──────────────────┘ └──────────────────────┘ │
302+ │ | | │
303+ │ v v │
304+ │ ┌──────────────────┐ ┌──────────────────────┐ │
305+ │ │ ResolverFactory │ │ TLSFactory │ │
306+ │ │ (k8s | static) │ │ (k8s | file | memory) │ │
307+ │ └──────────────────┘ └──────────────────────┘ │
308+ │ \ / │
309+ │ v v │
310+ │ ┌────────────────────────────────┐ │
311+ │ │ ProxyFactory (PostgreSQL) │ │
312+ │ │ builds ConnectionHandler │ │
313+ │ └────────────────────────────────┘ │
314+ │ | │
315+ │ ┌────────────────────────┐ │
316+ │ │ Core Server │ │
317+ │ │ (TCP accept loop) │ │
318+ │ └────────────────────────┘ │
319+ │ | │
320+ │ ┌────────────────────────┐ │
321+ │ │ Health Server │ │
322+ │ │ /health, /ready │ │
323+ │ └────────────────────────┘ │
324+ └───────────────────────────────────────────────────────────────┘
278325```
279326
327+ ** Flow**
328+ - Env → ` config ` : validates runtime, discovery, TLS, ports.
329+ - ` app.Application ` : initializes logger, resolver, TLS provider (optional), proxy handler, listener.
330+ - Factories: runtime-aware resolver (k8s/static), pluggable TLS (k8s/file/memory), protocol proxy.
331+ - ` core.Server ` : TCP accept loop, delegates to connection handler.
332+ - ` api.HealthServer ` : ` /health ` liveness, ` /ready ` readiness.
333+
280334## Health Check Endpoints
281335
282336- ` GET /health ` - Basic health check
0 commit comments