feat: add development kubernetes mtls overlay

This commit is contained in:
youfak 2026-08-07 18:02:27 +08:00
parent 2124523cef
commit 4f49473cdd
21 changed files with 543 additions and 15 deletions

View File

@ -22,10 +22,13 @@ jobs:
deployment:
runs-on: ubuntu-latest
env:
PROXY_POOL_GATEWAY_USERNAME: ci-gateway-user
PROXY_POOL_GATEWAY_PASSWORD: ci-gateway-password
PROXY_POOL_EXTRACT_TOKEN: ci-extract-token
PROXY_POOL_ADMIN_TOKEN: ci-admin-token
PROXY_POOL_CONFIG_FINGERPRINT_KEY: ci-config-fingerprint-key-at-least-32-bytes
PROXY_POOL_POSTGRES_URL: postgres://ci:ci@postgres.example:5432/proxy_pool?sslmode=verify-full
PROXY_POOL_REDIS_URL: rediss://:ci@redis.example:6379/0
PROVIDER_A_TOKEN: ci-provider-a-token
PROVIDER_B_TOKEN: ci-provider-b-token
steps:
@ -34,6 +37,10 @@ jobs:
run: docker compose -f deploy/docker-compose.yml config --quiet
- name: Render Kubernetes base
run: kubectl kustomize deploy/kubernetes/base > /dev/null
- name: Render Kubernetes development mTLS overlay
run: kubectl kustomize deploy/kubernetes/overlays/development-mtls > /dev/null
- name: Validate development mTLS configuration
run: go run ./deploy/tools/configcheck deploy/kubernetes/overlays/development-mtls/config.yaml
test:
strategy:

View File

@ -164,7 +164,7 @@ go run ./deploy/tools/configcheck deploy/config/local.yaml
```
`package-docs.ps1` 默认生成被忽略的 `dist/proxy-pool-docs-v1.0.zip`;包内包含 README、
`docs/`、图表、OpenAPI 和 Proto 契约,并以 `manifest.json` 记录 Git revision、文件大小和
`docs/`、图表、OpenAPI、Proto 契约和部署手册,并以 `manifest.json` 记录 Git revision、文件大小和
SHA-256。可使用 `-Version vMAJOR.MINOR[.PATCH]``-OutputPath OUTPUT.zip` 生成指定交付物。
`benchmark-gateway.ps1` 固定执行一次 100k 索引调度、Routing Round Robin 和 Snapshot Apply
微基准,并把版本与原始输出写入 `dist/gateway-benchmarks.txt`;它用于回归比较,不构成

View File

@ -14,9 +14,11 @@ SPIFFE URI 证书,私钥只写入被忽略的 `deploy/.control-plane-tls/`。
docker compose -f deploy/docker-compose.yml up -d --build
```
Kubernetes Base 仍保持 `controlPlane.enabled: false`,并保留 `checker.yaml` 作为
环境 Overlay 模板。生产 Overlay 必须为每个弹性 Gateway/Checker 工作负载配置唯一
身份与证书轮换,不能复用 Compose 的固定开发证书。
Kubernetes Base 仍保持 `controlPlane.enabled: false`。`kubernetes/overlays/development-mtls`
启用单副本 Controller/Gateway/Checker mTLS 拓扑,挂载三组外部 TLS Secret并固定
`gateway-a`、`checker-a` 身份。具体创建 Secret 和部署步骤见
[development mTLS overlay](kubernetes/overlays/development-mtls/README.md)。生产 Overlay
必须为每个弹性 Gateway/Checker 工作负载配置唯一身份与证书轮换,不能复用固定开发证书。
当前可执行验证:
@ -24,6 +26,7 @@ Kubernetes Base 仍保持 `controlPlane.enabled: false`,并保留 `checker.yam
docker compose -f deploy/docker-compose.yml config --quiet
docker compose -f deploy/docker-compose.test.yml config --quiet
kubectl kustomize deploy/kubernetes/base | Out-Null
kubectl kustomize deploy/kubernetes/overlays/development-mtls | Out-Null
go run ./deploy/tools/configcheck deploy/config/local.yaml
```

View File

