Die dreistufige App ist eine einfache To-do-Anwendung, die als einfache dreistufige Anwendung konzipiert wurde:
- Backend
- Datenbank – MySQL – Cloud SQL
- Caching – Redis – Cloud Memorystore
- Middleware/API
- Containergehostete API – Golang – Cloud Run
- Frontend/UI
- Container-gehostete UI – Nginx + HTML/JS/CSS – Cloud Run
- Bereitstellung
- Kontinuierliche Bereitstellung – Cloud Build
- Secret Management – Cloud Secret Manager
Jetzt starten
Klicken Sie auf den folgenden Link, um den Quellcode in Cloud Shell zu kopieren. Dort können Sie mit einem einzigen Befehl eine funktionierende Kopie der Anwendung in Ihrem Projekt erstellen.
Dreistufige App-Komponenten
Die dreistufige App-Architektur nutzt mehrere Produkte. Im Folgenden sind die Komponenten aufgeführt sowie weitere Informationen zu den Komponenten, Komponenten, einschließlich Links zu ähnlichen Videos, Produktdokumentation und interaktiven Schritt-für-Schritt-Anleitungen.Skripts
Das Installationsskript verwendet eine in go
geschriebene ausführbare Datei und Terraform-Befehlszeilentools, um ein leeres Projekt zu erstellen und die Anwendung darin zu installieren. Die Ausgabe sollte eine funktionierende Anwendung und eine URL für die Load Balancing-IP-Adresse sein.
./main.tf
Dienste aktivieren
Google Cloud-Dienste sind in einem Projekt standardmäßig deaktiviert. Für Google ToDo müssen Sie die folgenden Dienste aktivieren:
- Servicenetzwerke und Serverloser VPC-Zugriff: Cloud Run kann Kommunizieren Sie in einem privaten Netzwerk mit SQL und Redis und lassen Sie diese Server für externe Aufrufe, die von der API kommen, nicht zugänglich sind.
- Cloud Build: Erstellt Container-Images und stellt sie in Cloud Run bereit
- Cloud Memorystore: Bietet eine Caching-Ebene für die Anwendung.
- Cloud Run: Das serverlose Tool, das die Container hostet und URLs bereitstellt, über die auf die Anwendung zugegriffen werden kann.
- Cloud SQL: Datenbankspeicher für die Anwendung
- Cloud Storage – wird von Cloud Build verwendet und zum Laden des Schemas in den Datenbank
- Cloud Secret Manager – wird zum Injizieren der Host-IPs für SQL und Redis verwendet in Cloud Build für Cloud Run ein.
- Artifact Registry: Hier werden die Docker-Images für die Verwendung mit Cloud Build gespeichert.
variable "gcp_service_list" {
description = "The list of apis necessary for the project"
type = list(string)
default = [
"compute.googleapis.com",
"cloudapis.googleapis.com",
"vpcaccess.googleapis.com",
"servicenetworking.googleapis.com",
"cloudbuild.googleapis.com",
"sql-component.googleapis.com",
"sqladmin.googleapis.com",
"storage.googleapis.com",
"secretmanager.googleapis.com",
"run.googleapis.com",
"artifactregistry.googleapis.com",
"redis.googleapis.com"
]
}
resource "google_project_service" "all" {
for_each = toset(var.gcp_service_list)
project = var.project_number
service = each.key
disable_on_destroy = false
}
Berechtigungen festlegen
Mit dem folgenden Befehl werden IAM-Rollen und -Berechtigungen festgelegt, die Cloud Build das Bereitstellen von Diensten ermöglichen.
- Cloud Build-Dienstkonto für die Bereitstellung in Cloud Run aktivieren
- Aktivieren Sie das Cloud Build-Dienstkonto, um den VPN-Zugriff für Cloud Run festzulegen
- Aktivieren Sie das Cloud Build-Dienstkonto, um Dienstkontoaktivitäten auszuführen
- Cloud Build-Dienstkonto zulassen, im Namen des Compute-Dienstkontos zu handeln
- Cloud Build-Dienstkonto für die Veröffentlichung in Cloud Run aktivieren
- Cloud Build-Dienstkonto zum Verwenden von Secrets aktivieren
- Cloud Build-Dienstkonto zum Speichern von Containern in Artifact Registry aktivieren
variable "build_roles_list" {
description = "The list of roles that build needs for"
type = list(string)
default = [
"roles/run.developer",
"roles/vpaccess.user",
"roles/iam.serviceAccountUser",
"roles/run.admin",
"roles/secretmanager.secretAccessor",
"roles/artifactregistry.admin",
]
}
resource "google_project_iam_member" "allbuild" {
for_each = toset(var.build_roles_list)
project = var.project_number
role = each.key
member = "serviceAccount:${local.sabuild}"
depends_on = [google_project_service.all]
}
Netzwerk für SQL-Instanz erstellen
Mit dem folgenden Befehl können Sie Cloud SQL von Cloud Run aus aufrufen:
resource "google_compute_global_address" "google_managed_services_vpn_connector" {
name = "google-managed-services-vpn-connector"
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = local.defaultnetwork
project = var.project_id
depends_on = [google_project_service.all]
}
resource "google_service_networking_connection" "vpcpeerings" {
network = local.defaultnetwork
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.google_managed_services_vpn_connector.name]
}
VPC-Zugriffs-Connector erstellen
Verbindet Cloud Run mit einer Datenbank und Caching
resource "google_vpc_access_connector" "connector" {
provider = google-beta
project = var.project_id
name = "vpc-connector"
ip_cidr_range = "10.8.0.0/28"
network = "default"
region = var.region
depends_on = [google_compute_global_address.google_managed_services_vpn_connector, google_project_service.all]
}
Redis-Server erstellen
Konfiguriert und initialisiert eine Redis-Serverinstanz.
resource "google_redis_instance" "todo_cache" {
authorized_network = local.defaultnetwork
connect_mode = "DIRECT_PEERING"
location_id = var.zone
memory_size_gb = 1
name = "${var.basename}-cache"
project = var.project_id
redis_version = "REDIS_6_X"
region = var.region
reserved_ip_range = "10.137.125.88/29"
tier = "BASIC"
transit_encryption_mode = "DISABLED"
depends_on = [google_project_service.all]
}
SQL-Server erstellen
Mit dem folgenden Befehl wird eine SQL Server-Instanz konfiguriert und initialisiert.
resource "google_sql_database_instance" "todo_database" {
name="${var.basename}-db-${random_id.id.hex}"
database_version = "MYSQL_5_7"
region = var.region
project = var.project_id
settings {
tier = "db-g1-small"
disk_autoresize = true
disk_autoresize_limit = 0
disk_size = 10
disk_type = "PD_SSD"
ip_configuration {
ipv4_enabled = false
private_network = local.defaultnetwork
}
location_preference {
zone = var.zone
}
}
deletion_protection = false
depends_on = [
google_project_service.all,
google_service_networking_connection.vpcpeerings
]
# This handles loading the schema after the database installs.
provisioner "local-exec" {
working_dir = "${path.module}/code/database"
command = "./load_schema.sh ${var.project_id} ${google_sql_database_instance.todo_database.name}"
}
}
Artifact Registry-Repository erstellen
Mit dem folgenden Befehl werden Docker-Images für die Verwendung mit Cloud Run gespeichert.
resource "google_artifact_registry_repository" "todo_app" {
provider = google-beta
format = "DOCKER"
location = var.region
project = var.project_id
repository_id = "${var.basename}-app"
depends_on = [google_project_service.all]
}
Secrets erstellen
Mit dem folgenden Befehl werden Redis- und SQL-Hostdaten in Cloud Secrets gespeichert.
resource "google_secret_manager_secret" "redishost" {
project = var.project_number
replication {
automatic = true
}
secret_id = "redishost"
depends_on = [google_project_service.all]
}
resource "google_secret_manager_secret_version" "redishost" {
enabled = true
secret = "projects/${var.project_number}/secrets/redishost"
secret_data = google_redis_instance.todo_cache.host
depends_on = [google_project_service.all, google_redis_instance.todo_cache, google_secret_manager_secret.redishost]
}
resource "google_secret_manager_secret" "sqlhost" {
project = var.project_number
replication {
automatic = true
}
secret_id = "sqlhost"
depends_on = [google_project_service.all]
}
resource "google_secret_manager_secret_version" "sqlhost" {
enabled = true
secret = "projects/${var.project_number}/secrets/sqlhost"
secret_data = google_sql_database_instance.todo_database.private_ip_address
depends_on = [google_project_service.all, google_sql_database_instance.todo_database, google_secret_manager_secret.sqlhost]
}
Artefakt für die Middleware erstellen
Mit dem folgenden Befehl wird das Docker-Image erstellt und in Artifact Registry gehostet: ./code/frontend/clouldbuild.yaml
resource "null_resource" "cloudbuild_api" {
provisioner "local-exec" {
working_dir = "${path.module}/code/middleware"
command = "gcloud builds submit . --substitutions=_REGION=${var.region},_BASENAME=${var.basename}"
}
depends_on = [
google_artifact_registry_repository.todo_app,
google_secret_manager_secret_version.redishost,
google_secret_manager_secret_version.sqlhost,
google_project_service.all
]
}
API-Container in Cloud Run bereitstellen
Mit dem folgenden Befehl wird mit Cloud Build ein Dienst in Cloud Run mit dem gerade erstellten Container gestartet.
resource "google_cloud_run_service" "api" {
name = "${var.basename}-api"
location = var.region
project = var.project_id
template {
spec {
containers {
image = "${var.region}-docker.pkg.dev/${var.project_id}/${var.basename}-app/api"
env {
name = "REDISHOST"
value_from {
secret_key_ref {
name = google_secret_manager_secret.redishost.secret_id
key = "latest"
}
}
}
env {
name = "todo_host"
value_from {
secret_key_ref {
name = google_secret_manager_secret.sqlhost.secret_id
key = "latest"
}
}
}
env {
name = "todo_user"
value = "todo_user"
}
env {
name = "todo_pass"
value = "todo_pass"
}
env {
name = "todo_name"
value = "todo"
}
env {
name = "REDISPORT"
value = "6379"
}
}
}
metadata {
annotations = {
"autoscaling.knative.dev/maxScale" = "1000"
"run.googleapis.com/cloudsql-instances" = google_sql_database_instance.todo_database.connection_name
"run.googleapis.com/client-name" = "terraform"
"run.googleapis.com/vpc-access-egress" = "all"
"run.googleapis.com/vpc-access-connector" = google_vpc_access_connector.connector.id
}
}
}
autogenerate_revision_name = true
depends_on = [
null_resource.cloudbuild_api,
google_project_iam_member.secretmanager_secretAccessor
]
}
Öffnen Sie den Cloud Run API-Dienst, damit er von allen gelesen werden kann.
Diese API-Ebene der Anwendung wird vom Browser des Nutzers aufgerufen, aber durch Cloud Run-Standarddienste sind nicht öffentlich. Damit Nutzer diesen Dienst nutzen können, müssen wir Berechtigungen für diese Dienste gewähren, damit sie weltweit zugänglich sind.
resource "google_cloud_run_service_iam_policy" "noauth_api" {
location = google_cloud_run_service.api.location
project = google_cloud_run_service.api.project
service = google_cloud_run_service.api.name
policy_data = data.google_iam_policy.noauth.policy_data
}
Artefakt für das Frontend erstellen
Mit dem folgenden Befehl wird das Docker-Image erstellt und in Artifact Registry gehostet: ./code/frontend/clouldbuild.yaml
resource "null_resource" "cloudbuild_fe" {
provisioner "local-exec" {
working_dir = "${path.module}/code/frontend"
command = "gcloud builds submit . --substitutions=_REGION=${var.region},_BASENAME=${var.basename}"
}
depends_on = [
google_artifact_registry_repository.todo_app,
google_cloud_run_service.api
]
}
Frontend-Container in Cloud Run bereitstellen
Im nächsten Befehl wird mit Cloud Build ein Dienst in Cloud Run mit dem soeben erstellten Container gestartet.
resource "google_cloud_run_service" "fe" {
name = "${var.basename}-fe"
location = var.region
project = var.project_id
template {
spec {
containers {
image = "${var.region}-docker.pkg.dev/${var.project_id}/${var.basename}-app/fe"
ports {
container_port = 80
}
}
}
}
depends_on = [null_resource.cloudbuild_fe]
}
Cloud Run-Frontenddienst für alle lesbar öffnen
Dies ist das Frontend der Anwendung, das die HTML/JS/CSS rendert. durch die der Nutzer mit der Anwendung interagiert (standardmäßig Cloud Run-Dienste) sind nicht öffentlich. Damit diese Anwendung funktioniert, müssen wir Berechtigungen für diese Dienste, um für die Welt zugänglich zu sein.
resource "google_cloud_run_service_iam_policy" "noauth_fe" {
location = google_cloud_run_service.fe.location
project = google_cloud_run_service.fe.project
service = google_cloud_run_service.fe.name
policy_data = data.google_iam_policy.noauth.policy_data
}
./code/database/load_schema.sh
Datenbankschema initialisieren
Mit diesem Befehl wird ein temporärer Cloud Storage-Bucket erstellt, um das Schema in Cloud SQL hochzuladen.
PROJECT=$1
SQLNAME=$2
SQLSERVICEACCOUNT=$(gcloud sql instances describe $SQLNAME --format="value(serviceAccountEmailAddress)" | xargs)
gcloud storage buckets create gs://$PROJECT-temp
gcloud storage cp schema.sql gs://$PROJECT-temp/schema.sql
gcloud storage buckets add-iam-policy-binding gs://$PROJECT-temp/ --member=serviceAccount:$SQLSERVICEACCOUNT --role=roles/storage.objectViewer
gcloud sql import sql $SQLNAME gs://$PROJECT-temp/schema.sql -q
gcloud storage rm gs://$PROJECT-temp --recursive
./code/middleware/clouldbuild.yaml
API-Container erstellen
Mit diesem Code wird ein Docker-Image für die Middleware-Ebene erstellt.
name: 'gcr.io/cloud-builders/docker'
args: [ 'build', '-t', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/api', '.' ]
```
#### Push API container to Artifact Registry
Pushing the container to Artifact Registry makes it possible for Cloud Run to
get the image and serve it.
``` yaml
name: 'gcr.io/cloud-builders/docker'
args: ['push', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/api']
Ersetzungen
Im folgenden Code werden Variablen mit Standardwerten erstellt, damit diese Werte zum Zeitpunkt der Bereitstellung geändert werden können.
substitutions:
_REGION: us-central1
_BASENAME: todo
./code/frontend/clouldbuild.yaml
Inhalt des Massagecodes
Das Frontend ist vollständig statisch (HTML/JS/CSS). Die App muss auf die URL für die API-Dienst, den wir gerade erstellt haben. Cloud Run-Diensten wird jedoch eine URL mit einer zufälligen . Dieses „Massageskript“ erfasst diese zufällige URL und fügt sie in den Code ein. des statischen JS in diesem Container.
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: bash
args: [ './massage.sh', '$_REGION' ]
API-Container erstellen
Mit dem folgenden Code wird ein Docker-Image für die Middleware-Ebene erstellt:
name: 'gcr.io/cloud-builders/docker'
args: [ 'build', '-t', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/fe', '.' ]
API-Container per Push in die Artifact Registry übertragen
Wenn Sie den Container in Artifact Registry übertragen, kann Cloud Run das Image abrufen und bereitstellen.
name: 'gcr.io/cloud-builders/docker'
args: ['push', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/fe']
Ersetzungen
Erstellen Sie eine Variable mit einem Standardwert, damit diese Werte bei der Bereitstellung geändert werden können.
substitutions:
_REGION: us-central1
_BASENAME: todo
./code/frontend/massage.sh
JavaScript bearbeiten
Mit diesem Befehl wird der Endpunkt für die Middleware in den JavaScript-Code des Frontends eingefügt.
API=$(gcloud run services describe todo-api --region=$1 --format="value(status.url)")
stripped=$(echo ${API/https:\/\//})
sed -i"" -e "s/127.0.0.1:9000/$stripped/" www/js/main.js
Fazit
Sie haben jetzt eine einfache dreistufige Aufgabenanwendung, die in Cloud ausgeführt wird In Ihrem Projekt ausführen Außerdem haben Sie Zugriff auf den gesamten Code, um diese Lösung an Ihre Umgebung anzupassen oder zu erweitern.