EddytorDocs & API
02 · Deploy & RunKubernetes with Helm

GKE / EKS

Deploy Eddytor on Google GKE or Amazon EKS - managed Postgres and keyless storage deltas.

Both are deltas over Install the chart - the chart install, secret, verify, and first-admin steps are identical. The cloud-specific parts are: creating the cluster, a managed Postgres, and keyless object-storage access (Workload Identity on GKE, IRSA on EKS).

# Autopilot - Google manages nodes; Workload Identity on by default
gcloud container clusters create-auto "$CLUSTER" --region="$REGION"
  # existing VPC: --network "$VPC" --subnetwork "$SUBNET"

gcloud container clusters get-credentials "$CLUSTER" --region="$REGION"
kubectl create namespace eddytor

Cloud SQL for PostgreSQL

Connect via private IP (simplest with a VPC-native cluster) or the Cloud SQL Auth Proxy. Put the conn string in the secret with TLS required, and install with the external-DB wait gate on (GKE's private-IP DB resolves fine, unlike the bundled-name probe):

--from-literal=EDDYTOR_DATABASE_URL="postgres://eddytor:PW@10.x.x.x:5432/eddytor?sslmode=require"
helm upgrade --install eddytor oci://ghcr.io/nordalf/charts/eddytor -n eddytor \
  --set secrets.existingSecret=eddytor-secrets \
  --set waitForDb.enabled=true \
  --set config.publicUrl="https://eddytor.example.com" \
  --set ingress.enabled=true --set ingress.host=eddytor.example.com

GCS via Workload Identity (preferred - no static key)

gcloud iam service-accounts create eddytor-gcs
gsutil iam ch \
  serviceAccount:eddytor-gcs@PROJECT_ID.iam.gserviceaccount.com:roles/storage.objectAdmin \
  gs://your-eddytor-bucket
gcloud iam service-accounts add-iam-policy-binding \
  eddytor-gcs@PROJECT_ID.iam.gserviceaccount.com \
  --role=roles/iam.workloadIdentityUser \
  --member="serviceAccount:PROJECT_ID.svc.id.goog[eddytor/eddytor-engine]"
kubectl -n eddytor annotate serviceaccount eddytor-engine \
  iam.gke.io/gcp-service-account=eddytor-gcs@PROJECT_ID.iam.gserviceaccount.com

Then register the GCS bucket - with Workload Identity the pod gets credentials ambiently, no key file.

Ingress / TLS

--set ingress.enabled=true --set ingress.host=eddytor.example.com \
--set ingress.className=gce --set ingress.tls=true   # Google-managed cert

A Google-managed cert only issues once the Ingress has a stable IP and DNS resolves to it.

Cluster (with IRSA)

eksctl create cluster --name "$CLUSTER" --region "$REGION" \
  --nodes "$NODES" --node-type "$NODE_TYPE" --with-oidc
aws eks update-kubeconfig --name "$CLUSTER" --region "$REGION"

--with-oidc associates the IAM OIDC provider - required for IRSA. On an existing cluster: eksctl utils associate-iam-oidc-provider --cluster "$CLUSTER" --approve.

RDS for PostgreSQL

Put the RDS conn string in the secret (SSL required), and allow the node group's security group inbound on 5432:

--from-literal=EDDYTOR_DATABASE_URL="postgres://eddytor:PASS@eddytor.abc123.eu-west-1.rds.amazonaws.com:5432/eddytor?sslmode=require"

Install against RDS with ALB ingress + an ACM cert:

helm upgrade --install eddytor oci://ghcr.io/nordalf/charts/eddytor -n eddytor \
  --set secrets.existingSecret=eddytor-secrets \
  --set postgres.bundled=false \
  --set waitForDb.enabled=true \
  --set config.publicUrl="https://eddytor.example.com" \
  --set ingress.enabled=true --set ingress.host=eddytor.example.com \
  --set ingress.className=alb --set ingress.tls=true

The AWS Load Balancer Controller and ACM cert are AWS prerequisites configured outside the chart.

S3 via IRSA (preferred - no static keys)

eksctl create iamserviceaccount --cluster "$CLUSTER" --namespace eddytor \
  --name eddytor-server --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess \
  --approve --override-existing-serviceaccounts

Heads up

AmazonS3FullAccess is shown for brevity - scope a custom policy to your bucket(s) for production (s3:GetObject/PutObject/DeleteObject/ ListBucket on arn:aws:s3:::your-bucket[/*]).

Then register the S3 bucket - the pod assumes the role, no keys needed.

Shared gotchas

  • ?sslmode=require on the managed-DB URL - Cloud SQL / RDS reject or warn on plaintext, and the server's preflight handshake fails without it.
  • Bundled Postgres can crash-loop on the cloud CSI (PD / EBS) with chown: Operation not permitted - prefer the managed DB, or patch the StatefulSet caps (CHOWN,FOWNER,DAC_OVERRIDE,SETGID,SETUID).
  • One release per namespace - engine Services are fixed-named; the GKE Workload Identity binding targets the eddytor-engine KSA specifically.
  • EKS IRSA needs the OIDC provider - without --with-oidc, the SA role annotation does nothing and S3 calls 403.
  • Raw LB endpoint unknown until provisioned - use the two-step publicUrl update.

Teardown

gcloud container clusters delete "$CLUSTER" --region="$REGION"   # GKE
eksctl delete cluster --name "$CLUSTER" --region "$REGION"       # EKS (RDS deleted separately)

Next

On this page