diff --git a/k8s/README.md b/k8s/README.md index 7b02a48..9ad9ac9 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -1,80 +1,100 @@ -# Kubernetes Deployment Files +# High Command Kubernetes (Kustomize) -This directory contains Kubernetes manifests for deploying the High Command stack (UI, API, MCP, Gateway, Cloudflare Tunnel). +Kustomize-based deployment for the High Command stack: UI, API, Poller, PostgreSQL, Gateway, Cloudflare Tunnel. -## Architecture +## Structure -Traffic flow: **Cloudflare Tunnel** → **Envoy Gateway** → **HTTPRoute** → UI/API/MCP. No nginx Ingress. - -## UI Files - -- `ui-deployment-blue.yaml`, `ui-deployment-green.yaml` - Blue/green deployments -- `ui-service.yaml` - Service routing -- `ui-pdb.yaml` - Pod Disruption Budget - -## Full Stack Files +``` +k8s/ +├── base/ # Base resources by component +│ ├── api/ # API deployments (blue/green), service, pdb +│ ├── ui/ # UI deployments (blue/green), service, pdb +│ ├── poller/ # Data collector +│ ├── postgres/ # CloudNativePG cluster, pooler +│ ├── gateway/ # Envoy Gateway, HTTPRoute, certificate +│ ├── mcp/ # MCP service alias, ReferenceGrant +│ └── cloudflare/ # Cloudflare Tunnel deployment +├── overlays/ +│ └── default/ # Default overlay (no patches) +├── docs/ +│ └── CLOUDFLARE_TUNNEL.md # Tunnel setup guide +└── README.md +``` -- `api-deployment-blue.yaml`, `api-deployment-green.yaml` - API deployments -- `api-service.yaml`, `api-pdb.yaml` - API service -- `httproute.yaml` - Gateway API HTTPRoute (/api, /claude, /mcp, /) -- `gateway.yaml`, `gatewayclass.yaml`, `gateway-certificate.yaml` - Envoy Gateway -- `gateway-tunnel-service.yaml` - Alias for Cloudflare Tunnel → Gateway -- `cloudflared-tunnel-deployment.yaml` - Cloudflare Tunnel pod -- `mcp-service.yaml`, `mcp-referencegrant.yaml`, `referencegrant.yaml` - MCP routing +## Quick Start -See `CLOUDFLARE_TUNNEL.md` for tunnel setup. +```bash +# 1. Create secrets (required before deploy) +kubectl create secret generic high-command-postgres-credentials \ + --from-literal=username=highcommand \ + --from-literal=password='$(openssl rand -base64 32)' \ + -n high-command -## Secrets +kubectl create secret generic high-command-api-secrets \ + --from-literal=database-url='postgresql://user:pass@high-command-postgres-pooler.high-command.svc.cluster.local:5432/highcommand' \ + --from-literal=claude-api-key='sk-ant-...' \ + -n high-command -**No secrets are stored in these files.** +kubectl create secret generic high-command-poller-secrets \ + --from-literal=database-url='postgresql://user:pass@high-command-postgres-pooler.high-command.svc.cluster.local:5432/highcommand' \ + --from-literal=helldivers-api-base='https://api.helldivers2.dev/api/v1' \ + --from-literal=helldivers-api-client-name='High Command' \ + --from-literal=helldivers-api-contact='lee@fullmetal.dev' \ + --from-literal=scrape-interval='300' \ + -n high-command -**API secrets** (required): `database-url` and optionally `claude-api-key`: +# 2. Deploy +kubectl apply -k overlays/default -```bash -kubectl create secret generic high-command-api-secrets \ - --from-literal=database-url='postgresql://user:password@high-command-postgres-rw.high-command.svc.cluster.local:5432/highcommand' \ - --from-literal=claude-api-key='sk-ant-api03-...' \ - -n high-command +# 3. Cloudflare Tunnel (optional, see docs/CLOUDFLARE_TUNNEL.md) +kubectl create secret generic cloudflared-tunnel-credentials --from-literal=token='...' -n high-command +kubectl apply -k overlays/default ``` -See `api-secrets-example.yaml` for details. +## Commands -## Cloudflare +```bash +# Build manifests (dry-run) +kubectl kustomize overlays/default -The `../cloudflare/` folder contains the tunnel Dockerfile. GitLab CI builds the cloudflared-tunnel image from `cloudflare/Dockerfile`. +# Deploy +kubectl apply -k overlays/default -## Environment Variables +# Delete +kubectl delete -k overlays/default +``` -The UI uses environment variables at build time (Vite). These are configured in: -- `ui-deployment-blue.yaml` -- `ui-deployment-green.yaml` +## Secrets Examples -Current environment variables: -- `NODE_ENV=production` -- `PORT=3000` +Secret templates are in `base/*/` with `-example` suffix. Create secrets with `kubectl create`, do not apply example files: -For build-time variables (e.g., `VITE_CLAUDE_API_KEY`), they must be set during the Docker build process, not at runtime. +- `base/api/api-secrets-example.yaml` +- `base/ui/ui-secrets-example.yaml` +- `base/poller/poller-secrets-example.yaml` +- `base/postgres/postgres-credentials-example.yaml` +- `base/cloudflare/cloudflared-tunnel-secrets-example.yaml` -## Deployment +## Database: Use PgBouncer Pooler -Deploy all resources: +API and poller use `high-command-postgres-pooler` to avoid exhausting Postgres `max_connections`. The pooler must be deployed (`postgres-pooler-example.yaml`) before creating secrets. +**To migrate existing deployment** from direct Postgres to pooler: ```bash -kubectl apply -f k8s/ +kubectl delete secret high-command-api-secrets high-command-poller-secrets -n high-command +# Recreate with pooler URL (see Quick Start above) +kubectl rollout restart deployment/high-command-api-blue deployment/high-command-api-green deployment/high-command-poller -n high-command ``` -Switch between blue/green by updating the service selector in `ui-service.yaml`: +## Prerequisites -```yaml -selector: - app: high-command-ui - version: blue # or green -``` +- **CloudNativePG operator** – for PostgreSQL cluster +- **Envoy Gateway** – for Gateway API +- **cert-manager** – for TLS certificates +- **Namespace** – `kubectl create namespace high-command` (or let apply create it) -Or use the annotation: +## Blue/Green Switching ```bash -kubectl annotate service high-command-ui \ - deployment.kubernetes.io/active-version=green \ - -n high-command +kubectl patch svc high-command-ui -n high-command -p '{"spec":{"selector":{"version":"green"}}}' +kubectl patch svc high-command-api -n high-command -p '{"spec":{"selector":{"version":"green"}}}' ``` diff --git a/k8s/api-deployment-blue.yaml b/k8s/base/api/api-deployment-blue.yaml similarity index 93% rename from k8s/api-deployment-blue.yaml rename to k8s/base/api/api-deployment-blue.yaml index b873cc1..764d6b4 100644 --- a/k8s/api-deployment-blue.yaml +++ b/k8s/base/api/api-deployment-blue.yaml @@ -20,7 +20,7 @@ spec: spec: containers: - name: api - image: harbor.dataknife.net/library/high-command-api:v0.11 + image: harbor.dataknife.net/library/high-command-api:v0.21 imagePullPolicy: Always env: - name: MODE @@ -56,27 +56,27 @@ spec: protocol: TCP livenessProbe: httpGet: - path: /api/health + path: /api/livez port: http initialDelaySeconds: 30 periodSeconds: 30 - timeoutSeconds: 5 + timeoutSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /api/health port: http - initialDelaySeconds: 10 + initialDelaySeconds: 15 periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 2 + timeoutSeconds: 10 + failureThreshold: 3 resources: requests: cpu: "200m" memory: "256Mi" limits: cpu: "1000m" - memory: "1Gi" + memory: "2Gi" securityContext: runAsNonRoot: true runAsUser: 1000 diff --git a/k8s/api-deployment-green.yaml b/k8s/base/api/api-deployment-green.yaml similarity index 93% rename from k8s/api-deployment-green.yaml rename to k8s/base/api/api-deployment-green.yaml index a80ba1c..cd085f3 100644 --- a/k8s/api-deployment-green.yaml +++ b/k8s/base/api/api-deployment-green.yaml @@ -20,7 +20,7 @@ spec: spec: containers: - name: api - image: harbor.dataknife.net/library/high-command-api:v0.11 + image: harbor.dataknife.net/library/high-command-api:v0.21 imagePullPolicy: Always env: - name: MODE @@ -56,27 +56,27 @@ spec: protocol: TCP livenessProbe: httpGet: - path: /api/health + path: /api/livez port: http initialDelaySeconds: 30 periodSeconds: 30 - timeoutSeconds: 5 + timeoutSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /api/health port: http - initialDelaySeconds: 10 + initialDelaySeconds: 15 periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 2 + timeoutSeconds: 10 + failureThreshold: 3 resources: requests: cpu: "200m" memory: "256Mi" limits: cpu: "1000m" - memory: "1Gi" + memory: "2Gi" securityContext: runAsNonRoot: true runAsUser: 1000 diff --git a/k8s/api-pdb.yaml b/k8s/base/api/api-pdb.yaml similarity index 100% rename from k8s/api-pdb.yaml rename to k8s/base/api/api-pdb.yaml diff --git a/k8s/api-secrets-example.yaml b/k8s/base/api/api-secrets-example.yaml similarity index 72% rename from k8s/api-secrets-example.yaml rename to k8s/base/api/api-secrets-example.yaml index 32d8b47..f633df8 100644 --- a/k8s/api-secrets-example.yaml +++ b/k8s/base/api/api-secrets-example.yaml @@ -1,11 +1,15 @@ # API secrets - DATABASE_URL required, claude-api-key optional # Never commit real values. Create with kubectl: # +# Use PgBouncer pooler (recommended - avoids exhausting Postgres max_connections): # kubectl create secret generic high-command-api-secrets \ -# --from-literal=database-url='postgresql://user:password@high-command-postgres-rw.high-command.svc.cluster.local:5432/highcommand' \ +# --from-literal=database-url='postgresql://user:password@high-command-postgres-pooler.high-command.svc.cluster.local:5432/highcommand' \ # --from-literal=claude-api-key='sk-ant-api03-...' \ # -n high-command # +# Direct Postgres (use only if pooler not deployed): +# --from-literal=database-url='postgresql://user:password@high-command-postgres-rw.high-command.svc.cluster.local:5432/highcommand' +# # DATABASE_URL: Required. PostgreSQL connection string. # claude-api-key: Optional. For Claude UI integration via backend proxy. # diff --git a/k8s/api-service.yaml b/k8s/base/api/api-service.yaml similarity index 100% rename from k8s/api-service.yaml rename to k8s/base/api/api-service.yaml diff --git a/k8s/base/api/kustomization.yaml b/k8s/base/api/kustomization.yaml new file mode 100644 index 0000000..3f1bb16 --- /dev/null +++ b/k8s/base/api/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - api-deployment-blue.yaml + - api-deployment-green.yaml + - api-service.yaml + - api-pdb.yaml diff --git a/k8s/cloudflared-tunnel-secrets-example.yaml b/k8s/base/cloudflare/cloudflared-tunnel-secrets-example.yaml similarity index 100% rename from k8s/cloudflared-tunnel-secrets-example.yaml rename to k8s/base/cloudflare/cloudflared-tunnel-secrets-example.yaml diff --git a/k8s/base/cloudflare/kustomization.yaml b/k8s/base/cloudflare/kustomization.yaml new file mode 100644 index 0000000..d4b9f78 --- /dev/null +++ b/k8s/base/cloudflare/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - tunnel-deployment.yaml diff --git a/k8s/cloudflared-tunnel-deployment.yaml b/k8s/base/cloudflare/tunnel-deployment.yaml similarity index 100% rename from k8s/cloudflared-tunnel-deployment.yaml rename to k8s/base/cloudflare/tunnel-deployment.yaml diff --git a/k8s/gateway-certificate.yaml b/k8s/base/gateway/certificate.yaml similarity index 100% rename from k8s/gateway-certificate.yaml rename to k8s/base/gateway/certificate.yaml diff --git a/k8s/gateway.yaml b/k8s/base/gateway/gateway.yaml similarity index 100% rename from k8s/gateway.yaml rename to k8s/base/gateway/gateway.yaml diff --git a/k8s/gatewayclass.yaml b/k8s/base/gateway/gatewayclass.yaml similarity index 100% rename from k8s/gatewayclass.yaml rename to k8s/base/gateway/gatewayclass.yaml diff --git a/k8s/httproute.yaml b/k8s/base/gateway/httproute.yaml similarity index 100% rename from k8s/httproute.yaml rename to k8s/base/gateway/httproute.yaml diff --git a/k8s/base/gateway/kustomization.yaml b/k8s/base/gateway/kustomization.yaml new file mode 100644 index 0000000..18af36f --- /dev/null +++ b/k8s/base/gateway/kustomization.yaml @@ -0,0 +1,9 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - gatewayclass.yaml + - gateway.yaml + - certificate.yaml + - httproute.yaml + - tunnel-service.yaml diff --git a/k8s/gateway-tunnel-service.yaml b/k8s/base/gateway/tunnel-service.yaml similarity index 100% rename from k8s/gateway-tunnel-service.yaml rename to k8s/base/gateway/tunnel-service.yaml diff --git a/k8s/base/kustomization.yaml b/k8s/base/kustomization.yaml new file mode 100644 index 0000000..050d420 --- /dev/null +++ b/k8s/base/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +# Namespace set per-resource (most high-command, mcp-referencegrant uses mcp-servers) + +resources: + - api + - ui + - poller + - postgres + - gateway + - mcp + - cloudflare diff --git a/k8s/base/mcp/kustomization.yaml b/k8s/base/mcp/kustomization.yaml new file mode 100644 index 0000000..a9fb7be --- /dev/null +++ b/k8s/base/mcp/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - service.yaml + - referencegrant.yaml diff --git a/k8s/mcp-referencegrant.yaml b/k8s/base/mcp/referencegrant.yaml similarity index 100% rename from k8s/mcp-referencegrant.yaml rename to k8s/base/mcp/referencegrant.yaml diff --git a/k8s/mcp-service.yaml b/k8s/base/mcp/service.yaml similarity index 81% rename from k8s/mcp-service.yaml rename to k8s/base/mcp/service.yaml index beca30d..6785c4e 100644 --- a/k8s/mcp-service.yaml +++ b/k8s/base/mcp/service.yaml @@ -1,3 +1,4 @@ +# Alias for HTTPRoute to reach MCP in mcp-servers namespace apiVersion: v1 kind: Service metadata: @@ -11,6 +12,4 @@ spec: ports: - name: http port: 8000 - targetPort: 8000 protocol: TCP - sessionAffinity: None diff --git a/k8s/base/poller/deployment.yaml b/k8s/base/poller/deployment.yaml new file mode 100644 index 0000000..8333273 --- /dev/null +++ b/k8s/base/poller/deployment.yaml @@ -0,0 +1,71 @@ +# Data collector - polls Hell Divers 2 API and writes to PostgreSQL. +# Runs separately from API (API is read-only). One replica sufficient. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: high-command-poller + namespace: high-command + labels: + app: high-command-poller +spec: + replicas: 1 + selector: + matchLabels: + app: high-command-poller + template: + metadata: + labels: + app: high-command-poller + spec: + containers: + - name: poller + image: harbor.dataknife.net/library/high-command-api:v0.22 + imagePullPolicy: Always + env: + - name: MODE + value: "collector" + - name: PYTHONUNBUFFERED + value: "1" + - name: LOG_LEVEL + value: "INFO" + - name: POOL_MAX_CONN + value: "100" + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: high-command-poller-secrets + key: database-url + - name: HELLDIVERS_API_BASE + valueFrom: + secretKeyRef: + name: high-command-poller-secrets + key: helldivers-api-base + - name: HELLDIVERS_API_CLIENT_NAME + valueFrom: + secretKeyRef: + name: high-command-poller-secrets + key: helldivers-api-client-name + - name: HELLDIVERS_API_CONTACT + valueFrom: + secretKeyRef: + name: high-command-poller-secrets + key: helldivers-api-contact + - name: SCRAPE_INTERVAL + valueFrom: + secretKeyRef: + name: high-command-poller-secrets + key: scrape-interval + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "500m" + memory: "512Mi" + securityContext: + runAsNonRoot: true + runAsUser: 1000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL diff --git a/k8s/base/poller/kustomization.yaml b/k8s/base/poller/kustomization.yaml new file mode 100644 index 0000000..88a04b5 --- /dev/null +++ b/k8s/base/poller/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - deployment.yaml diff --git a/k8s/base/poller/poller-secrets-example.yaml b/k8s/base/poller/poller-secrets-example.yaml new file mode 100644 index 0000000..3952a05 --- /dev/null +++ b/k8s/base/poller/poller-secrets-example.yaml @@ -0,0 +1,21 @@ +# Poller secrets. Create with kubectl: +# Use PgBouncer pooler (recommended - avoids exhausting Postgres max_connections): +# kubectl create secret generic high-command-poller-secrets \ +# --from-literal=database-url='postgresql://user:pass@high-command-postgres-pooler.high-command.svc.cluster.local:5432/highcommand' \ +# --from-literal=helldivers-api-base='https://api.helldivers2.dev/api/v1' \ +# --from-literal=helldivers-api-client-name='High Command' \ +# --from-literal=helldivers-api-contact='lee@fullmetal.dev' \ +# --from-literal=scrape-interval='300' \ +# -n high-command +apiVersion: v1 +kind: Secret +metadata: + name: high-command-poller-secrets + namespace: high-command +type: Opaque +stringData: + database-url: "" + helldivers-api-base: "https://api.helldivers2.dev/api/v1" + helldivers-api-client-name: "High Command" + helldivers-api-contact: "lee@fullmetal.dev" + scrape-interval: "300" diff --git a/k8s/base/postgres/cluster.yaml b/k8s/base/postgres/cluster.yaml new file mode 100644 index 0000000..5fa995d --- /dev/null +++ b/k8s/base/postgres/cluster.yaml @@ -0,0 +1,25 @@ +# PostgreSQL cluster (CloudNativePG). Requires CloudNativePG operator. +# Create postgres-credentials secret first. +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: high-command-postgres + namespace: high-command +spec: + instances: 3 + bootstrap: + initdb: + database: highcommand + owner: highcommand + secret: + name: high-command-postgres-credentials + storage: + size: 10Gi + storageClass: truenas-nfs + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1000m" diff --git a/k8s/base/postgres/kustomization.yaml b/k8s/base/postgres/kustomization.yaml new file mode 100644 index 0000000..16507cd --- /dev/null +++ b/k8s/base/postgres/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - cluster.yaml + - pooler.yaml diff --git a/k8s/base/postgres/pooler.yaml b/k8s/base/postgres/pooler.yaml new file mode 100644 index 0000000..9696659 --- /dev/null +++ b/k8s/base/postgres/pooler.yaml @@ -0,0 +1,15 @@ +# PgBouncer pooler for PostgreSQL. Deploy after postgres-cluster. +apiVersion: postgresql.cnpg.io/v1 +kind: Pooler +metadata: + name: high-command-postgres-pooler + namespace: high-command +spec: + cluster: + name: high-command-postgres + instances: 2 + type: rw + pgbouncer: + poolMode: transaction + parameters: + max_client_conn: "500" \ No newline at end of file diff --git a/k8s/base/postgres/postgres-credentials-example.yaml b/k8s/base/postgres/postgres-credentials-example.yaml new file mode 100644 index 0000000..498a7db --- /dev/null +++ b/k8s/base/postgres/postgres-credentials-example.yaml @@ -0,0 +1,16 @@ +# PostgreSQL credentials. Create with kubectl before postgres-cluster: +# kubectl create secret generic high-command-postgres-credentials \ +# --from-literal=username=highcommand \ +# --from-literal=password='$(openssl rand -base64 32)' \ +# -n high-command +# +# Do not apply this file with real passwords. Use kubectl create. +apiVersion: v1 +kind: Secret +metadata: + name: high-command-postgres-credentials + namespace: high-command +type: Opaque +stringData: + username: highcommand + password: "REPLACE_VIA_KUBECTL_CREATE" diff --git a/k8s/base/ui/kustomization.yaml b/k8s/base/ui/kustomization.yaml new file mode 100644 index 0000000..768e8ad --- /dev/null +++ b/k8s/base/ui/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ui-deployment-blue.yaml + - ui-deployment-green.yaml + - ui-service.yaml + - ui-pdb.yaml diff --git a/k8s/ui-deployment-blue.yaml b/k8s/base/ui/ui-deployment-blue.yaml similarity index 100% rename from k8s/ui-deployment-blue.yaml rename to k8s/base/ui/ui-deployment-blue.yaml diff --git a/k8s/ui-deployment-green.yaml b/k8s/base/ui/ui-deployment-green.yaml similarity index 100% rename from k8s/ui-deployment-green.yaml rename to k8s/base/ui/ui-deployment-green.yaml diff --git a/k8s/ui-pdb.yaml b/k8s/base/ui/ui-pdb.yaml similarity index 100% rename from k8s/ui-pdb.yaml rename to k8s/base/ui/ui-pdb.yaml diff --git a/k8s/base/ui/ui-secrets-example.yaml b/k8s/base/ui/ui-secrets-example.yaml new file mode 100644 index 0000000..899ec6c --- /dev/null +++ b/k8s/base/ui/ui-secrets-example.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: high-command-ui-secrets + namespace: high-command +type: Opaque +stringData: + # vite-claude-api-key: Optional, for Claude. Must be set at BUILD time (Vite), not runtime. diff --git a/k8s/ui-service.yaml b/k8s/base/ui/ui-service.yaml similarity index 100% rename from k8s/ui-service.yaml rename to k8s/base/ui/ui-service.yaml diff --git a/k8s/CLOUDFLARE_TUNNEL.md b/k8s/docs/CLOUDFLARE_TUNNEL.md similarity index 87% rename from k8s/CLOUDFLARE_TUNNEL.md rename to k8s/docs/CLOUDFLARE_TUNNEL.md index 29d0e15..6c753ff 100644 --- a/k8s/CLOUDFLARE_TUNNEL.md +++ b/k8s/docs/CLOUDFLARE_TUNNEL.md @@ -22,11 +22,14 @@ Use the token from the Docker command in the Cloudflare dashboard: ### 2. Deploy the tunnel and gateway alias +The tunnel and gateway alias are included in the kustomize build: + ```bash -kubectl apply -f gateway-tunnel-service.yaml -kubectl apply -f cloudflared-tunnel-deployment.yaml +kubectl apply -k overlays/default ``` +Or deploy the full stack (see README). + ### 3. Configure ingress in Cloudflare dashboard Route all traffic to the Envoy Gateway — it already handles path routing (`/api`, `/mcp`, `/`) and MCP path rewrite via the HTTPRoute. @@ -78,6 +81,6 @@ docker push harbor.dataknife.net/library/cloudflared-tunnel:latest ## Files -- `cloudflared-tunnel-deployment.yaml` - Deployment (token from secret, `--no-autoupdate`) -- `cloudflared-tunnel-secrets-example.yaml` - Secret template (do not commit real token) -- `gateway-tunnel-service.yaml` - Stable alias to Envoy Gateway for tunnel routing +- `base/cloudflare/tunnel-deployment.yaml` - Deployment (token from secret, `--no-autoupdate`) +- `base/cloudflare/cloudflared-tunnel-secrets-example.yaml` - Secret template (do not commit real token) +- `base/gateway/tunnel-service.yaml` - Stable alias to Envoy Gateway for tunnel routing diff --git a/k8s/overlays/default/kustomization.yaml b/k8s/overlays/default/kustomization.yaml new file mode 100644 index 0000000..774a422 --- /dev/null +++ b/k8s/overlays/default/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../../base diff --git a/k8s/referencegrant.yaml b/k8s/referencegrant.yaml deleted file mode 100644 index fc19137..0000000 --- a/k8s/referencegrant.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1beta1 -kind: ReferenceGrant -metadata: - name: allow-cert-manager-secrets - namespace: cert-manager -spec: - from: - - group: gateway.networking.k8s.io - kind: Gateway - namespace: high-command - to: - - group: "" - kind: Secret - name: wildcard-dataknife-ai-tls diff --git a/k8s/ui-secrets-example.yaml b/k8s/ui-secrets-example.yaml deleted file mode 100644 index d8671ba..0000000 --- a/k8s/ui-secrets-example.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: high-command-ui-secrets - namespace: high-command -type: Opaque -stringData: - # Claude API Key (optional - only needed for Claude integration) - # This must be set at BUILD TIME in the Docker image, not runtime. - # vite-claude-api-key: "sk-ant-api03-..." - # - # Example: Create this secret using kubectl: - # - # kubectl create secret generic high-command-ui-secrets \ - # --from-literal=vite-claude-api-key='your-claude-api-key-here' \ - # -n high-command - # - # Or generate from a file: - # kubectl create secret generic high-command-ui-secrets \ - # --from-file=vite-claude-api-key=/path/to/api-key-file \ - # -n high-command - # - # Note: Vite environment variables must be set at BUILD TIME, not runtime. - # If you need to change these values, you must rebuild the Docker image - # with the new environment variables. - # - # Current pod environment variables (set in deployment, not secrets): - # - NODE_ENV: "production" - # - PORT: "3000"