Deploying Fred on GCP / GKE
A typical Google Kubernetes Engine deployment — the workloads, the in-cluster services, the managed Google Cloud services, and how you know it is correct, not just running.
PROJECT_ID,
REGION, studio.example.com.
Scope & audience
For operators and platform engineers standing up Fred on GKE Autopilot. This page is the map: the shape of a deployment, what talks to what, and its definition of "done". It is deliberately not the environment-specific runbook (exact hostnames, secrets, and commands) — that ships with the Helm chart and stays in sync with it.
Topology at a glance
A Fred instance runs in a single Kubernetes namespace on a GKE Autopilot cluster. Four stateless application workloads share a set of in-cluster services (Postgres, Keycloak, OpenFGA, OpenSearch, Temporal). The only reach outside the cluster is to a few managed Google Cloud services — reached keylessly through Workload Identity.
Fred's stateless workloads (deployed via GitOps) and its in-cluster services run in one namespace. Only Knowledge Flow reaches managed Google Cloud — Cloud Storage and Vertex AI — authenticated keylessly through Workload Identity (no service-account keys). Images come from Artifact Registry, built by Cloud Build.
What runs in the cluster
Fred workloads (stateless)
ExecutionGrant issuance. The sole authority for agent discovery and enrollment./agents/execute, /agents/execute/stream, plus an OpenAI-compatible endpoint). Runs the agent definitions; conversation state persists to Postgres.In-cluster services
keycloak, openfga, temporal, fred). Backed by a persistent volume — never ephemeral pod storage.Managed Google Cloud services
A typical GKE deployment leans on a small set of managed services:
type: gcs discriminator; used only by Knowledge Flow.roles/aiplatform.user.Keyless object storage — Workload Identity
Fred authenticates to Google Cloud with no service-account keys. It uses GKE Workload Identity: clients call Application Default Credentials, and the pod's Kubernetes service account (KSA) is federated to a Google service account (GSA).
- A GSA (e.g.
fred-knowledge-flow-gcs@PROJECT_ID.iam.gserviceaccount.com) is grantedroles/storage.objectAdminon the buckets androles/aiplatform.user. - The GSA is bound to the workload's KSA with
roles/iam.workloadIdentityUser. - The KSA is annotated
iam.gke.io/gcp-service-account: <GSA>. That is the whole wiring — no JSON key is ever created, committed, or mounted.
Edge, TLS & secrets
Ingress, TLS and DNS
All external traffic enters through a single GKE Ingress, fronted by a reserved global static
IP. Public hostnames (frontend, Keycloak, and the Temporal UI) resolve via DNS A-records you
create outside Helm. TLS uses GKE ManagedCertificate resources — one per host —
which provision automatically once DNS points at the IP.
Active only
after DNS resolves to the load-balancer IP — typically 15–60 minutes. A ready pod behind a
still-provisioning certificate is unreachable over HTTPS; don't mistake that for a failure.
Secrets & configuration
Sensitive values live in a single Kubernetes Secret, rendered from a git-ignored values file (a committed example shows the shape with empty values). It carries the Postgres passwords, the Keycloak admin password and confidential client secrets, the OpenFGA API token, and any optional model-provider API key. Object storage is absent by design — it uses Workload Identity. Non-secret configuration (hostnames, feature flags, per-team quotas) is plain Helm values.
How it is deployed
The deployment splits cleanly into two layers with different change cadences:
maxSurge: 0) rather than surging a
second copy of all four at once — which would spike memory and node auto-provisioning on a
small cluster. Postgres uses a modest persistent volume on a standard storage class.
Deployment steps
- Prerequisites.
gcloud,kubectl, andhelmauthenticated to the target project; a GKE Autopilot cluster; the target namespace. - Reserve the edge. Reserve a global static IP and create DNS A-records for the public hostnames pointing at it.
- Google Cloud prerequisites. Create the Artifact Registry repository and enable Cloud Build; create the GCS buckets, the GSA, the Workload Identity binding, and enable Vertex AI.
- Fill secrets. Copy the example values file, fill the required secret values, and keep it out of version control.
- Deploy the foundation. Install the foundation chart. Its hook Jobs provision the databases and users, seed the Keycloak realm and clients, and register the Temporal namespace. Confirm the provisioning Jobs completed.
- Build images. Build the component images at one shared, date-stamped tag via Cloud Build, so a release round is one coherent version.
- Run migrations. Apply the control-plane and knowledge-flow schema migrations (each tracks its own migration version).
- Deploy the apps. Bring up
control-plane-backend, thenknowledge-flow(backend + worker) andfred-agents, and thefred-frontendlast — it resolves backend DNS at startup. - Provision identity. Create the initial users, teams, and groups so the
groupsclaim is populated. - Verify. Run the status/completeness check until it is fully green (see below), then log in over HTTPS and run an ingestion smoke test.
rollout restart —
no full release.
Verifying the deployment — complete and correct
The hardest deployment bugs are silent: every pod is 1/1 Ready, yet the product is
subtly broken. Liveness is not correctness. Treat "done" as an executable checklist
— a single status command green across every dimension:
/ready probe confirms its real backends (Postgres, OpenSearch, OpenFGA, object storage) — not just that the pod started.Active, not provisioning — a ready pod behind a half-issued certificate is unreachable over HTTPS.Gotchas worth knowing
emptyDir — otherwise conversations vanish on every restart while still appearing in the session list.