Add CGP Cloud Run deployment documentation

* Add docs for gcp cloud run

* terraform gcp cloud run

* Edit GCP Clound Run documentation for clarity

---------

Co-authored-by: Christopher Charbonneau Wells <10456740+cdubz@users.noreply.github.com>
This commit is contained in:
Edvin N 2023-12-22 18:53:36 +01:00 committed by GitHub
parent 9d3501d366
commit d053050ed5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 282 additions and 11 deletions

View File

@ -89,6 +89,27 @@ for your instance of babybuddy.
After that, you just have to push babybuddy code repository to the Git After that, you just have to push babybuddy code repository to the Git
deployment URL of your Clever Cloud Python application. deployment URL of your Clever Cloud Python application.
## GCP Cloud Run
Baby Buddy can be hosted serverless in GCP Cloud Run using configuration provided at
`terraform/gcp-cloud-run`. The configuration scales down to zero for cost effectiveness.
With this approach initial requests to the service after a long period will be slow but
subsequent requests will be much faster. A [billing account](https://cloud.google.com/billing/docs/how-to/create-billing-account)
mut be configured in GCP to use the configuration.
The terraform code isn't production ready and is meant to be a good way of getting started.
No state strage is configured. See [storage options](https://cloud.google.com/run/docs/storage-options)
for information about how to configure persistant storage.
Run `terraform init` from the configurtion directory to get started:
```shell
git clone https://github.com/babybuddy/babybuddy.git
cd babybuddy/terraform/gcp-cloud-run
terraform init
terraform apply -var project_id=<project-id> -var project_name=<project-name> -var billing_account=<billing-account-id>
```
## Manual ## Manual
There are many ways to deploy Baby Buddy manually to any server/VPS. The basic There are many ways to deploy Baby Buddy manually to any server/VPS. The basic

View File

@ -0,0 +1,40 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/google" {
version = "5.6.0"
hashes = [
"h1:eZMUVtLYrZMNb5QeqWpWfeQv5wNWQMRhzVtr/Fo5Wis=",
"zh:102b6a2672fade82114eb14ed46923fb1b74be2aaca3a50b4f35f7057a9a94b9",
"zh:1a56b63175068c67efbe7d130986ba2839a938f5ffc96a14fd450153174dbfa3",
"zh:1ba1c5e0c86e8aaa8037406390846e78c89b63faf9e527c7874641f35d436e1b",
"zh:3f7161b9288b47cbe89d2f9675f78d83b58ad5880c793b01f50a71ee2583844b",
"zh:66912d6e4180dac37185d17424b345a9d4e3c3c791d45e0737b35e32c9536b35",
"zh:6f06f56e9fac2e55b50e74ffac42d9522bb379394e51dca1eddd4c3b7a68545c",
"zh:8741861ebfa13bb1ed74ea7f4865388a0725ca3a781b6d873ce45e6a4630fe41",
"zh:ae89a9c538665fbc30bb83aa3b13acb18d8380e551ccf242e1c0ab4d626089ab",
"zh:c510f8321c7599aa601b1870fdc0c76cbad3054ed5cc70fe8e37a13a8046a71f",
"zh:cf143a53d5a25c6216d09a9c0b115bb473ffcebd5c4c62b2b2594b1ebc13e662",
"zh:de05b957e5dfdbaf92db47cd9b3ef46a0f8d94599eea6d472928f33058856add",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.5.1"
hashes = [
"h1:VSnd9ZIPyfKHOObuQCaKfnjIHRtR7qTw19Rz8tJxm+k=",
"zh:04e3fbd610cb52c1017d282531364b9c53ef72b6bc533acb2a90671957324a64",
"zh:119197103301ebaf7efb91df8f0b6e0dd31e6ff943d231af35ee1831c599188d",
"zh:4d2b219d09abf3b1bb4df93d399ed156cadd61f44ad3baf5cf2954df2fba0831",
"zh:6130bdde527587bbe2dcaa7150363e96dbc5250ea20154176d82bc69df5d4ce3",
"zh:6cc326cd4000f724d3086ee05587e7710f032f94fc9af35e96a386a1c6f2214f",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:b6d88e1d28cf2dfa24e9fdcc3efc77adcdc1c3c3b5c7ce503a423efbdd6de57b",
"zh:ba74c592622ecbcef9dc2a4d81ed321c4e44cddf7da799faa324da9bf52a22b2",
"zh:c7c5cde98fe4ef1143bd1b3ec5dc04baf0d4cc3ca2c5c7d40d17c0e9b2076865",
"zh:dac4bad52c940cd0dfc27893507c1e92393846b024c5a9db159a93c534a3da03",
"zh:de8febe2a2acd9ac454b844a4106ed295ae9520ef54dc8ed2faf29f12716b602",
"zh:eab0d0495e7e711cca367f7d4df6e322e6c562fc52151ec931176115b83ed014",
]
}

View File

@ -0,0 +1,187 @@
provider "google" {
region = var.region
}
resource "google_project" "baby_buddy" {
name = var.project_name
project_id = var.project_id
billing_account = var.billing_account
auto_create_network = false
}
locals {
services = toset(["run.googleapis.com",
"sqladmin.googleapis.com",
"sql-component.googleapis.com",
"secretmanager.googleapis.com"
])
}
resource "google_project_service" "project_services" {
for_each = local.services
project = google_project.baby_buddy.project_id
service = each.value
disable_on_destroy = true
disable_dependent_services = true
}
resource "random_password" "root_password" {
min_lower = 1
min_numeric = 1
min_upper = 1
length = 19
special = true
min_special = 1
lifecycle {
ignore_changes = [
min_lower, min_upper, min_numeric, special, min_special, length
]
}
}
resource "random_password" "django_secret_key" {
min_lower = 1
min_numeric = 1
min_upper = 1
length = 20
special = true
min_special = 1
lifecycle {
ignore_changes = [
min_lower, min_upper, min_numeric, special, min_special, length
]
}
}
resource "google_sql_database_instance" "baby_buddy" {
name = "babybuddy"
database_version = "POSTGRES_15"
root_password = random_password.root_password.result
settings {
tier = "db-f1-micro"
disk_autoresize = false
deletion_protection_enabled = false
insights_config {
query_insights_enabled = false
}
maintenance_window {
day = 1
hour = 0
}
}
deletion_protection = "true"
}
resource "google_secret_manager_secret" "postgres_password" {
secret_id = "postgres-password"
project = google_project.baby_buddy.project_id
replication {
auto {}
}
}
resource "google_secret_manager_secret_version" "postgres_password" {
secret = google_secret_manager_secret.postgres_password.name
secret_data = google_sql_database_instance.baby_buddy.root_password
}
resource "google_secret_manager_secret_iam_member" "postgres_password" {
secret_id = google_secret_manager_secret.postgres_password.id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_project.baby_buddy.number}-compute@developer.gserviceaccount.com"
depends_on = [google_secret_manager_secret.postgres_password]
}
resource "google_secret_manager_secret" "django_secret_key" {
secret_id = "django-secret-key"
project = google_project.baby_buddy.project_id
replication {
auto {}
}
}
resource "google_secret_manager_secret_version" "django_secret_key" {
secret = google_secret_manager_secret.django_secret_key.name
secret_data = random_password.django_secret_key.result
}
resource "google_secret_manager_secret_iam_member" "django_secret_key" {
secret_id = google_secret_manager_secret.django_secret_key.name
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_project.baby_buddy.number}-compute@developer.gserviceaccount.com"
depends_on = [google_secret_manager_secret.django_secret_key]
}
resource "google_cloud_run_v2_service" "baby_buddy" {
name = "babybuddy"
location = var.region
ingress = "INGRESS_TRAFFIC_ALL"
project = google_project.baby_buddy.project_id
template {
scaling {
max_instance_count = 2
}
volumes {
name = "cloudsql"
cloud_sql_instance {
instances = [google_sql_database_instance.baby_buddy.connection_name]
}
}
containers {
name = "babybuddy-1"
image = "docker.io/linuxserver/babybuddy:latest"
env {
name = "DB_HOST"
value = "/cloudsql/${google_project.baby_buddy.project_id}:${var.region}:${google_sql_database_instance.baby_buddy.name}"
}
env {
name = "DB_USER"
value = "postgres"
}
env {
name = "DB_NAME"
value = "postgres"
}
env {
name = "DB_ENGINE"
value = "django.db.backends.postgresql"
}
env {
name = "DB_PASSWORD"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.postgres_password.secret_id
version = google_secret_manager_secret_version.postgres_password.version
}
}
}
env {
name = "SECRET_KEY"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.django_secret_key.secret_id
version = google_secret_manager_secret_version.django_secret_key.version
}
}
}
volume_mounts {
name = "cloudsql"
mount_path = "/cloudsql"
}
}
}
annotations = {
"foo" = "bar"
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
depends_on = [google_secret_manager_secret_version.postgres_password, google_secret_manager_secret_version.django_secret_key]
}

View File

@ -0,0 +1,3 @@
output "url" {
value = google_cloud_run_v2_service.baby_buddy.uri
}

View File

@ -0,0 +1,20 @@
variable "project_name" {
description = "project name"
type = string
}
variable "project_id" {
description = "project id, remember the project id has to be unique"
type = string
}
variable "billing_account" {
description = "value of the billing account id"
type = string
}
variable "region" {
description = "which region to deploy to"
type = string
default = "europe-north1"
}