Skip to main content

Overview

This guide covers GCP-specific integration for CrewAI Platform deployments on Google Kubernetes Engine (GKE). It focuses on configuring GCS for object storage, Artifact Registry (or registry-less Bucket Deployment) for crew image builds, Cloud SQL for PostgreSQL, and optionally Secret Manager — all authenticated via GKE Workload Identity Federation (no static keys).
This guide assumes you have:
  • A GKE cluster running Kubernetes 1.28+ with Workload Identity enabled
  • gcloud CLI and kubectl configured
  • Helm 3.10+ installed
  • Basic familiarity with GCP services (Cloud SQL, GCS, Artifact Registry)

Prerequisites

Before configuring CrewAI Platform, ensure these GCP components are in place: CrewAI Platform supports AMD64 (x86_64) Kubernetes worker nodes. ARM64 (aarch64) worker nodes are not currently supported. For full platform requirements, see the Requirements Guide.

Required GCP Infrastructure

Required GCP APIs

Enable the following APIs in your project before proceeding:
Do not proceed with CrewAI installation until these prerequisites are met. The Helm chart will fail to deploy without them.

Pre-Install Checklist

Before running helm install, confirm the following are complete:
  • GKE cluster with Workload Identity enabled
  • Gateway API enabled (gcloud container clusters update --gateway-api=standard)
  • All four Cloud SQL databases created: crewai_plus_production, crewai_plus_cable_production, crewai_plus_oauth_production, wharf
  • SQL privileges granted to IAM user on all four databases
  • GSA IAM roles bound (roles/cloudsql.client, roles/cloudsql.instanceUser, roles/iam.workloadIdentityUser, roles/storage.objectAdmin)
  • GCS_IAM_SIGNING: "true" set in envVars (required when using Workload Identity — omitting this causes Google::Cloud::Storage::SignedUrlUnavailable at runtime)

Step 1: Create the GCP Service Account

All CrewAI workloads (web, worker, buildkit) share a single GCP Service Account (GSA) that is mapped to the Kubernetes ServiceAccount via Workload Identity. This GSA needs permissions for GCS, Artifact Registry, Cloud SQL, and optionally Secret Manager.
The Workload Identity IAM binding in Step 3 references KSA_NAME. If your helm install command uses a different release name than the one in this guide, your KSA_NAME will not match the ServiceAccount the chart creates. To avoid a silent Workload Identity failure, add serviceAccount.name: crewai-sa to your Helm values to force the chart to create a ServiceAccount with the name this guide assumes, OR update the gcloud iam binding command to use your actual {release-name}-sa value.

Step 2: Grant IAM Roles

Bind the required IAM roles to the service account. Each role maps to a specific CrewAI requirement:
For tighter security, scope roles/storage.objectAdmin and roles/artifactregistry.writer to specific resources using --condition flags or bucket/repo-level IAM instead of project-level bindings.The node pool GCE SA binding is separate from the GSA bindings. The platform injects a short-lived GAR token at deploy time for immediate pulls, but the node SA provides reliable fallback when crew pods are rescheduled after the token expires.

Step 3: Bind Workload Identity

Create the IAM policy bindings that allow the Kubernetes ServiceAccounts to impersonate the GCP Service Account. Two bindings are needed: one for the platform namespace (web, worker, buildkit daemon) and one for the crews namespace (build pods that push images to GAR):
The [NAMESPACE/KSA_NAME] in the member string must exactly match the Kubernetes namespace and the ServiceAccount name. The chart creates crewai-sa by default when rbac.create: true. The crews namespace (crewai-crews by default) uses the default ServiceAccount for build pods.

Post-Install: Annotate the Crew Namespace

After the initial Helm install (which creates the crewai-crews namespace automatically), annotate the default ServiceAccount in the crews namespace so build pods can authenticate to GAR via Workload Identity:
Until this annotation is applied, all crew image builds will fail with a permission denied error when pushing to Artifact Registry. If deploying via CI/CD and you need to apply the annotation before helm install, create the namespace in advance: kubectl create namespace crewai-crews, then annotate immediately.
ArgoCD users: This step requires a two-Application pattern because the crewai-crews namespace does not exist until after the first sync completes. See the ArgoCD Deployment Guide.

Cloud SQL for PostgreSQL

CrewAI Platform requires PostgreSQL 16+ for production deployments.

Cloud SQL Instance Sizing

Minimum recommended specifications based on CrewAI workload characteristics:

Create the Cloud SQL Instance

