Three Tier App adalah aplikasi daftar tugas sederhana yang dirancang sebagai aplikasi vanila 3 tingkat:
- Backend
- Database - MySQL - Cloud SQL
- Menyimpan ke Cache - Redis - Cloud Memorystore
- Middleware/API
- API yang dihosting container - Golang - Cloud Run
- Tampilan Depan/UI
- UI yang dihosting container - Nginx + HTML/JS/CSS - Cloud Run
- Deployment
- Deployment Berkelanjutan - Cloud Build
- Secret Management - Cloud Secret Manager
Mulai
Klik link berikut untuk mendapatkan salinan kode sumber di Cloud Shell. Setelah ada, satu perintah akan menjalankan salinan aplikasi yang berfungsi di project Anda..
Komponen Aplikasi Tiga Tingkat
Arsitektur Aplikasi Tiga Tingkat menggunakan beberapa produk. Berikut ini daftar komponen, beserta informasi selengkapnya tentang komponen, termasuk link ke video terkait, dokumentasi produk, dan panduan interaktif.Skrip
Skrip penginstalan menggunakan file yang dapat dieksekusi yang ditulis di alat CLI Terraform dan go
untuk mengambil project kosong dan menginstal aplikasi di dalamnya. Output harus berupa aplikasi yang berfungsi dan URL untuk alamat IP load balancing.
./main.tf
Mengaktifkan layanan
Layanan Google Cloud dinonaktifkan dalam project secara default. ToDo mengharuskan Anda mengaktifkan layanan berikut:
- Jaringan Layanan & Akses VPC Serverless - memungkinkan Cloud Run untuk Berkomunikasi dengan SQL dan Redis di jaringan pribadi, sehingga server ini tidak dapat diakses dari panggilan luar yang berasal dari API.
- Cloud Build - membuat image container dan men-deploy ke Cloud Run
- Cloud Memorystore - menyediakan lapisan cache untuk aplikasi.
- Cloud Run - alat serverless yang akan menghosting container, dan menyediakan URL tempat mengakses aplikasi.
- Cloud SQL - penyimpanan database untuk aplikasi
- Cloud Storage - digunakan oleh Cloud Build dan untuk memuat skema di database
- Cloud Secret Manager - digunakan untuk memasukkan ip host untuk SQL dan Redis ke dalam Cloud Build for Cloud Run.
- Artifact Registry - menyimpan image Docker untuk digunakan dengan Cloud Build.
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
}
Tetapkan izin
Perintah berikut menetapkan Peran dan Izin IAM yang memungkinkan Cloud Build men-deploy layanan.
- Mengaktifkan Akun Layanan Cloud Build untuk men-deploy ke Cloud Run
- Aktifkan Akun Layanan Cloud Build untuk menetapkan Akses VPN untuk Cloud Run
- Mengaktifkan Akun Layanan Cloud Build untuk menjalankan aktivitas Akun Layanan
- Aktifkan Akun Layanan Cloud Build untuk bertindak atas nama Akun Layanan Compute
- Aktifkan Akun Layanan Cloud Build untuk memublikasikan ke Cloud Run
- Mengaktifkan Akun Layanan Cloud Build untuk menggunakan secret
- Aktifkan Akun Layanan Cloud Build untuk menyimpan container di Artifact Registry
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]
}
Membuat jaringan untuk instance SQL
Perintah berikut memungkinkan Cloud SQL dapat diakses dari Cloud Run:
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]
}
Buat konektor akses VPC
Menghubungkan Cloud Run ke Database dan 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]
}
Membuat Server Redis
Mengonfigurasi dan melakukan inisialisasi instance server Redis.
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]
}
Membuat server SQL
Perintah berikut mengonfigurasi dan menginisialisasi instance server SQL.
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}"
}
}
Membuat repositori Artifact Registry
Perintah berikut menyimpan Image Docker untuk digunakan dengan Cloud Run.
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]
}
Membuat secret
Perintah berikut menyimpan data host Redis dan SQL di Cloud Secrets.
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]
}
Membuat artefak untuk middleware
Perintah berikut membuat image Docker dan menghostingnya di Artifact Registry: ./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
]
}
Men-deploy container API ke Cloud Run
Perintah berikut menggunakan Cloud Build untuk menjalankan layanan di Cloud Run menggunakan container yang baru saja Anda bangun.
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
]
}
Membuka Layanan Cloud Run API agar dapat dibaca oleh semua orang.
Lapisan API aplikasi ini akan dipanggil oleh browser pengguna, tetapi secara default layanan Cloud Run tidak bersifat publik. Agar pengguna dapat menggunakan layanan ini, kita harus membuka izin pada layanan ini agar dapat diakses oleh dunia.
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
}
Membuat artefak untuk front end
Perintah berikut membuat image Docker dan menghostingnya di Artifact Registry: ./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
]
}
Men-deploy container front end ke Cloud Run
Perintah berikutnya menggunakan Cloud Build untuk menjalankan layanan di Cloud Run menggunakan container yang baru saja kita bangun
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]
}
Membuka layanan frontend Cloud Run agar dapat dibaca di seluruh dunia
Ini adalah frontend aplikasi, yang akan merender HTML/JS/CSS yang digunakan pengguna untuk berinteraksi dengan aplikasi - secara default layanan Cloud Run tidak bersifat publik. Agar aplikasi ini dapat berfungsi, kami harus membuka izin pada layanan ini agar dapat diakses oleh dunia.
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
Menginisialisasi skema database
Perintah ini membuat bucket Cloud Storage sementara untuk mengupload skema ke Cloud SQL.
PROJECT=$1
SQLNAME=$2
SQLSERVICEACCOUNT=$(gcloud sql instances describe $SQLNAME --format="value(serviceAccountEmailAddress)" | xargs)
gsutil mb gs://$PROJECT-temp
gsutil cp schema.sql gs://$PROJECT-temp/schema.sql
gsutil iam ch serviceAccount:$SQLSERVICEACCOUNT:objectViewer gs://$PROJECT-temp/
gcloud sql import sql $SQLNAME gs://$PROJECT-temp/schema.sql -q
gsutil rm gs://$PROJECT-temp/schema.sql
gsutil rb gs://$PROJECT-temp
./code/middleware/clouldbuild.yaml
Membangun penampung API
Kode ini membuat image Docker untuk lapisan middleware.
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']
Substitusi
Kode berikut membuat variabel dengan nilai default sehingga nilai tersebut dapat diubah pada waktu deployment.
substitutions:
_REGION: us-central1
_BASENAME: todo
./code/frontend/clouldbuild.yaml
Konten kode pijat
Tampilan depan benar-benar statis/JS/CSS. Aplikasi harus mengarah ke URL untuk layanan API yang baru saja kita buat, tetapi layanan Cloud Run diberi URL dengan string acak. 'Skrip pijat' ini menangkap URL acak dan memasukkannya ke dalam kode JS statis dalam container ini.
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: bash
args: [ './massage.sh', '$_REGION' ]
Membangun penampung API
Kode berikut membuat image Docker untuk lapisan middleware:
name: 'gcr.io/cloud-builders/docker'
args: [ 'build', '-t', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/fe', '.' ]
Mengirim container API ke Artifact Registry
Mengirim container ke Artifact Registry memungkinkan Cloud Run mendapatkan image dan menayangkannya.
name: 'gcr.io/cloud-builders/docker'
args: ['push', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_BASENAME-app/fe']
Substitusi
Buat variabel dengan default agar nilai tersebut dapat diubah pada waktu deployment.
substitutions:
_REGION: us-central1
_BASENAME: todo
./code/frontend/massage.sh
Edit JavaScript
Perintah ini memasukkan endpoint untuk Middleware ke JavaScript front end.
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
Kesimpulan
Anda kini memiliki aplikasi daftar tugas 3 tingkat sederhana yang berjalan di Cloud Run di project Anda. Anda juga memiliki semua kode untuk dimodifikasi atau memperluas solusi ini agar sesuai dengan lingkungan Anda.