GCP Cloud Run vs Drupal
So, I tried. I really did.
For a basic site, it can even probably work.
If you have a need for things like, user-supplied files.. then, omg, don't. Just.. no. Not sure how it copes with larger deployments, but the concept was to keep 1 instance alive, and spin up as many as needed for load. Right? Sounds like it should be good. But.. nope, even that one instance was unhappy.
The main issue is that Drupal likes to WRITE files, not just read them, if it was just reading files, then it would be fine. Even D11 configured to use flysystem_gcs via a bucket with cached reads.. slow.
Configuring it to "write" files to a tmp disk.. kinda worked. But, FAIL for anything dynamic.
What worked:
- Configuring the container to talk to Cloud SQL via a socket, works kinda great!
- Pushing containers and updating them via `gcloud`, works well.
- The artifact registry, the service-accounts, the database.. all work really well.
- Setting up cron-jobs via another pod/container even that worked well.
- Secret management was a breeze, but, non-obvious in the CLI.
What didn't:
Not available in all regions.. did you know that? You can't just.. push to Melbourne and have it work, when Sydney is the only region in AU that is supported for the cloud-scheduler.
SPEED.
Holy moly, turns out connecting to a serverless K8S wrapper that does everything it can to turn off your pod (they don't call it that, but it is) is really irritatingly slow.
Also, you need to rewrite all requests to use the flysystem, and rewriting them is.. not possible for dynamic images (it doesn't act as a CDN, it's.. a redirector?).. which means, IF you need to dynamically write the images to a different size, YOU CANNOT. So, don't try that.
Again, a basic container for a low-tier website, with even moderate interactivity, is probably totally fine.
If you've got some lovely drupal backend headless js site, you might even be able to get a cheap win here, because CloudRun is kinda CloudFun for pushing updates.
Do you think this will survive Cloudflare entering the space?
https://developers.cloudflare.com/containers/
I mean.. maybe?
Some notes for future me, should I do this again:
Setting up a cron-job is doable:
@gcloud scheduler jobs create http $(GCP_CRON_JOB_NAME)-trigger \
--location "$(GCP_REGION)" \
--schedule "*/30 * * * *" \
--uri "https://$(GCP_REGION)-run.googleapis.com/apis/run.apache.org/v1/namespaces/$(GCP_PROJECT_ID)/jobs/$(GCP_CRON_JOB_NAME):run" \
--http-method POST \
--oauth-service-account-email "$(GCP_SERVICE_ACCOUNT)"
Deploying tasks requires the params inline (note the secret names are case-sensitive and versioned, so DB_NAME is the name of the secret, and ":latest" is the version, so, to put that into a secret called "DB_NAME", you need to combine it.. fun: DB_NAME=DB_NAME:latest
Then, to get ANOTHER one, because, calling --set-secrets will overwrite the previous invocation, you need to join them together, eg:
@gcloud run jobs deploy $(GCP_CRON_JOB_NAME) \
--image "$(GCP_IMAGE_FULL_PATH)" \
--region "$(GCP_REGION)" \
--service-account "$(GCP_SERVICE_ACCOUNT)" \
--set-cloudsql-instances "$(GCP_CLOUD_SQL_INSTANCE)" \
--set-env-vars "DB_INSTANCE_CONNECTION_NAME=$(GCP_CLOUD_SQL_INSTANCE)" \
--set-secrets "DB_NAME=DB_NAME:latest,DB_USER=drupal-db-user:latest,DB_PASS=drupal-db-pass:latest" \
--command "/usr/local/bin/cron.sh"
Updating a cloud-run container is.. almost trivial after you've built and pushed it:
@gcloud run jobs update $(GCP_JOB_NAME) \
--image "$(GCP_IMAGE_FULL_PATH)" \
--region "$(GCP_REGION)"
Of course, you can't just send Drupal to a container and have it work.. modern D8+ sites require.. Deployment, so, you need a container that is setup to run your deploy script, eg something like:
DEPLOY_PATH=${DEPLOY_PATH:-"/drupal/path"}
WEB_CONTAINER=${WEB_CONTAINER:-"container"}
echo "--- STARTING REMOTE DEPLOYMENT ---"
echo "Target directory: $DEPLOY_PATH"
cd "$DEPLOY_PATH"
echo "--- Pulling latest images ---"
docker compose pull
echo "--- Restarting containers ---"
docker compose up -d
echo "--- Running post-deployment tasks (drush deploy) ---"
docker compose exec -T "$WEB_CONTAINER" drush deploy -y
echo "--- REMOTE DEPLOYMENT COMPLETE ---"
Then of course, you can't run that on EVERY container boot.. and you're going to see a few of those, so, you'll need a deployment push spin up a container to run that, then when it's done, allow the actual job to start.. fun times.
@gcloud run jobs update $(GCP_CRON_JOB_NAME) \
--image "$(GCP_IMAGE_FULL_PATH)" \
--region "$(GCP_REGION)"
# Run the Deploy job now.. and wait for it to finish.. otherwise the new container will run
# but the DB/config might be out of date.
@gcloud run jobs execute $(GCP_JOB_NAME) --region "$(GCP_REGION)" --wait
Anyway. I'm thinking something else.. maybe an ec2 instance.. something light, and tasty. Maybe a local Talos cluster! hmm.
ANYWAY, enough complainies.
Comments
Post a Comment