Create Databases and User

CrewAI requires four databases — primary, cable, OAuth, and Wharf for OTLP trace storage:
You can use either password-based or IAM-based authentication: Option A: Password-based authentication (simpler)
Option B: IAM-based authentication (no static passwords) IAM authentication uses Workload Identity to authenticate the application to Cloud SQL via short-lived tokens. No DB_PASSWORD is needed. Step 1: Enable IAM authentication on the Cloud SQL instance:
The cloudsql.iam_authentication flag is off by default. Without it, Cloud SQL rejects IAM tokens regardless of user or role configuration.
Step 2: Create the IAM database user:
Step 3: Grant the GSA the Cloud SQL IAM login role:
Step 4: Grant SQL privileges to the IAM user. Connect to the Cloud SQL instance using the postgres superuser (recommended) or an existing admin user. You can connect via gcloud sql connect or from inside a running pod:
Then run the following SQL commands (replace GSA_NAME@GCP_PROJECT_ID.iam with your actual IAM user, e.g., crewai-platform@jr-testing-487713.iam):
Migrating from password-based to IAM auth? If your databases already have tables created by a password-based user (e.g., crewai), you must run the GRANT ALL ON ALL TABLES and GRANT ALL ON ALL SEQUENCES commands above for each database. Without these grants, the IAM user will get permission denied for table schema_migrations errors during migrations. The ALTER DEFAULT PRIVILEGES statements only apply to future objects — they do not retroactively grant access to existing tables.
Step 5: Transfer table ownership to the IAM user. PostgreSQL DDL operations (e.g., ALTER TABLE, DROP COLUMN) require the executing user to be the owner of the table — GRANT ALL PRIVILEGES is not sufficient. If the databases were initially set up by a different user (e.g., postgres or a password-based crewai user), the IAM user will not own existing tables, and future upgrade migrations that modify table structure will fail. The pre-upgrade migration hook automatically detects this condition and will report the affected tables with the exact SQL to fix them. To prevent this from blocking your first upgrade, transfer ownership proactively. Connect to the database as the postgres superuser using the same host and port the application uses:
Then run the following SQL (replace the IAM user with your actual value, e.g., crewai-platform@your-project.iam):
Any tables the IAM user creates going forward (via Rails migrations) are automatically owned by it, so this transfer only needs to be done once for pre-existing tables.
Use the postgres superuser for these commands. Only the current owner or a superuser can transfer table ownership. A non-superuser like crewai can run GRANT commands on objects it owns, but cannot run ALTER TABLE ... OWNER TO for tables it doesn’t own.
The Helm chart includes a built-in Cloud SQL Auth Proxy sidecar. When enabled, it runs alongside the web, worker, OAuth, Wharf, and job containers, authenticating via Workload Identity. The app connects to 127.0.0.1 through the proxy.
If you prefer password-based auth through the proxy, set autoIamAuthn: false and provide DB_PASSWORD via secrets.

Helm Database Configuration

For IAM authentication (autoIamAuthn: true):
DB_USER format for Cloud SQL IAM authentication: Use the GSA email WITHOUT the .gserviceaccount.com suffix. Cloud SQL Auth Proxy strips this suffix internally during IAM token exchange — including it causes authentication to fail silently.
  • Correct: crewai-platform@your-project.iam
  • Wrong: crewai-platform@your-project.iam.gserviceaccount.com
The full GSA email (with suffix) is used for gcloud iam service-accounts create and IAM bindings. The truncated form is used ONLY for DB_USER in Helm values.
You must explicitly set POSTGRES_OAUTH_DB in your Helm values. The chart default is oauth_db, but this GCP guide instructs you to create a database named crewai_plus_oauth_production. If your actual database name differs from the chart default and you do not override POSTGRES_OAUTH_DB, the OAuth service attempts to connect to a database that does not exist and fails silently at startup.Set it explicitly in envVars: to match the database you created:
No DB_PASSWORD is needed — the Cloud SQL Auth Proxy handles authentication automatically via Workload Identity. For password-based authentication (autoIamAuthn: false):

Google Cloud Storage for Object Storage

CrewAI Platform uses GCS for storing crew artifacts, tool outputs, and user uploads. With Workload Identity, no static credentials are needed.

Create GCS Bucket

Helm Configuration for GCS