@ -31,6 +31,8 @@ func TestCIValidatesProtocolAndDeploymentAssets(t *testing.T) {
"./scripts/verify-proto.ps1",
"docker compose -f deploy/docker-compose.yml config --quiet",
"kubectl kustomize deploy/kubernetes/base",
"kubectl kustomize deploy/kubernetes/overlays/development-mtls",
"go run ./deploy/tools/configcheck deploy/kubernetes/overlays/development-mtls/config.yaml",
} {
if !strings.Contains(workflow, required) {
t.Errorf("ci workflow does not validate %q", required)

View File

@ -0,0 +1,56 @@
# Kubernetes development mTLS overlay
该 Overlay 在 base 资源之上启用 Controller 控制面 mTLS并启动一个固定身份的 Gateway
和 Checker。它只用于开发或预发布的单副本控制面验证不是生产弹性身份方案。
## Prepare certificates
先生成未提交的开发证书。输出目录必须为空;生成器的 `controller` 证书包含
`DNS:controller`Overlay 中的客户端也只拨号 `controller:8443`
```powershell
./scripts/generate-local-controlplane-certs.ps1
kubectl apply -f deploy/kubernetes/base/namespace.yaml
```
将生成的三组证书写入 Kubernetes Secret。下面的命令可重复执行只更新对应 Secret
```powershell
kubectl -n proxy-pool create secret generic proxy-pool-controlplane-server-tls `
--from-file=tls.crt=deploy/.control-plane-tls/controller/tls.crt `
--from-file=tls.key=deploy/.control-plane-tls/controller/tls.key `
--from-file=ca.crt=deploy/.control-plane-tls/controller/ca.crt `
--dry-run=client -o yaml | kubectl apply -f -
kubectl -n proxy-pool create secret generic proxy-pool-controlplane-gateway-tls `
--from-file=tls.crt=deploy/.control-plane-tls/gateway-a/tls.crt `
--from-file=tls.key=deploy/.control-plane-tls/gateway-a/tls.key `
--from-file=ca.crt=deploy/.control-plane-tls/gateway-a/ca.crt `
--dry-run=client -o yaml | kubectl apply -f -
kubectl -n proxy-pool create secret generic proxy-pool-controlplane-checker-tls `
--from-file=tls.crt=deploy/.control-plane-tls/checker-a/tls.crt `
--from-file=tls.key=deploy/.control-plane-tls/checker-a/tls.key `
--from-file=ca.crt=deploy/.control-plane-tls/checker-a/ca.crt `
--dry-run=client -o yaml | kubectl apply -f -
```
另行从私密配置系统创建 `proxy-pool-secrets`。可参考 base 目录的
`secret.example.yaml`但不要把实际数据库、Redis、Provider 或 API 凭据写入 Git。
## Deploy
```powershell
kubectl apply -k deploy/kubernetes/overlays/development-mtls
kubectl -n proxy-pool rollout status deployment/proxy-controller --timeout=5m
kubectl -n proxy-pool rollout status deployment/proxy-gateway --timeout=5m
kubectl -n proxy-pool rollout status deployment/proxy-checker --timeout=5m
```
Overlay 的 Gateway 固定为 `worker_id=gateway-a`Checker 固定为
`checker_id=checker-a`,并把 Gateway HPA 限制为 `minReplicas=maxReplicas=1`
因此不得在此 Overlay 上增加副本数或放宽 HPA重复使用同一 Worker 身份会破坏
session、ownership 和证书角色边界。
生产环境需要由工作负载身份系统为每个副本签发独立、可轮换的证书,并将该副本的
身份注入 `worker_id`、`instance_id`、Gateway Client TLS 或 Checker Client TLS。

View File

@ -0,0 +1,24 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: checker-control-plane
namespace: proxy-pool
spec:
podSelector:
matchLabels: {app.kubernetes.io/name: proxy-checker}
policyTypes: [Ingress, Egress]
ingress:
- from:
- namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: monitoring}}
ports: [{port: 9090, protocol: TCP}]
egress:
- to:
- namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: kube-system}}
ports: [{port: 53, protocol: UDP}, {port: 53, protocol: TCP}]
- to:
- podSelector: {matchLabels: {app.kubernetes.io/name: proxy-controller}}
ports: [{port: 8443, protocol: TCP}]
- to:
- ipBlock:
cidr: 0.0.0.0/0
except: [10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16]

