# SERVICE-PROXY ARCHITECTURE

## Overview

service-proxy is a Data Plane component running in every tenant Kubernetes cluster's `tidb-admin` namespace. It acts as the HTTP gateway between the Regional Control Plane and in-cluster TiDB ecosystem services.

## Runtime Topology

```text
External Request
      │
      ▼
┌─────────────┐
│ Kong Ingress │  regex path matching
│  Controller  │  /@/proxy/cluster/\d+/(pd|tibr|ticdc|dm)(/.*)?
└──────┬──────┘  /check
       │
       ▼
┌──────────────┐        ┌──────────────────────────────────┐
│ service-proxy │        │  Target services (per cluster)   │
│  :8080 biz   │───────►│  pd-api           :2379          │
│  :8081 prom  │        │  tibr-api         :19500         │
└──────────────┘        │  ticdc-api        :8300          │
                        │  dm-api           :8261          │
                        │  tiflash-compute  :20292         │
                        │  tiflash-write    :20292         │
                        └──────────────────────────────────┘
```

- **Port 8080**: business traffic (proxy + `/check` endpoint)
- **Port 8081**: Prometheus metrics

## Core Functions

| Function | Entry point | Description |
|----------|-------------|-------------|
| HTTP reverse proxy | `pkg/proxy/`, `pkg/route/` | Routes requests to PD, TiBR, TiCDC, DM, TiFlash based on URL path |
| Connectivity check | `pkg/checker/` | `/check` endpoint verifying backend reachability and external dependency checks such as KMS master key usability |
| Audit logging | `pkg/audit/` | Request/response logging; optional sidecar mode (`audit-ng`) pushes logs to cloud storage |
| Config hot-reload | `pkg/config/` | Watches `/etc/service-proxy/config.yaml` (from ConfigMap) for changes |
| Secret management | `pkg/secret/` | TLS via `db-cluster-client-secret` |
| Observability | `pkg/observability/` | Prometheus metrics on :8081 |

## Ingress Configuration

Kong Ingress Controller with regex-based routing:

| Path pattern | Backend |
|-------------|---------|
| `/@/proxy/cluster/\d+/pd(/.*)?` | pd-api:2379 |
| `/@/proxy/cluster/\d+/tibr(/.*)?` | tibr-api:19500 |
| `/@/proxy/cluster/\d+/ticdc(/.*)?` | ticdc-api:8300 |
| `/@/proxy/cluster/\d+/dm(/.*)?` | dm-api:8261 |
| `/check` | service-proxy /check handler |

## Security

- Non-root container: UID 1000 / GID 2000
- TLS client cert from `db-cluster-client-secret`
- Pod anti-affinity for HA

## Helm Chart

Path: `../dataplane-manager/helm/service-proxy/`

Resources deployed:
- **Deployment**: service-proxy pods + optional `audit-ng` sidecar
- **Service**: ClusterIP, port 80 → 8080
- **Ingress**: Kong ingress rules (see above)
- **ConfigMap**: `/etc/service-proxy/config.yaml`
- **RBAC**: ServiceAccount, Role, RoleBinding

## Deployment Pipeline

```text
Code merge to main
      │
      ▼
┌──────────────────────────────────────────────┐
│ CI/CD: .github/workflows/service-proxy-cd.yaml│
│  1. Docker build                              │
│  2. Push to 3 registries:                     │
│     - AWS ECR (us-west-2)                     │
│     - Alicloud ACR (ap-southeast-1)           │
│     - Azure ACR (tidbclouddev)                │
│  3. Trigger app-delivery version bump         │
└──────────────────┬───────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────┐
│ app-delivery: bump-service-proxy-version.yaml │
│  bump-service-proxy.sh uses yq to update      │
│  serviceProxy.helmValues.image.tag             │
│  in k8s-dedicated-templates.yaml               │
│  - dev/staging: auto-merge                     │
│  - prod: manual approval                       │
└──────────────────┬───────────────────────────┘
                   │
                   ▼
┌──────────────────────────────────────────────┐
│ ArgoCD detects change                         │
│  → dataplane-manager reads updated config     │
│  → APPBox Controller runs ServiceProxy Task   │
│  → helm.Apply() to tidb-admin namespace       │
└──────────────────────────────────────────────┘
```

Progressive rollout: **dev** (auto) → **staging** (auto) → **prod** (manual trigger via `service-proxy-prod-cd.yml`)

## APPBox Task Integration

Source: `../dataplane-manager/pkg/controllers/appbox/task/common/service_proxy.go`

```
NewServiceProxy() ← reads DedicatedTmplConfig.ServiceProxy
  │
  ├─ Create()
  │    ├─ optionally reads audit config from kong configmap
  │    └─ helm.Apply() with merged values
  │
  └─ PostCreate()
       └─ EnsureChartDeploymentReady()
```

If `chartPath == ""` in config, deployment is skipped entirely (config-driven toggle).

## Configuration in app-delivery

Templates live in `app-delivery` repo:
- Per-environment configs: `{env}/nextgen-regional-control-plane/dataplane-manager/envs/{cloud}-{env}-{region}-{pool}/config/k8s-dedicated-templates.yaml`
- Variant templates: `{env}/nextgen-regional-control-plane/dataplane-manager/variants/{env}-{cloud}/config/k8s-dedicated-templates_tmpl.yaml`

Key fields under `serviceProxy`:
- `helmValues.image.tag`: commit SHA tag, updated by CI bump script
- `releaseName`: `service-proxy`
- `namespace`: `tidb-admin`