No credentials or keyfile configuration is required. The google-cloud-storage gem uses Application Default Credentials (ADC), which are automatically provided by GKE Workload Identity.
GCS_IAM_SIGNING is required when using Workload Identity. Without it, GCS signed URL generation will fail with Google::Cloud::Storage::SignedUrlUnavailable whenever any file upload or download signed URL is generated — a hard failure that occurs in normal platform use. When enabled, the platform uses the IAM signBlob API instead, which requires the roles/iam.serviceAccountTokenCreator role granted in Step 2.If GCS_SIGNING_EMAIL is left blank, the service account email is automatically detected from the GKE metadata server.

Artifact Registry for Container Images

CrewAI Platform requires Artifact Registry for storing crew automation container images. When users create and deploy crews, CrewAI builds container images and pushes them to your registry.

Repository Requirements

Critical Requirements:
  • Repository URI must end in /crewai-enterprise once the platform appends its suffix
  • Immutable tags must be disabled (CrewAI overwrites tags for crew versions)

Create Artifact Registry Repository

The resulting registry host is GCP_REGION-docker.pkg.dev. For example: us-central1-docker.pkg.dev/your-project/crewai. Valid repository URIs (set in CREW_IMAGE_REGISTRY_OVERRIDE):
  • us-central1-docker.pkg.dev/your-project/crewai
  • us-docker.pkg.dev/your-project/crewai
  • europe-west1-docker.pkg.dev/your-project/crewai

Helm Configuration for Artifact Registry

Do not set global.imageRegistry to your Artifact Registry host for standard deployments. Setting global.imageRegistry redirects all platform component image pulls (Redis, BuildKit, Wharf, etc.) away from images.crewai.com, causing ImagePullBackOff on every pod. CREW_IMAGE_REGISTRY_OVERRIDE is the only registry value needed for directing crew image builds to Artifact Registry.
The Helm chart auto-detects the GAR host from CREW_IMAGE_REGISTRY_OVERRIDE when it matches the *-docker.pkg.dev pattern and sets GCP_ARTIFACT_REGISTRY_HOST automatically. BuildKit pods then obtain short-lived access tokens from the GKE metadata server to authenticate pushes.

How Crew Pods Pull Images from GAR

When a crew is deployed, the platform automatically injects a fresh short-lived GAR access token into the crew namespace’s image pull secret. This ensures crew pods can immediately pull their built images from Artifact Registry without any manual credential management. How it works:
  1. Build pods push images to GAR via Workload Identity (using the GSA’s roles/artifactregistry.writer)
  2. At deploy time, the platform fetches a fresh GAR access token from the GKE metadata server and merges it into the registry pull secret
  3. Crew pods use this enriched pull secret to pull their images from GAR
This mechanism is fully automatic — it activates whenever the Helm chart auto-detects a GAR registry from CREW_IMAGE_REGISTRY_OVERRIDE.

Enable GKE Node Image Pulls from GAR (Defense-in-Depth)

As a fallback for scenarios where a crew pod is rescheduled to a new node after the injected token has expired, the node pool’s compute service account must have roles/artifactregistry.reader. This is configured in Step 2: Grant IAM Roles.
This IAM binding is required for production reliability. Without it, crew pods may fail to pull images if they are rescheduled to a new node more than one hour after initial deployment.

Verifying Artifact Registry Access

Test that the Workload Identity binding is working:

Bucket Deployment — Registry-Less Image Delivery

Bucket Deployment is an alternative to Artifact Registry that eliminates the need for any container registry. Instead of pushing built crew images to a registry, the platform stores them as compressed OCI tarballs in a GCS bucket and loads them directly into the container runtime on each Kubernetes node before deployment.
Bucket Deployment and Artifact Registry are mutually exclusive for crew image delivery. Choose one approach based on your requirements. Both still use BuildKit to build images — the difference is where the built image is stored and how it reaches the nodes.

When to Use Bucket Deployment

How Bucket Deployment Works

The workflow has four phases: 1. Build — When a crew is deployed, BuildKit builds the container image as usual, but instead of pushing it to a registry, it outputs an OCI tarball. The tarball is compressed with gzip and uploaded to a GCS bucket using a Workload Identity access token. 2. Preload — A temporary Kubernetes DaemonSet is created, placing one pod on every node in the cluster. Each pod downloads the tarball from GCS, decompresses it, and imports it into the node’s containerd runtime using ctr images import. This makes the image available to the kubelet as if it had been pulled from a registry. 3. Deploy — Once all nodes have the image loaded, the crew is deployed via Helm with imagePullPolicy: Never and no imagePullSecrets. The kubelet finds the image in its local store and starts the pod normally. 4. Cleanup — The preloader DaemonSet is deleted. The imported images remain in the node’s containerd store.
The preloader DaemonSet runs with privileged: true to access the node’s containerd socket and ctr binary. This elevated access is ephemeral — it only exists during the deployment process and is cleaned up immediately after the image is loaded. The crew pods themselves run with normal, unprivileged security contexts.