View File

@ -0,0 +1,24 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: proxy-checker
namespace: proxy-pool
spec:
replicas: 1
template:
spec:
containers:
- name: checker
env:
- {name: PROXY_POOL_CONTROL_PLANE_ADDRESS, value: controller:8443}
- {name: PROXY_POOL_CHECKER_ID, value: checker-a}
- {name: PROXY_POOL_CHECKER_INSTANCE_ID, value: checker-a-1}
- {name: PROXY_POOL_CHECKER_MAX_IN_FLIGHT, value: "200"}
volumeMounts:
- name: controlplane-checker-tls
mountPath: /run/proxy-pool-tls/client
readOnly: true
volumes:
- name: controlplane-checker-tls
secret:
secretName: proxy-pool-controlplane-checker-tls

View File

@ -0,0 +1,65 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: proxy-checker
namespace: proxy-pool
labels: {app.kubernetes.io/name: proxy-checker, app.kubernetes.io/part-of: proxy-pool}
spec:
replicas: 1
minReadySeconds: 5
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate: {maxUnavailable: 1, maxSurge: 1}
selector:
matchLabels: {app.kubernetes.io/name: proxy-checker}
template:
metadata:
labels: {app.kubernetes.io/name: proxy-checker, app.kubernetes.io/part-of: proxy-pool}
annotations: {prometheus.io/scrape: "true", prometheus.io/port: "9090", prometheus.io/path: /metrics}
spec:
serviceAccountName: proxy-pool
automountServiceAccountToken: false
terminationGracePeriodSeconds: 45
securityContext: {runAsNonRoot: true, seccompProfile: {type: RuntimeDefault}}
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector: {matchLabels: {app.kubernetes.io/name: proxy-checker}}
containers:
- name: checker
image: REGISTRY/proxy-pool:VERSION
imagePullPolicy: IfNotPresent
command: [proxy-checker]
env:
- {name: PROXY_POOL_CONFIG, value: /etc/proxy-pool/config.yaml}
envFrom:
- secretRef: {name: proxy-pool-secrets}
ports:
- {name: metrics, containerPort: 9090}
readinessProbe:
httpGet: {path: /readyz, port: metrics}
periodSeconds: 5
timeoutSeconds: 2
livenessProbe:
httpGet: {path: /livez, port: metrics}
periodSeconds: 10
timeoutSeconds: 2
lifecycle:
preStop: {exec: {command: [sh, -c, "sleep 3"]}}
resources:
requests: {cpu: "1", memory: 512Mi}
limits: {cpu: "2", memory: 1Gi}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: {drop: [ALL]}
volumeMounts:
- {name: config, mountPath: /etc/proxy-pool, readOnly: true}
- {name: tmp, mountPath: /tmp}
volumes:
- name: config
configMap: {name: proxy-pool-config}
- name: tmp
emptyDir: {sizeLimit: 64Mi}

View File

