Deploying EdgeDB to Google Cloud

In this guide we show how to deploy EdgeDB on GCP using Cloud SQL and Kubernetes.

Prerequisites

Make sure you are logged into google cloud.

  1. $
  1. gcloud init

Create a project

Set the PROJECT environment variable to the project name you’d like to use. Google Cloud only allow letters, numbers, and hyphens.

  1. $
  1. PROJECT=edgedb

Then create a project with this name. Skip this step if your project already exists.

  1. $
  1. gcloud projects create $PROJECT

Then enable the requisite APIs.

  1. $
  1. gcloud services enable \
  2. container.googleapis.com \
  3. sqladmin.googleapis.com \
  4. iam.googleapis.com \
  5. --project=$PROJECT

Provision a Postgres instance

Use the read command to securely assign a value to the PASSWORD environment variable.

  1. $
  1. echo -n "> " && read -s PASSWORD

Then create a Cloud SQL instance and set the password.

  1. $
  1. gcloud sql instances create ${PROJECT}-postgres \
  2. --database-version=POSTGRES_13 \
  3. --cpu=1 \
  4. --memory=3840MiB \
  5. --region=us-west2 \
  6. --project=$PROJECT
  1. $
  1. gcloud sql users set-password postgres \
  2. --instance=${PROJECT}-postgres \
  3. --password=$PASSWORD \
  4. --project=$PROJECT

Create a Kubernetes cluster

Create an empty Kubernetes cluster inside your project.

  1. $
  1. gcloud container clusters create ${PROJECT}-k8s \
  2. --zone=us-west2-a \
  3. --num-nodes=1 \
  4. --project=$PROJECT

Configure service account

Create a new service account, configure it’s permissions, and generate a credentials.json file.

  1. $
  1. gcloud iam service-accounts create ${PROJECT}-account \
  2. --project=$PROJECT
  1. $
  1. MEMBER="${PROJECT}-account@${PROJECT}.iam.gserviceaccount.com"
  1. $
  1. gcloud projects add-iam-policy-binding $PROJECT \
  2. --member=serviceAccount:${MEMBER} \
  3. --role=roles/cloudsql.admin \
  4. --project=$PROJECT
  1. $
  1. gcloud iam service-accounts keys create credentials.json \
  2. --iam-account=${MEMBER}

Then use this credentials.json to authenticate the Kubernetes CLI tool kubectl.

  1. $
  1. kubectl create secret generic cloudsql-instance-credentials \
  2. --from-file=credentials.json=credentials.json
  1. $
  1. INSTANCE_CONNECTION_NAME=$(
  2. gcloud sql instances describe ${PROJECT}-postgres \
  3. --format="value(connectionName)" \
  4. --project=$PROJECT
  5. )
  1. $
  1. DSN="postgresql://postgres:${PASSWORD}@127.0.0.1:5432"
  1. $
  1. kubectl create secret generic cloudsql-db-credentials \
  2. --from-literal=dsn=$DSN \
  3. --from-literal=password=$PASSWORD \
  4. --from-literal=instance=${INSTANCE_CONNECTION_NAME}=tcp:5432

Deploy EdgeDB

Download the starter EdgeDB Kubernetes configuration file. This file specifies a persistent volume, a container running a Cloud SQL authorization proxy, and a container to run EdgeDB itself. It relies on the secrets we declared in the previous step.

  1. $
  1. wget "https://raw.githubusercontent.com\
  2. /edgedb/edgedb-deploy/dev/gcp/deployment.yaml"
  1. $
  1. kubectl apply -f deployment.yaml

Ensure the pods are running.

  1. $
  1. kubectl get pods
  1. NAME READY STATUS RESTARTS AGE
  2. edgedb-977b8fdf6-jswlw 0/2 ContainerCreating 0 16s

The READY 0/2 tells us neither of the two pods have finished booting. Re-run the command until 2/2 pods are READY.

If there were errors you can check EdgeDB’s logs with:

  1. $
  1. kubectl logs deployment/edgedb --container edgedb

Persist TLS Certificate

Now that our EdgeDB instance is up and running, we need to download a local copy of its self-signed TLS certificate (which it generated on startup) and pass it as a secret into Kubernetes. Then we’ll redeploy the pods.

  1. $
  1. kubectl create secret generic cloudsql-tls-credentials \
  2. --from-literal=tlskey="$(
  3. kubectl exec deploy/edgedb -c=edgedb -- \
  4. edgedb-show-secrets.sh --format=raw EDGEDB_SERVER_TLS_KEY
  5. )" \
  6. --from-literal=tlscert="$(
  7. kubectl exec deploy/edgedb -c=edgedb -- \
  8. edgedb-show-secrets.sh --format=raw EDGEDB_SERVER_TLS_CERT
  9. )"
  1. $
  1. kubectl delete -f deployment.yaml
  1. $
  1. kubectl apply -f deployment.yaml

Expose EdgeDB

  1. $
  1. kubectl expose deploy/edgedb --type LoadBalancer

Get your instance’s DSN

Get the public-facing IP address of your database.

  1. $
  1. kubectl get service
  1. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
  2. edgedb LoadBalancer <ip> <ip> 5656:30841/TCP

Copy and paste the EXTERNAL-IP associated with the service named edgedb. With this IP address, you can construct your instance’s DSN:

  1. $
  1. EDGEDB_IP=<copy IP address here>
  1. $
  1. EDGEDB_DSN="edgedb://edgedb:${PASSWORD}@${EDGEDB_IP}"

To print the final DSN, you can echo it. Note that you should only run this command on a computer you trust, like a personal laptop or sandboxed environment.

  1. $
  1. echo $EDGEDB_DSN

The resuling DSN can be used to connect to your instance. To test it, try opening a REPL:

  1. $
  1. edgedb --dsn $EDGEDB_DSN --tls-security insecure
  1. \EdgeDB 1.x (repl 1.x)
  2. Type \help for help, \quit to quit.
  3. edgedb> select "hello world!";

In development

To make this instance easier to work with during local development, create an alias using edgedb instance link.

  1. $
  1. echo $PASSWORD | edgedb instance link \
  2. --dsn $EDGEDB_DSN \
  3. --password-from-stdin \
  4. --non-interactive \
  5. --trust-tls-cert \
  6. gcp_instance

You can now refer to the remote instance using the alias instance on your machine called gcp_instance. You can use this alias wherever an instance name is expected; for instance, you can open a REPL:

  1. $
  1. edgedb -I gcp_instance

Or apply migrations:

  1. $
  1. edgedb -I gcp_instance migrate

In production

To connect to this instance in production, set the EDGEDB_DSN environment variable wherever you deploy your application server; EdgeDB’s client libraries read the value of this variable to know how to connect to your instance.