Prerequisites

Before enabling Bucket Deployment, ensure you have:
  1. GCS bucket — A dedicated bucket for storing crew image tarballs
  2. IAM permissions — The Workload Identity GSA must have roles/storage.objectAdmin on the image bucket (for both upload and download)
  3. Workload Identity — Already configured per Step 3
  4. BuildKit — Enabled in the Helm chart (buildkit.enabled: true)
If you already configured roles/storage.objectAdmin at the project level for GCS object storage (see Step 2), the same binding covers the image bucket. No additional IAM configuration is needed — skip to Create the Image Bucket.

Create the Image Bucket

Create a dedicated GCS bucket for crew image tarballs. This bucket is separate from the general-purpose GCS_BUCKET used for crew artifacts and uploads.
If you scoped roles/storage.objectAdmin to the general-purpose bucket (rather than project-level), grant access to the image bucket separately:
Lifecycle policies are not recommended for the image bucket. Image tarballs are actively referenced by running crews and must remain available for node rescheduling or cluster scaling events. If you need cleanup, delete tarballs only after the corresponding crew has been undeployed.

Helm Configuration for Bucket Deployment

Set the following environment variables in your Helm values to enable Bucket Deployment:
CREW_IMAGE_REGISTRY_OVERRIDE is still required even though no registry is used. This value serves as the image name/tag throughout the build, preload, and deploy pipeline. The image is tagged with this name when imported into containerd, and Kubernetes pods reference it in their image: field. Do not remove it.

Configuration Reference

The CONTAINERD_SOCKET_PATH and CTR_HOST_PATH defaults are correct for standard GKE nodes (Container-Optimized OS and Ubuntu). Override them only if your cluster uses custom node images with non-standard containerd paths.

What Changes from Artifact Registry Mode

When switching from Artifact Registry to Bucket Deployment, the following Helm values change:

Verifying Bucket Deployment

After deploying a crew, verify the bucket deployment pipeline: 1. Check the image tarball was uploaded:
2. Check preloader DaemonSet (during deployment):
3. Verify the image is loaded on nodes:
4. Confirm crew pods are running with imagePullPolicy: Never:

Secret Manager Integration (Optional)

GCP Secret Manager provides centralized secret management for CrewAI Platform.

Which Secrets to Store

Store in Secret Manager (sensitive, need rotation):
  • DB_PASSWORD - Database credentials (if not using IAM auth)
  • SECRET_KEY_BASE - Rails secret key
  • GITHUB_TOKEN - For private repository access
  • Auth provider secrets (ENTRA_ID_CLIENT_SECRET, OKTA_CLIENT_SECRET, etc.)
Keep in values.yaml (configuration, not secrets):
  • DB_HOST, DB_PORT, DB_USER, POSTGRES_DB
  • GCS_PROJECT_ID, GCS_BUCKET
  • APPLICATION_HOST, AUTH_PROVIDER

External Secrets Operator Setup

CrewAI uses External Secrets Operator (ESO) to sync secrets from Secret Manager to Kubernetes. Install ESO (if not already installed):

Helm Configuration for Secret Manager

External Access (Gateway API or Ingress)

GKE provides built-in support for the Kubernetes Gateway API, which is the recommended way to expose services externally.
The NGINX Ingress Controller was retired in March 2026. For new GKE deployments, Gateway API is recommended over traditional Ingress resources. Existing Ingress configurations continue to work.
GKE ships with built-in GatewayClass resources — no additional controller installation is needed, but Gateway API support must be enabled on the cluster.

Enable Gateway API on GKE

Verify the GatewayClass resources are available (this may take a minute to propagate):
You should see the following classes:
For most single-region production deployments, the regional class reduces latency by keeping traffic within a single region and avoids the global load balancer premium. Choose global only if you require multi-region failover or Cloud CDN integration.
If kubectl get gatewayclass returns “No resources found”, the Gateway API CRDs are not installed. The Helm chart will fail with no matches for kind "Gateway". Run the gcloud container clusters update command above and wait for it to complete before deploying.
Merge all web: settings under a single top-level web: key in your final values.yaml. Helm silently drops all but the last occurrence of a duplicate top-level key.

