Ghost: Architecting a Test Site
My previous topic described preparation steps for my new pet project - a test site in the Google Cloud. This post describes the design stage with my train of thought explanation and the current design state.
Let's start with the requirements reiteration and then review the design steps. My original goal is to bring up the latest site clone for tests and do it for less than $25/month.
Plus a few additional requirements:
- Minimize site engine and database maintenance as much as possible, but control the system entirely.
- Make production backups reliable and not as annoying as the Google Drive version.
- Quickly bring up the dev system from the latest site backup and try the new design or site-wide changes.
- In perspective, make out of it a production setup, not necessarily on the same cloud provider.
Components selection
Since I don't want to do patching and configurations, containers are the only reasonable way. Fortunately, Google Cloud offers quite a few ways to run containers. But, unfortunately, most of those ways are predominantly stateless.
I don't want to set up a Kubernetes cluster for something I may use once or twice a month. Building a new cluster and deployment takes a while (not a minute). Even just keeping it down all the time is expensive for the task.
The next best option would be a Cloud Run, and its older relative AppEngine, allows you to spin serverless apps in Docker containers. Unfortunately, none of those passed the inexpensive state preservation check, primarily due to static content on the POSIX file system. Plus, it may require a custom version of the standard Ghost container, which practically brings me to square one - watch Ghost releases and do manual upgrades.
Being said, it leaves me no option but a good old compute instance with an ephemeral boot device (less expensive than a separate block device, though.) Plus, because I don intend to preserve instance content, it could be a spot VM that drives the cost of ownership to the ground level.
Since Spot VM could be killed at any time - it should be a part of the instance group with the max instance == 1. Plus, I need a load balancer to make my dev instance accessible from the outside.
A few more conveniences:
- I want to refresh the running instance when the new backup is available.
- I want to stop VM when the project cost hits 75% of the monthly budget.
All that led me to the small architecture depicted below.
Here is a walk-through:
- The scheduled job on this site uploads the new backup into the Google Cloud Store. The bucket has a lifecycle policy enabled and keeps the current and two latest site copies for two weeks. After that, outdated versions are deleted automatically.
- New file checkout triggers pub/sub notification for the Cloud Function. It checks the current state of the instance and, if it's up - kills it for the restart and rebuild.
- When the old instance is killed, the instance group spins up a new one using the standard OS image and some tricky init scripts to initialize a new site clone.
- The project budget watches project spending and pushes a reach-the-limit alert to the pub/sub-topic.
- The budget-driven cloud function stops the instance and keeps it down until the next month.
The design is current but not final and will be adjusted on the go. I'll post another update with the results and all the code when this design goes live.