8435ad85f3 | ||
---|---|---|
.. | ||
images | ||
README.md | ||
alb.tf | ||
cloudrun.tf | ||
dns.tf | ||
main.tf | ||
outputs.tf | ||
psc.tf | ||
variables.tf | ||
vpc.tf |
README.md
Cloud Run Microservices
Introduction
This blueprint contains all the necessary Terraform modules to deploy two microservices running in Cloud Run and communicating with each other.
The content of this blueprint corresponds to the chapter 'Microservices architectures - Developing Microservices applications' of the Serverless Networking Guide. This guide is an easy to follow introduction to Cloud Run, where a couple of friendly characters will guide you from the basics to more advanced topics with a very practical approach and in record time! The code here complements this learning and allows you to test the scenarios presented and your knowledge.
If you are interested in following this guide, take a look to the chapters' blueprints:
- Exploring Cloud Run - My serverless "Hello, World!"
- The corporate environment - Developing an enterprise application
- Microservices architectures - Developing Microservices applications
Prerequisites
Depending on the use case, you will need one or two projects with billing enabled and a user with the “Project owner” IAM role on those projects. You can use existing projects or let the blueprint create them for you but in that case you will need to add extra information for each project. E.g.:
project_configs = {
main = {
billing_account_id = "ABCDE-12345-ABCDE"
parent = "organizations/0123456789"
project_id = "spiritual-hour-331417"
}
}
How to set this information is explained below.
Spinning up the architecture
General steps
- Clone the repo to your local machine or Cloud Shell:
git clone https://github.com/GoogleCloudPlatform/cloud-foundation-fabric
- Change to the directory of the blueprint:
cd cloud-foundation-fabric/blueprints/serverless/cloud-run-microservices
You should see this README and some terraform files.
- To deploy a specific use case, you will need to create a file in this directory called
terraform.tfvars
and follow the corresponding instructions to set variables. Values that are meant to be substituted will be shown inside brackets but you need to omit these brackets. E.g.:
project_configs = {
main = {
project_id = "[project_id]"
}
}
may become
project_configs = {
main = {
project_id = "spiritual-hour-331417"
}
}
Use cases are self-contained so you can deploy any of them at will.
- The usual terraform commands will do the work:
terraform init
terraform plan
terraform apply
It will take a few minutes. When complete, you should see an output stating the command completed successfully, a list of the created resources, and some output variables with information to access your services.
Congratulations! You have successfully deployed the use case you chose based on the variables configuration.
Use case 1: Service to service communication in the same project
This use case deploys two Cloud Run services in the same project. Service B is protected as an internal only service and communication between Cloud Run services, even in the same project, is not considered internal by default. To communicate them, one option is to use PSC/PGA (the second option is shown in the use case 2). We will use a PSC endpoint and a Serverless VPC connector to reach Service B. A DNS record for the PSC endpoint is created.
Service A uses an application with a GUI to test connectivity. You can find its source code in:
https://github.com/willypalacin/vpc-network-tester/tree/main
You will need to build an image and push it to Artifact Registry, setting the corresponding Terraform variable to its URL. Add the main project ID in terraform.tfvars
. E.g.:
image_configs = {
svc_a = "us-docker.pkg.dev/[project-id]/[repo-name]/[tester-app]"
}
prefix = "[prefix]"
project_configs = {
main = {
project_id = "[project_id]"
}
}
Note that final project ids will be of the form "[prefix]-[project-id]".
The service B default URL is created and shown as a terraform output variable. It will be similar to the one shown in the picture above. Get into service A and try to reach service B URL as shown below:
You can see service A is resolving service B to an internal IP, 10.0.0.100, the PSC endpoint (see variable 'ip_configs'). Public access is restricted, if you try to e.g. curl
from your laptop you will get an error.
Use case 2: Service to service communication in different projects
The second option for internal service to service communication is to use an internal Application Load Balancer (ALB). This use case extends the previous architecture using a Shared VPC and a service project. Instead of a VPC connector, it uses Direct VPC Egress which allows Cloud Run to directly use IPs from a subnet. And the ALB allows you to use a custom domain.
Set the following in terraform.tfvars
:
image_configs = {
svc_a = "us-docker.pkg.dev/[project-id]/[repo-name]/[tester-app]"
}
prefix = "[prefix]"
project_configs = {
main = { # Used as host project
project_id = "[project_id]"
}
service = {
project_id = "[project_id]"
}
}
The blueprint uses an HTTP connection to the ALB to avoid management of SSL certificates. Try to reach service B custom URL as shown below:
Cleaning up your environment
The easiest way to remove all the deployed resources is to run the following command:
terraform destroy
The above command will delete the associated resources so there will be no billable charges afterwards. Projects are removed from Terraform state but not deleted from Google Cloud.
Files
name | description | modules | resources |
---|---|---|---|
alb.tf | Internal Application Load Balancer resource. | net-lb-app-int |
|
cloudrun.tf | Cloud Run services. | cloud-run-v2 |
|
dns.tf | DNS resources. | dns |
|
main.tf | Project resources. | project |
|
outputs.tf | Module outputs. | ||
psc.tf | Private Service Connect resources. | net-address |
google_compute_global_forwarding_rule |
variables.tf | Module variables. | ||
vpc.tf | VPC resources. | net-vpc |
Variables
name | description | type | required | default |
---|---|---|---|---|
image_configs | Container images for Cloud Run services. | object({…}) |
✓ | |
prefix | Prefix used for project names. | string |
✓ | |
custom_domain | Custom domain for the Load Balancer. | string |
"service-b.acme.org" |
|
ip_configs | IP ranges or IPs used by the VPC. | map(string) |
{…} |
|
project_configs | Projects to use, one project or host and service projects. | map(object({…})) |
{…} |
|
region | Cloud region where resources will be deployed. | string |
"europe-west1" |
Outputs
name | description | sensitive |
---|---|---|
custom_domain | Custom domain for the Application Load Balancer. | |
default_URLs | Cloud Run services default URLs. | |
load_balancer_ip | Load Balancer IP address. |
Tests
module "test" {
source = "./fabric/blueprints/serverless/cloud-run-microservices"
image_configs = {
svc_a = "cloud-run-image"
}
prefix = "prefix"
project_configs = {
main = {
billing_account_id = "ABCDE-12345-ABCDE"
parent = "organizations/0123456789"
project_id = "main-project-id"
}
}
}
# tftest modules=7 resources=22
module "test" {
source = "./fabric/blueprints/serverless/cloud-run-microservices"
image_configs = {
svc_a = "cloud-run-image"
}
prefix = "prefix"
project_configs = {
main = { # Used as host project
billing_account_id = "ABCDE-12345-ABCDE"
parent = "organizations/0123456789"
project_id = "main-project-id"
}
service = {
billing_account_id = "ABCDE-12345-ABCDE"
parent = "organizations/0123456789"
project_id = "service-project-id"
}
}
}
# tftest modules=10 resources=32