Helm Configuration

If OAuth requires a dedicated hostname (e.g., because GKE does not support NGINX-style regex path rewriting), set pathPrefix: "/" and specify the hostname:
When using a dedicated OAuth hostname, add it to the Gateway TLS certificate (or create a separate certificate map entry) and update DNS to point to the same Gateway IP.
To use a GCP-managed certificate instead of a Kubernetes TLS secret, add the annotation:
To create the certificate map:
If you already have a Gateway resource (e.g., shared across multiple apps), reference it instead of creating one:
After deploying, get the load balancer IP:
The Helm chart automatically creates a GKE HealthCheckPolicy that configures the load balancer to use /health as the health check path. Without this, GKE’s health probes use the pod IP as the Host header, which Rails’ HostAuthorization middleware blocks — causing unconditional drop overload errors. This is handled automatically; no manual configuration is needed.

Option 2: GCE Ingress (Native GKE)

If you prefer traditional Ingress resources:

Option 3: NGINX Ingress Controller (Deprecated)

The NGINX Ingress Controller was retired in March 2026. Consider migrating to Gateway API for new deployments.
GKE does not include a pre-installed NGINX Ingress Controller. Using className: nginx without first installing the controller will create an Ingress resource that never receives an external IP. For new GKE deployments, use Option 1 (Gateway API) or Option 2 (GCE Ingress).

Complete GCP Deployment Example