@ -0,0 +1,216 @@
version: 1
security:
requireProtectionOnPublicListen: true
gateway:
enabled: true
listen: 0.0.0.0:8080
access:
allowCIDRs: [0.0.0.0/0]
trustedProxies: []
auth:
mode: usernamePassword
username: "${PROXY_POOL_GATEWAY_USERNAME}"
password: "${PROXY_POOL_GATEWAY_PASSWORD}"
limits:
maxConcurrentConnections: 20000
requestsPerMinutePerClient: 60000
transport:
maxIdleConns: 20000
maxIdleConnsPerHost: 32
maxConnsPerHost: 32
tunnelBufferBytes: 32768
retry:
maxAttempts: 2
retryMethods: [GET, HEAD]
destinationPolicy:
denyPrivateNetworks: true
denyLoopback: true
denyLinkLocal: true
denyCIDRs: [169.254.169.254/32]
distribution:
enabled: true
listen: 0.0.0.0:8081
access:
allowCIDRs: [10.0.0.0/8]
trustedProxies: [10.0.0.0/8]
auth:
mode: apiKey
header: X-API-Key
token: "${PROXY_POOL_EXTRACT_TOKEN}"
limits:
requestsPerMinute: 6000
requestsPerMinutePerClient: 600
clientIdentification:
mode: sourceIP
extraction:
fulfillment: partial
maxCountPerRequest: 100
minRemainingTTL: 30s
maxHealthCheckAge: 30s
reserveForGateway: 1000
idempotencyTTL: 5m
admin:
enabled: true
listen: 0.0.0.0:8082
access:
allowCIDRs: [10.0.0.0/8]
auth:
mode: apiKey
header: X-Admin-Key
token: "${PROXY_POOL_ADMIN_TOKEN}"
controlPlane:
enabled: true
listen: 0.0.0.0:8443
protocolVersion: 1
heartbeatInterval: 10s
sessionTTL: 30s
maxStaleAge: 30s
maxMessageBytes: 4194304
maxRuntimeCounters: 100000
maxConcurrentStreams: 1000
tls:
mode: mtls
certFile: /run/proxy-pool-tls/server/tls.crt
keyFile: /run/proxy-pool-tls/server/tls.key
clientCAFile: /run/proxy-pool-tls/server/ca.crt
trustDomain: proxy-pool.local
environment: development
gatewayTLS:
certFile: /run/proxy-pool-tls/client/tls.crt
keyFile: /run/proxy-pool-tls/client/tls.key
serverCAFile: /run/proxy-pool-tls/client/ca.crt
checkerTLS:
certFile: /run/proxy-pool-tls/client/tls.crt
keyFile: /run/proxy-pool-tls/client/tls.key
serverCAFile: /run/proxy-pool-tls/client/ca.crt
metrics:
enabled: true
listen: 0.0.0.0:9090
storage:
postgresURL: "${PROXY_POOL_POSTGRES_URL}"
redisURL: "${PROXY_POOL_REDIS_URL}"
routing:
- name: gateway-default
enabled: true
purpose: gateway
upstreams: [provider-a, provider-b]
strategy:
type: sequential
switchAfterEmptyFetch: 5
endBehavior: stayLast
onUnavailable:
action: reject
- name: extract-default
enabled: true
purpose: extract
upstreams: [provider-a, provider-b]
strategy:
type: sequential
switchAfterEmptyFetch: 5
endBehavior: stayLast
onUnavailable:
action: reject
upstreams:
provider-a:
enabled: true
exposure: [gateway, extract]
provider:
billingMode: fetch
protocols: [http]
api:
url: https://provider-a.invalid/api/proxies
method: GET
auth:
type: apiKey
location: header
name: Authorization
value: "${PROVIDER_A_TOKEN}"
template: '{{ . }}'
proxyAuth:
type: response
pool:
maxSize: 5000
shrinkDelay: 30s
capacity:
maxConcurrencyPerProxy: 20
refill:
reconcileInterval: 1s
minimumAvailableSlots: 8000
targetAvailableSlots: 12000
lifecycle:
ttl: 5m
allocationSafetyMargin: 20s
fetch:
estimatedIPsPerCall: 100
requestInterval: 1s
timeout: 3s
maxAttempts: 3
maxInFlight: 1
maxTotal: 100000
maxResponseBytes: 4194304
templateTimeout: 100ms
retry: {initial: 500ms, max: 30s, jitter: 20}
check:
interval: 30s
jitter: 20
maxInFlight: 200
timeout: 3s
maxAttempts: 2
maxConsecutiveFailures: 3
urls: [https://example.com/]
provider-b:
enabled: true
exposure: [gateway, extract]
provider:
billingMode: fetch
protocols: [http]
api:
url: https://provider-b.invalid/api/proxies
method: GET
auth:
type: apiKey
location: header
name: Authorization
value: "${PROVIDER_B_TOKEN}"
template: '{{ . }}'
proxyAuth:
type: response
pool:
maxSize: 5000
shrinkDelay: 30s
capacity:
maxConcurrencyPerProxy: 20
refill:
reconcileInterval: 1s
minimumAvailableSlots: 8000
targetAvailableSlots: 12000
lifecycle:
ttl: 5m
allocationSafetyMargin: 20s
fetch:
estimatedIPsPerCall: 100
requestInterval: 1s
timeout: 3s
maxAttempts: 3
maxInFlight: 1
maxTotal: 100000
maxResponseBytes: 4194304
templateTimeout: 100ms
retry: {initial: 500ms, max: 30s, jitter: 20}
check:
interval: 30s
jitter: 20
maxInFlight: 200
timeout: 3s
maxAttempts: 2
maxConsecutiveFailures: 3
urls: [https://example.com/]

View File

@ -0,0 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: proxy-controller
namespace: proxy-pool
spec:
replicas: 1
template:
spec:
containers:
- name: controller
volumeMounts:
- name: controlplane-server-tls
mountPath: /run/proxy-pool-tls/server
readOnly: true
volumes:
- name: controlplane-server-tls
secret:
secretName: proxy-pool-controlplane-server-tls

View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: controller
namespace: proxy-pool
labels: {app.kubernetes.io/name: proxy-controller}
spec:
type: ClusterIP
selector: {app.kubernetes.io/name: proxy-controller}
ports:
- {name: control, port: 8443, targetPort: control}

View File

@ -0,0 +1,8 @@
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: proxy-gateway
namespace: proxy-pool
spec:
minReplicas: 1
maxReplicas: 1

View File

@ -0,0 +1,25 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: proxy-gateway
namespace: proxy-pool
spec:
replicas: 1
template:
spec:
containers:
- name: gateway
env:
- {name: PROXY_POOL_CONTROL_PLANE_ADDRESS, value: controller:8443}
- {name: PROXY_POOL_CLUSTER_ID, value: kubernetes-development}
- {name: PROXY_POOL_WORKER_ID, value: gateway-a}
- {name: PROXY_POOL_INSTANCE_ID, value: gateway-a-1}
- {name: PROXY_POOL_ZONE, value: kubernetes-development}
volumeMounts:
- name: controlplane-gateway-tls
mountPath: /run/proxy-pool-tls/client
readOnly: true
volumes:
- name: controlplane-gateway-tls
secret:
secretName: proxy-pool-controlplane-gateway-tls

View File

@ -0,0 +1,20 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- checker.yaml
- controller-service.yaml
- checker-networkpolicy.yaml
configMapGenerator:
- name: proxy-pool-config
namespace: proxy-pool
behavior: replace
files:
- config.yaml
generatorOptions:
disableNameSuffixHash: true
patches:
- path: controller-patch.yaml
- path: gateway-patch.yaml
- path: checker-patch.yaml
- path: gateway-hpa-patch.yaml

View File

@ -0,0 +1,39 @@
package deploy
import (
"os/exec"
"strings"
"testing"
)
func TestKubernetesDevelopmentMTLSOverlayRendersStaticWorkerIdentities(t *testing.T) {
kubectl, err := exec.LookPath("kubectl")
if err != nil {
t.Skip("kubectl is required to render the Kubernetes development mTLS overlay")
}
command := exec.Command(kubectl, "kustomize", "kubernetes/overlays/development-mtls")
command.Dir = "."
payload, err := command.CombinedOutput()
if err != nil {
t.Fatalf("render development mTLS overlay: %v\n%s", err, payload)
}
rendered := string(payload)
for _, required := range []string{
"mode: mtls",
"trustDomain: proxy-pool.local",
"value: controller:8443",
"value: gateway-a",
"value: checker-a",
"secretName: proxy-pool-controlplane-server-tls",
"secretName: proxy-pool-controlplane-gateway-tls",
"secretName: proxy-pool-controlplane-checker-tls",
"name: proxy-checker",
"name: checker-control-plane",
"minReplicas: 1",
"maxReplicas: 1",
} {
if !strings.Contains(rendered, required) {
t.Errorf("development mTLS overlay does not render %q", required)
}
}
}

View File

@ -374,7 +374,9 @@ OpenAPI 结构契约由 Go 测试在双平台 CI 执行。
Gateway 热路径。`platform/logging` 以 JSON `slog` 输出进程级致命错误字段、URL
用户信息、查询 Secret 和错误对象均经过脱敏,且不在请求热路径逐条写日志。
CI 另有独立 Deployment job在占位凭据下渲染 Compose并使用 `kubectl kustomize`
渲染 Kubernetes base它不启动容器、不访问真实存储或密钥。
渲染 Kubernetes base 和单副本 development mTLS Overlay它不启动容器、不访问真实存储或密钥。
development Overlay 已挂载独立 Controller/Gateway/Checker TLS Secret、启用 Checker 和最小
网络策略,但固定 `gateway-a`、`checker-a` 身份且 HPA 锁为单副本,不能代替生产证书轮换。
## Task 14: Documentation, Examples, and Diagrams
@ -386,7 +388,7 @@ CI 另有独立 Deployment job在占位凭据下渲染 Compose并使用 `k
- [x] Provide at least 30 Mermaid architecture, flow, sequence, state, and failure diagrams.
- [x] Generate `proxy-pool-docs-v1.0.zip` from versioned documentation assets.
`scripts/package-docs.ps1` 会将 README、`docs/`、图表、OpenAPI 与 Proto 契约复制至临时目录,
`scripts/package-docs.ps1` 会将 README、`docs/`、图表、OpenAPI、Proto 契约与部署手册复制至临时目录,
生成包含 Git revision、文件大小和 SHA-256 的 `manifest.json`,再以临时 ZIP 原子替换目标。
默认输出为被 Git 忽略的 `dist/proxy-pool-docs-v1.0.zip`Go 回归测试实际执行脚本并校验归档内容。

View File

@ -76,6 +76,8 @@ func TestPackageDocsCreatesTraceableArchive(t *testing.T) {
}
for _, required := range []string{
"README.md",
"deploy/README.md",
"deploy/kubernetes/overlays/development-mtls/README.md",
"docs/design/architecture.md",
"docs/operations/runbook.md",
"diagrams/README.md",

View File

@ -103,8 +103,10 @@ Windows 环境为 `CGO_ENABLED=0` 且没有 C 编译器,`go test -race` 在本
CI 已配置 Linux race job。PostgreSQL 18 和 Redis 8.2 的隔离 Adapter fixture
已经运行;本地 Compose 已声明 Controller、两个独立 Gateway 身份和一个 Checker 的
mTLS 运行拓扑并由配置、证书、命令装配和部署契约测试覆盖。Kubernetes base 刻意不直接
启用 Checker因为生产环境必须通过 Overlay 为每个弹性 Worker 注入唯一身份与证书;
该 Overlay 和容器端到端启动仍待具备镜像网络的环境验证。
启用 Checker`development-mtls` Overlay 已为单副本 Controller、Gateway 和 Checker
提供固定开发身份、mTLS Secret 挂载、最小出站 NetworkPolicy 与渲染/配置契约验证。
生产环境仍必须通过独立 Overlay 为每个弹性 Worker 注入唯一、可轮换的身份与证书,且
容器端到端启动仍待具备镜像网络的环境验证。
## 3. 后续实现范围
@ -116,8 +118,9 @@ mTLS 运行拓扑,并由配置、证书、命令装配和部署契约测试覆
与 p99 告警;仍需代表性环境的流量压测和容量报告。
3. Provider 长期凭据回收与累计额度的生产运营策略仍需结合实际供应商合同、失效时间和
密钥平台完成演练。
4. Kubernetes 需要按工作负载身份系统提供 mTLS Overlay、证书轮换、唯一 Worker ID 和
Checker 出站 NetworkPolicybase 清单不假定或伪造这些生产环境能力。
4. Kubernetes 的开发 mTLS Overlay 已覆盖单副本固定身份和 Checker 出站
NetworkPolicy生产环境仍需要按工作负载身份系统提供证书轮换、每副本唯一 Worker ID
与可弹性扩缩容的身份注入base 清单不假定或伪造这些能力。
5. Redis/PostgreSQL 故障转移、控制面断线恢复、Snapshot 回滚、Drain 回收和 Extract
库存不足的完整故障演练。
6. 10k 稳态、100k 峰值、CONNECT 活跃连接和建连速率的代表性集群负载测试。

View File

@ -9,7 +9,7 @@
|---|---|---|---|
| ARCH-001 | 数据面 Worker 与控制面 Controller 分离 | 1-70 | 包、协议和部署拓扑已分离Controller 已运行 Worker Register/Watch/ACK/Runtime/Outcome 与 Checker Observation gRPC并发布 Proxy/Gateway Routing/按引用去重凭据完整快照Checker 任务流已具备有界领取、租约栅栏和任务期凭据契约。Gateway 已将快照编译为同版本动态 View并由独立进程维护控制面会话。`proxy-checker` 与 Redis BASIC/EGRESS/TARGET 共享任务运行态、`proxy-loadgen` 有界 HTTP/CONNECT/Extract 校验场景均已实现 |
| ARCH-002 | 热路径只做认证、本地路由和网络转发 | 1-70, 380-430 | Gateway bootstrap 集成测试验证启动期控制面会话与快照就绪HTTP 请求只走本地 Snapshot/DispatchOutcome 仅写入有界非阻塞本地队列,代表性性能剖析待完成 |
| ARCH-003 | Gateway、Distribution、Admin、Metrics 独立入口 | 8904-8958 | Controller 命令已装配 Distribution/Admin/Metrics 三个独立监听及联动停机Gateway 命令已装配代理与 Metrics 监听。本地 Compose 已声明 Controller/Gateway/Checker mTLS 拓扑Kubernetes 的工作负载身份 Overlay 仍待环境实现 |
| ARCH-003 | Gateway、Distribution、Admin、Metrics 独立入口 | 8904-8958 | Controller 命令已装配 Distribution/Admin/Metrics 三个独立监听及联动停机Gateway 命令已装配代理与 Metrics 监听。本地 Compose 已声明 Controller/Gateway/Checker mTLS 拓扑Kubernetes `development-mtls` Overlay 已通过渲染与配置契约验证单副本固定身份链路,生产工作负载身份仍待环境实现 |
| ARCH-004 | Controller 集中 Provider 获取与切换 | 1403-1580 | Redis Leader、动态 Provider Supervisor 与 Bootstrap 生产装配已完成;静态配置与 Admin 管理态共同决定 Provider 启停,停用策略以 Upstream revision 栅栏驱动既有 ownership DrainRouting 切换会向本进程 Worker 快照流广播完整刷新,多副本按定时刷新与权威 HMAC 指纹/revision 栅栏收敛并拒绝旧配置换主 |
| ARCH-005 | 100k QPS 峰值使用多 Worker 集群 | 当前会话 | 未验证设计目标;待代表性集群负载报告 |

View File

@ -31,7 +31,9 @@ $sources = @(
"docs",
"diagrams",
"api/openapi",
"api/proto"
"api/proto",
"deploy/README.md",
"deploy/kubernetes/overlays/development-mtls/README.md"
)
$stagingRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("proxy-pool-docs-" + [Guid]::NewGuid().ToString("N"))
$temporaryArchive = ""

View File

@ -75,8 +75,8 @@
与 PostgreSQL 18 的隔离 Adapter fixture 已运行。Docker Desktop 缺少镜像 HTTPS
代理配置,未能在本机完成 Compose 容器端到端启动。
- Controller、Gateway、Checker、Loadgen、Provider Fleet、WorkerControlPlane、业务指标和
Redis 故障边界均有实现与定向测试。真实容器故障转移、Kubernetes 工作负载身份 Overlay
与代表性集群压测仍属于后续验证范围。
- `implementation-plan.md` 当前按 74 个验收项统计;验收勾选数不等同于生产就绪度。
Redis 故障边界均有实现与定向测试。Kubernetes `development-mtls` Overlay 已静态验证
单副本固定身份链路;真实容器故障转移、生产工作负载身份与代表性集群压测仍属于后续验证范围。
- `implementation-plan.md` 当前按 75 个验收项统计;验收勾选数不等同于生产就绪度。
Compose 本地 mTLS 控制面运行链已实现并通过配置、证书、单元与构建验证;受本机 Docker
Desktop 镜像 HTTPS 代理缺失影响,容器端到端启动仍待具备镜像网络的环境复核。