feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,10 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: ql3-postgres
spec:
plugins:
- name: barman-cloud.cloudnative-pg.io
isWALArchiver: true
parameters:
barmanObjectName: ql3-postgres-backup
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- scheduled-backup.yaml
patches:
- path: cluster-plugin-patch.yaml
@@ -0,0 +1,30 @@
# Example only. Copy into a private overlay and replace every placeholder.
# This resource is intentionally excluded from the Component.
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: ql3-postgres-backup
namespace: qinglong3-system
labels:
app.kubernetes.io/name: ql3-postgres
app.kubernetes.io/component: database-backup
app.kubernetes.io/part-of: qinglong3
spec:
retentionPolicy: 30d
configuration:
destinationPath: s3://REPLACE_WITH_VERSIONED_LOCKED_BUCKET/qinglong3/ql3-postgres
endpointURL: https://REPLACE_WITH_OBJECT_STORE_ENDPOINT
s3Credentials:
accessKeyId:
name: ql3-postgres-backup-object-store
key: ACCESS_KEY_ID
secretAccessKey:
name: ql3-postgres-backup-object-store
key: ACCESS_SECRET_KEY
wal:
compression: lz4
encryption: AES256
maxParallel: 2
data:
compression: lz4
encryption: AES256
@@ -0,0 +1,11 @@
# Example only. Save as kustomization.yaml in a private overlay beside a
# populated object-store.yaml. Do not apply this file directly.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../operators/cloudnative-pg
- object-store.yaml
components:
- ../../components/barman-cloud-backup
@@ -0,0 +1,20 @@
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: ql3-postgres-daily
namespace: qinglong3-system
labels:
app.kubernetes.io/name: ql3-postgres
app.kubernetes.io/component: database-backup
app.kubernetes.io/part-of: qinglong3
spec:
schedule: '0 0 0 * * *'
backupOwnerReference: self
immediate: false
suspend: false
target: prefer-standby
cluster:
name: ql3-postgres
method: plugin
pluginConfiguration:
name: barman-cloud.cloudnative-pg.io
@@ -0,0 +1,30 @@
# Optional Cluster AI durable Prompt output
This component opts the existing Cluster AI runtime into encrypted, durable
Prompt output. Apply it only together with `../cluster-ai`; the default Cluster
and default Cluster AI profiles remain live-output-only.
The runtime receives only a read-only `0440` projection of
`ql3-prompt-output-keyring/keyring.json`. It does not receive a ServiceAccount
token, Kubernetes API authority, or permission to provision, rotate, or retire
keys. The projected-keyring adapter reopens the manifest for each operation, so
Kubernetes atomic projection updates become visible without a process restart.
Before applying it:
1. Provision the namespaced `ql3-prompt-output-keyring` Secret through the
deployment platform or Secret manager. Do not commit key material or a
deployable Secret manifest to this repository.
2. Store the canonical
`qinglong/plugin-package-prompt-output-keyring@v1` document under the exact
`keyring.json` data key. Keep the active key and bounded decrypt-only history
in that one document.
3. Apply both components from a private overlay and pin the independent Cluster
AI image digest, as shown by
`../../overlays/cluster-ai-prompt-output-example/kustomization.yaml`.
4. Use the reviewed management operation for retirement. Provisioning and
active-key rotation remain deployment-plane responsibilities; the runtime
must never be granted Secret mutation authority.
The Secret must remain non-optional. A missing, malformed, writable, escaped,
or rotating-during-read keyring fails startup or the affected operation closed.
@@ -0,0 +1,26 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ql3-cluster-control
spec:
template:
spec:
containers:
- name: cluster-control
env:
- name: QL3_CLUSTER_AI_PROMPT_OUTPUT_ENABLED
value: 'true'
- name: QL3_CLUSTER_AI_PROMPT_OUTPUT_KEYRING_ROOT
value: /var/run/secrets/qinglong3/ai/prompt-output-keyring
volumeMounts:
- name: cluster-ai-prompt-output-keyring
mountPath: /var/run/secrets/qinglong3/ai/prompt-output-keyring
readOnly: true
volumes:
- name: cluster-ai-prompt-output-keyring
secret:
secretName: ql3-prompt-output-keyring
defaultMode: 288
items:
- key: keyring.json
path: keyring.json
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
patches:
- path: deployment-patch.yaml
@@ -0,0 +1,26 @@
# Optional Cluster AI component
This component replaces only the Cluster Control image with the explicit
`runtime-ai` target. The default Cluster deployment and image remain AI-free.
Before applying it:
1. Replace the example Project, provider URL, model and policy revision in
`provider-authority-configmap.yaml`; keep `authority.json` canonical,
one-line JSON with one trailing newline.
2. Bind the same Project/provider to a canonical SecretRef through the
append-only model-provider credential catalog.
3. Project each provider authorization value under the lowercase SHA-256 of
its canonical SecretRef. Use `provider-secrets.example.yaml` only as a
shape reference and provision the real Secret through a Secret manager.
4. Build and publish the Docker `runtime-ai` target, then pin its independent
digest in a private overlay based on `private-overlay.example.yaml`.
The component mounts ConfigMap and Secret volumes read-only with mode `0440`,
does not mount a ServiceAccount token, and grants no Kubernetes API access.
It remains live-output-only by default. Compose the separate
`../cluster-ai-prompt-output` component only when encrypted durable Prompt
output and its externally provisioned keyring are required.
Each replica adds a separate, bounded PostgreSQL runtime pool of four
connections by default; tune `QL3_CLUSTER_AI_DATABASE_MAX_CONNECTIONS` and
`QL3_CLUSTER_AI_MAX_CONCURRENT` together for the cluster's resource budget.
@@ -0,0 +1,42 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ql3-cluster-control
spec:
template:
spec:
containers:
- name: cluster-control
image: qinglong3-cluster-control-ai:3.0.0-alpha.0
env:
- name: QL3_CLUSTER_AI_ENABLED
value: "true"
- name: QL3_CLUSTER_AI_PROVIDER_AUTHORITY_FILE
value: /var/run/qinglong3/ai/provider-authority/authority.json
- name: QL3_CLUSTER_AI_SECRET_ROOT
value: /var/run/secrets/qinglong3/ai/provider-secrets
- name: QL3_CLUSTER_AI_MAX_CONCURRENT
value: "4"
- name: QL3_CLUSTER_AI_RECOVERY_LIMIT
value: "32"
- name: QL3_CLUSTER_AI_DATABASE_MAX_CONNECTIONS
value: "4"
volumeMounts:
- name: cluster-ai-provider-authority
mountPath: /var/run/qinglong3/ai/provider-authority
readOnly: true
- name: cluster-ai-provider-secrets
mountPath: /var/run/secrets/qinglong3/ai/provider-secrets
readOnly: true
volumes:
- name: cluster-ai-provider-authority
configMap:
name: ql3-cluster-ai-provider-authority
defaultMode: 288
items:
- key: authority.json
path: authority.json
- name: cluster-ai-provider-secrets
secret:
secretName: ql3-cluster-ai-provider-secrets
defaultMode: 288
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- provider-authority-configmap.yaml
patches:
- path: deployment-patch.yaml
@@ -0,0 +1,15 @@
# Example only. Save as kustomization.yaml in a private overlay and replace the
# digest with the independently verified runtime-ai image digest.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
components:
- ../../components/cluster-ai
images:
- name: qinglong3-cluster-control-ai
newName: registry.example.com/qinglong/qinglong3-cluster-control-ai
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
@@ -0,0 +1,11 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: ql3-cluster-ai-provider-authority
labels:
app.kubernetes.io/name: ql3-cluster-control
app.kubernetes.io/component: control-plane-ai
app.kubernetes.io/part-of: qinglong3
data:
authority.json: |
{"schema":"qinglong/projected-model-gateway-authority@v1","providers":[{"type":"openai-compatible","baseUrl":"https://models.example.invalid/v1/","allowPlaintextLoopback":false,"maxResponseBytes":1048576}],"projects":[{"projectId":"replace-project-id","policy":{"revision":"replace-policy-v1","allowedProviders":["openai-compatible"],"allowedModels":["replace-model-id"],"maxInputBytes":65536,"maxOutputBytes":1048576,"maxOutputTokens":4096,"maxTotalTokens":32768,"maxCostMicros":null,"priceRevision":null}}]}
@@ -0,0 +1,11 @@
# Example only. Populate through a Secret manager and never commit real values.
# The data key is sha256(canonical SecretRef); the matching catalog binding is:
# qlsecret:v1:eyJwcm9qZWN0SWQiOiJyZXBsYWNlLXByb2plY3QtaWQiLCJuYW1lIjoib3BlbmFpLWNvbXBhdGlibGUtdG9rZW4ifQ
apiVersion: v1
kind: Secret
metadata:
name: ql3-cluster-ai-provider-secrets
namespace: qinglong3-system
type: Opaque
stringData:
2ac34db919c697fd198d1a4fdfd90f69d9fa58c363c7ce5c8e4ca113413fbc6b: REPLACE_WITH_PROVIDER_AUTHORIZATION_VALUE