If using WorkOS authentication, place WORKOS_API_KEY under envVars: — NOT under secrets:. See the WorkOS SSO guide for the full explanation and the correct YAML placement. This is a known chart limitation.
Here is a complete production configuration for GCP:
The image.registries section is required when installing via direct Helm (helm install ... oci://registry.crewai.com/...). It provides credentials for pulling platform images (busybox, redis, buildkit, etc.) from the Replicated proxy at images.crewai.com. Use the same email and license token you used for helm registry login registry.crewai.com.When installing via Replicated KOTS, these credentials are injected automatically and image.registries is not needed.
Deploy:
Post-install: After the first install, annotate the crews namespace ServiceAccount for Workload Identity (see Step 3):

Bucket Deployment Variant

To use Bucket Deployment instead of Artifact Registry, modify the envVars section in the example above:
When using Bucket Deployment, Artifact Registry IAM roles (roles/artifactregistry.writer, roles/artifactregistry.reader) are not needed. The roles/storage.objectAdmin role on the image bucket handles both upload (from build pods) and download (from preloader pods). The Crews namespace Workload Identity binding is still required — build pods use it to obtain GCS access tokens for uploading image tarballs.

Troubleshooting GCP-Specific Issues

Workload Identity Not Working

Symptoms: Pods get 403 Forbidden or could not retrieve default credentials errors. Verify Workload Identity is enabled on the cluster:
Check ServiceAccount annotation:
Test from a pod:
If this fails, verify the IAM binding:

GCS Signed URL Errors

Symptoms: Logs show Google::Cloud::Storage::SignedUrlUnavailable: Service account credentials 'issuer (client_email)' is missing when deploying crews. This happens when Workload Identity is used but IAM-based URL signing is not enabled. The google-cloud-storage gem cannot sign URLs without a private key; with Workload Identity, the IAM signBlob API must be used instead. Fix:
  1. Ensure GCS_IAM_SIGNING: "true" is set in envVars
  2. Grant the roles/iam.serviceAccountTokenCreator role to the GSA:
  1. Redeploy the Helm chart

GCS Access Denied

Symptoms: Logs show Google::Cloud::PermissionDeniedError for storage operations.

Cloud SQL Connection Failures

Symptoms: Pods show connection refused on 127.0.0.1:5432. Check the Cloud SQL Proxy sidecar is running:
Verify the instance connection name:

Cloud SQL IAM Authentication Failures

DB_USER must be the GSA email WITHOUT the .gserviceaccount.com suffix. Including the full domain will cause authentication failures.
Symptoms: fe_sendauth: no password supplied or issue connecting with your username/password. “no password supplied”autoIamAuthn is not enabled in your Helm values:
“issue connecting with your username/password” — the IAM token is being injected but rejected. Check these in order:
  1. IAM authentication flag on the instance (most common miss — off by default):
  1. IAM database user exists:
  1. GSA has required IAM roles:
  1. DB_USER is in IAM format (in Helm values):
  1. SQL privileges granted — the IAM user must have been granted access to the databases via GRANT ALL PRIVILEGES (see “Create Databases and User” section above)

Cloud SQL IAM: Table Ownership Errors During Upgrades

Symptoms: Rails migrations fail with PG::InsufficientPrivilege: ERROR: must be owner of table <table_name>. Root cause: PostgreSQL DDL operations (ALTER TABLE, DROP COLUMN, ADD INDEX, etc.) require the executing user to be the owner of the table. When using IAM authentication, the IAM database user typically does not own tables that were created by the postgres superuser or a previous password-based user. GRANT ALL PRIVILEGES grants read/write access but does not transfer ownership. Fix: Connect as the postgres superuser and transfer ownership of all tables, sequences, and views to the IAM user. See Step 5 of the IAM authentication setup for the exact SQL commands. Prevention: Run the ownership transfer SQL during initial IAM auth setup (Step 5), before the first Helm upgrade.

Artifact Registry Push Failures

Symptoms: Crew deployments fail with unauthorized or denied during image push. Verify the GSA has Artifact Registry write access:
Check BuildKit pod logs:
Check Workload Identity annotation on the crews namespace default SA (build pods use this SA):
If missing, annotate it (see Step 3).

Artifact Registry Pull Failures (Crew Pods)

Symptoms: Crew pods in crewai-crews namespace show ImagePullBackOff or ErrImagePull with 403 Forbidden when pulling from *-docker.pkg.dev. This can have multiple causes: 1. Wrong pull secret name: The crew pod references a pull secret that doesn’t exist or has empty credentials.
If the decoded config shows {"auths":{}} (empty), the Helm chart’s image.registries may not be configured. See the Complete Example. 2. Node pool compute SA lacks GAR read access:
If the role is missing, grant it (see Step 2). 3. Verify the image exists in GAR:

Build Pod Image Pull Failures

Symptoms: Build pods in the platform namespace show ErrImagePull for images from images.crewai.com. This means the registry pull secret lacks Replicated proxy credentials. Verify:
If images.crewai.com is not in the auths section, add Replicated proxy credentials to image.registries in your Helm values and redeploy (see the Complete Example).

Secret Manager Access Denied

Symptoms: ExternalSecret shows SecretSyncedError.

Bucket Deployment: Upload Failed

Symptoms: Crew deployment fails during the build phase with Bucket upload failed in the build pod logs. Check the build pod logs:
Common causes:
  1. Missing IMAGE_BUCKET_NAME — The environment variable is not set. Verify it appears in your Helm values under envVars.
  2. Bucket does not exist — Verify the bucket exists:
  1. Missing IAM permissions — The Workload Identity GSA needs roles/storage.objectAdmin on the image bucket:
  1. Metadata server unreachable — Build pods obtain access tokens from the GCE metadata server. If the logs show Failed to get access token from metadata server, verify that Workload Identity is bound for the crews namespace (see Step 3).

Bucket Deployment: Preloader Timeout

Symptoms: Crew deployment hangs at the preload phase. The preloader DaemonSet pods are not reaching Ready state. Check the preloader DaemonSet and pod status:
Common causes:
  1. Image tarball not found in bucket — The preloader downloads from the bucket. If the build phase failed silently or the object name doesn’t match:
  1. GCS download permission denied — The preloader pods run in the platform namespace and use the platform KSA’s Workload Identity. Verify the GSA has read access to the image bucket.
  2. containerd socket not accessible — The preloader mounts the host’s containerd socket. If the node uses a non-standard socket path, set CONTAINERD_SOCKET_PATH in your Helm values. Check the default path:
  1. ctr binary not found — The preloader uses the host’s ctr binary from /usr/bin. If it’s in a different location on your nodes, set CTR_HOST_PATH in your Helm values:

Bucket Deployment: ErrImageNeverPull

Symptoms: Crew pods show ErrImageNeverPull status after deployment. This means Kubernetes is set to imagePullPolicy: Never but the image is not present in the node’s containerd store. This can happen if:
  1. Preloader didn’t complete on this node — The node may have been added to the cluster after the preloader DaemonSet ran. Redeploy the crew to trigger a fresh preload cycle.
  2. containerd image was garbage collected — containerd may have cleaned up unused images. Redeploy the crew.
  3. Image name mismatch — The CREW_IMAGE_REGISTRY_OVERRIDE value must be consistent across build, preload, and deploy. Verify:
The image name from the pod spec must exactly match an image in the ctr output.