Automating Multi-Region Redundancy for C++ Architectures on Google Cloud
From the GCP Console or using gcloud, create a read replica in your secondary region. This replica will automatically synchronize with the primary instance.
Using gcloud:
gcloud sql instances create my-app-db-replica \ --master-instance-name=my-app-db-primary \ --region=us-east1 \ --project=your-gcp-project-id \ --database-version=POSTGRES_14 \ --tier=db-f1-micro # Adjust tier as needed
Important Considerations:
- Replication Lag: Monitor replication lag using Cloud Monitoring. High lag can impact RPO (Recovery Point Objective).
- Failover Promotion: In a disaster scenario, the read replica must be promoted to a standalone instance. This is a manual or automated step.
- Write Operations: The replica is read-only. Your application must be designed to direct writes only to the primary instance.
C++ Microservice Deployment: Managed Instance Groups and CI/CD
We’ll deploy stateless C++ microservices using GCE Managed Instance Groups (MIGs). This provides auto-scaling, auto-healing, and rolling updates.
1. Containerization (Recommended):
While not strictly required, containerizing your C++ application (e.g., using Docker) simplifies deployment and ensures consistency across environments. A typical Dockerfile might look like this:
FROM ubuntu:22.04 AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN cmake . && make
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \ # Example dependency for PostgreSQL client
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/your_cpp_app /usr/local/bin/your_cpp_app
CMD ["/usr/local/bin/your_cpp_app"]
2. Cloud Build Configuration:
A cloudbuild.yaml file orchestrates the build and deployment process. This example assumes you’re building a container image and pushing it to Google Container Registry (GCR) or Artifact Registry.
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/your-cpp-app:$COMMIT_SHA', '.']
# Push the container image to GCR
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/your-cpp-app:$COMMIT_SHA']
# Deploy to the primary region's MIG
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args:
- compute
- instance-groups
- managed
- update-template
- your-cpp-app-mig-primary
- --template-file=instance-template-primary.yaml
- --region=us-central1
- --project=your-gcp-project-id
# Deploy to the secondary region's MIG (for active-passive, this might be a manual step or triggered by failover)
# For active-active, you'd deploy here as well.
# - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
# entrypoint: gcloud
# args:
# - compute
# - instance-groups
# - managed
# - update-template
# - your-cpp-app-mig-secondary
# - --template-file=instance-template-secondary.yaml
# - --region=us-east1
# - --project=your-gcp-project-id
images:
- 'gcr.io/$PROJECT_ID/your-cpp-app:$COMMIT_SHA'
3. Instance Template (instance-template-primary.yaml):
name: your-cpp-app-template-primary
machineType: n1-standard-1 # Adjust as needed
diskSizeGb: '10'
disks:
- boot: true
autoDelete: true
initializeParams:
sourceImage: projects/google-containers/global/images/container-vm
diskType: pd-standard
diskSizeGb: '10'
networkInterfaces:
- network: projects/your-gcp-project-id/global/networks/default
accessConfigs:
- type: ONE_TO_ONE_NAT
name: External NAT
tags:
items:
- http-server
- https-server
metadata:
items:
- key: google-container-deployment
value: |
{
"container": {
"image": "gcr.io/your-gcp-project-id/your-cpp-app:$COMMIT_SHA",
"ports": [{"containerPort": 8080}]
}
}
- key: startup-script
value: |
#!/bin/bash
# Optional: Add any pre-start commands here, e.g., database connection checks
echo "Starting C++ application..."
4. Managed Instance Groups (MIGs):
Create MIGs in each region, referencing the instance template. Configure auto-scaling based on CPU utilization or custom metrics.
# Primary Region MIG gcloud compute instance-groups managed create your-cpp-app-mig-primary \ --template=your-cpp-app-template-primary \ --size=2 \ --region=us-central1 \ --project=your-gcp-project-id # Secondary Region MIG (initially scaled down or inactive for active-passive) gcloud compute instance-groups managed create your-cpp-app-mig-secondary \ --template=your-cpp-app-template-secondary \ --size=0 \ --region=us-east1 \ --project=your-gcp-project-id
Global Load Balancing and DNS for Failover
A global external HTTP(S) load balancer is crucial for directing traffic to the active region and enabling automated failover.
1. Backend Services:
Create separate backend services for each region's MIG. Configure health checks to monitor the availability of your C++ application instances.
# Health Check gcloud compute health-checks create http my-app-health-check \ --request-path=/health \ --port=8080 \ --check-interval=10s \ --timeout=5s \ --unhealthy-threshold=3 \ --healthy-threshold=2 \ --project=your-gcp-project-id # Backend Service for Primary Region gcloud compute backend-services create my-app-backend-primary \ --protocol=HTTP \ --port-name=http \ --health-checks=my-app-health-check \ --global \ --project=your-gcp-project-id gcloud compute backend-services add-backend my-app-backend-primary \ --instance-group=your-cpp-app-mig-primary \ --instance-group-region=us-central1 \ --global \ --project=your-gcp-project-id # Backend Service for Secondary Region (initially disabled or with low priority) gcloud compute backend-services create my-app-backend-secondary \ --protocol=HTTP \ --port-name=http \ --health-checks=my-app-health-check \ --global \ --project=your-gcp-project-id gcloud compute backend-services add-backend my-app-backend-secondary \ --instance-group=your-cpp-app-mig-secondary \ --instance-group-region=us-east1 \ --global \ --project=your-gcp-project-id
2. URL Map and Forwarding Rule:
Configure a URL map to route traffic to the backend services. For active-passive, you'll set up a primary and a backup backend service. The global forwarding rule will point to this URL map.
# URL Map gcloud compute url-maps create my-app-url-map \ --default-service=my-app-backend-primary \ --project=your-gcp-project-id # Add a backend for failover gcloud compute url-maps add-backend my-app-url-map \ --default-service=my-app-backend-secondary \ --priority=10 \ --global \ --project=your-gcp-project-id # Global Forwarding Rule (using a static IP) gcloud compute addresses create my-app-global-ip \ --ip-version=IPV4 \ --global \ --project=your-gcp-project-id gcloud compute forwarding-rules create my-app-forwarding-rule \ --address=my-app-global-ip \ --target-http-proxy=$(gcloud compute target-http-proxies create my-app-http-proxy --url-map=my-app-url-map --global --project=your-gcp-project-id --format='value(name)') \ --ports=80 \ --global \ --project=your-gcp-project-id
3. Cloud DNS Configuration:
Point your application's domain name (e.g., app.yourdomain.com) to the static IP address of the global load balancer using Cloud DNS. This ensures that when the IP changes (during failover), DNS propagation is handled efficiently.
Automated Failover and Recovery Procedures
Automating failover is critical for minimizing downtime. This can be achieved using Cloud Functions, Cloud Run, or custom scripts triggered by Cloud Monitoring alerts.
1. Monitoring and Alerting:
Set up Cloud Monitoring alerts for:
- High replication lag on the Cloud SQL read replica.
- Persistent health check failures for the primary region's backend service.
- Unhealthy instances within the primary MIG.
2. Failover Trigger (Example using Cloud Functions):
A Cloud Function can be triggered by a monitoring alert. This function would then execute the necessary steps to promote the secondary resources.
import googleapiclient.discovery
import google.auth
def trigger_failover(event, context):
"""
Cloud Function to trigger multi-region failover.
Assumes it's triggered by a Cloud Monitoring alert.
"""
project_id = 'your-gcp-project-id'
primary_region = 'us-central1'
secondary_region = 'us-east1'
primary_db_instance = 'my-app-db-primary'
replica_db_instance = 'my-app-db-replica'
secondary_mig_name = 'your-cpp-app-mig-secondary'
secondary_template_name = 'your-cpp-app-template-secondary' # Needs to be defined
credentials, project = google.auth.default()
sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta4', credentials=credentials)
compute = googleapiclient.discovery.build('compute', 'v1', credentials=credentials)
print(f"Starting failover process for project: {project_id}")
# 1. Promote Cloud SQL read replica
try:
print(f"Promoting replica {replica_db_instance} in {secondary_region}...")
request = sqladmin.instances().promoteReplica(
project=project_id,
instance=replica_db_instance,
body={'settings': {'tier': 'db-f1-micro'}} # Ensure tier is set
)
response = request.execute()
print(f"Replica promotion initiated: {response}")
# In a real scenario, you'd poll for completion or use a callback.
# For simplicity, we assume it succeeds.
except Exception as e:
print(f"Error promoting replica: {e}")
return
# 2. Update application configuration to point to the new primary DB
# This is application-specific. It might involve updating secrets,
# config files on instances, or a configuration service.
print("Updating application DB connection strings (manual or automated step)...")
# 3. Scale up the secondary MIG and update its template if necessary
try:
print(f"Scaling up MIG {secondary_mig_name} in {secondary_region} to size 2...")
# Ensure the instance template for the secondary region is up-to-date
# You might need to update the template with the latest C++ app image
# before scaling up. This is often done via Cloud Build.
update_template_request = compute.instanceGroupManagers().patch(
project=project_id,
zone=f"{secondary_region}-a", # Assuming zone for MIG
instanceGroupManager=secondary_mig_name,
body={
"instanceTemplate": f"projects/{project_id}/global/instanceTemplates/{secondary_template_name}"
}
)
update_template_request.execute()
resize_request = compute.instanceGroupManagers().resize(
project=project_id,
zone=f"{secondary_region}-a", # Assuming zone for MIG
instanceGroupManager=secondary_mig_name,
size=2
)
resize_request.execute()
print(f"MIG {secondary_mig_name} resize initiated.")
except Exception as e:
print(f"Error scaling up secondary MIG: {e}")
return
# 4. Update Cloud DNS (if IP address of LB changes, though usually it's static)
# If using a static IP for the LB, this step is often not needed unless
# you're switching to a different LB IP.
print("Failover process completed. Manual verification recommended.")
# Example of how to trigger this function (e.g., from a Pub/Sub alert)
# You would configure Cloud Monitoring to send alerts to a Pub/Sub topic,
# and this function would be subscribed to that topic.
3. Manual Recovery Steps:
Even with automation, manual verification and intervention might be necessary. This includes:
- Verifying the promoted database is healthy and accessible.
- Confirming the secondary MIG instances are running and serving traffic.
- Checking application logs for any errors.
- Performing a "rollback" plan if the failover is unsuccessful.
Testing and Validation
Regularly test your disaster recovery plan. This involves simulating failures:
- Database Failover Test: Manually promote the replica and observe application behavior.
- Region Outage Simulation: Temporarily disable network access to the primary region's load balancer or MIGs.
- Application Health Check Manipulation: Temporarily make health checks fail for the primary region to trigger load balancer failover.
Document all test results and update procedures based on lessons learned. Ensure your RTO (Recovery Time Objective) and RPO are met during these tests.
Security Considerations
Ensure secure communication between services using VPC Service Controls, IAM roles, and SSL/TLS certificates. For database access, use private IP connectivity and authorized networks or IAM database authentication where applicable.
Service accounts used by Cloud Build, Cloud Functions, and GCE instances must have the minimum necessary permissions (principle of least privilege).
Establishing Multi-Region Redundancy for C++ Applications on Google Cloud
Achieving robust disaster recovery for C++ applications in a multi-region Google Cloud Platform (GCP) environment necessitates a strategic approach to data synchronization, service deployment, and automated failover. This post details a practical, production-ready implementation focusing on stateless C++ microservices and a managed relational database, leveraging GCP's native capabilities for resilience.
Core Components and Architecture Overview
Our target architecture comprises several key GCP services:
- Compute Engine (GCE): For hosting our C++ microservices. We'll utilize managed instance groups (MIGs) for scalability and self-healing.
- Cloud SQL: A fully managed relational database service. We'll configure cross-region read replicas and a robust backup strategy.
- Cloud Load Balancing: To distribute traffic across regions and facilitate seamless failover.
- Cloud DNS: For managing DNS records and enabling rapid IP address updates during failover.
- Cloud Build: To automate the CI/CD pipeline for C++ application deployments.
- Cloud Monitoring & Cloud Logging: Essential for observing system health and diagnosing issues.
The primary strategy involves maintaining active-passive or active-active deployments across two or more GCP regions. For this example, we'll focus on an active-passive setup with a primary region (e.g., us-central1) and a secondary region (e.g., us-east1).
Database Replication Strategy: Cloud SQL Cross-Region Replicas
For our C++ application's data persistence, Cloud SQL provides a straightforward mechanism for cross-region replication. This ensures that data changes in the primary region are asynchronously replicated to a read replica in the secondary region.
1. Provisioning the Primary Cloud SQL Instance:
Create your primary Cloud SQL instance in the primary region. Ensure you enable automated backups and point-in-time recovery. For production, consider a high-availability (HA) configuration for the primary instance itself.
2. Creating a Cross-Region Read Replica:
From the GCP Console or using gcloud, create a read replica in your secondary region. This replica will automatically synchronize with the primary instance.
Using gcloud:
gcloud sql instances create my-app-db-replica \ --master-instance-name=my-app-db-primary \ --region=us-east1 \ --project=your-gcp-project-id \ --database-version=POSTGRES_14 \ --tier=db-f1-micro # Adjust tier as needed
Important Considerations:
- Replication Lag: Monitor replication lag using Cloud Monitoring. High lag can impact RPO (Recovery Point Objective).
- Failover Promotion: In a disaster scenario, the read replica must be promoted to a standalone instance. This is a manual or automated step.
- Write Operations: The replica is read-only. Your application must be designed to direct writes only to the primary instance.
C++ Microservice Deployment: Managed Instance Groups and CI/CD
We'll deploy stateless C++ microservices using GCE Managed Instance Groups (MIGs). This provides auto-scaling, auto-healing, and rolling updates.
1. Containerization (Recommended):
While not strictly required, containerizing your C++ application (e.g., using Docker) simplifies deployment and ensures consistency across environments. A typical Dockerfile might look like this:
FROM ubuntu:22.04 AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN cmake . && make
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \ # Example dependency for PostgreSQL client
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/your_cpp_app /usr/local/bin/your_cpp_app
CMD ["/usr/local/bin/your_cpp_app"]
2. Cloud Build Configuration:
A cloudbuild.yaml file orchestrates the build and deployment process. This example assumes you're building a container image and pushing it to Google Container Registry (GCR) or Artifact Registry.
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/your-cpp-app:$COMMIT_SHA', '.']
# Push the container image to GCR
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/your-cpp-app:$COMMIT_SHA']
# Deploy to the primary region's MIG
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args:
- compute
- instance-groups
- managed
- update-template
- your-cpp-app-mig-primary
- --template-file=instance-template-primary.yaml
- --region=us-central1
- --project=your-gcp-project-id
# Deploy to the secondary region's MIG (for active-passive, this might be a manual step or triggered by failover)
# For active-active, you'd deploy here as well.
# - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
# entrypoint: gcloud
# args:
# - compute
# - instance-groups
# - managed
# - update-template
# - your-cpp-app-mig-secondary
# - --template-file=instance-template-secondary.yaml
# - --region=us-east1
# - --project=your-gcp-project-id
images:
- 'gcr.io/$PROJECT_ID/your-cpp-app:$COMMIT_SHA'
3. Instance Template (instance-template-primary.yaml):
name: your-cpp-app-template-primary
machineType: n1-standard-1 # Adjust as needed
diskSizeGb: '10'
disks:
- boot: true
autoDelete: true
initializeParams:
sourceImage: projects/google-containers/global/images/container-vm
diskType: pd-standard
diskSizeGb: '10'
networkInterfaces:
- network: projects/your-gcp-project-id/global/networks/default
accessConfigs:
- type: ONE_TO_ONE_NAT
name: External NAT
tags:
items:
- http-server
- https-server
metadata:
items:
- key: google-container-deployment
value: |
{
"container": {
"image": "gcr.io/your-gcp-project-id/your-cpp-app:$COMMIT_SHA",
"ports": [{"containerPort": 8080}]
}
}
- key: startup-script
value: |
#!/bin/bash
# Optional: Add any pre-start commands here, e.g., database connection checks
echo "Starting C++ application..."
4. Managed Instance Groups (MIGs):
Create MIGs in each region, referencing the instance template. Configure auto-scaling based on CPU utilization or custom metrics.
# Primary Region MIG gcloud compute instance-groups managed create your-cpp-app-mig-primary \ --template=your-cpp-app-template-primary \ --size=2 \ --region=us-central1 \ --project=your-gcp-project-id # Secondary Region MIG (initially scaled down or inactive for active-passive) gcloud compute instance-groups managed create your-cpp-app-mig-secondary \ --template=your-cpp-app-template-secondary \ --size=0 \ --region=us-east1 \ --project=your-gcp-project-id
Global Load Balancing and DNS for Failover
A global external HTTP(S) load balancer is crucial for directing traffic to the active region and enabling automated failover.
1. Backend Services:
Create separate backend services for each region's MIG. Configure health checks to monitor the availability of your C++ application instances.
# Health Check gcloud compute health-checks create http my-app-health-check \ --request-path=/health \ --port=8080 \ --check-interval=10s \ --timeout=5s \ --unhealthy-threshold=3 \ --healthy-threshold=2 \ --project=your-gcp-project-id # Backend Service for Primary Region gcloud compute backend-services create my-app-backend-primary \ --protocol=HTTP \ --port-name=http \ --health-checks=my-app-health-check \ --global \ --project=your-gcp-project-id gcloud compute backend-services add-backend my-app-backend-primary \ --instance-group=your-cpp-app-mig-primary \ --instance-group-region=us-central1 \ --global \ --project=your-gcp-project-id # Backend Service for Secondary Region (initially disabled or with low priority) gcloud compute backend-services create my-app-backend-secondary \ --protocol=HTTP \ --port-name=http \ --health-checks=my-app-health-check \ --global \ --project=your-gcp-project-id gcloud compute backend-services add-backend my-app-backend-secondary \ --instance-group=your-cpp-app-mig-secondary \ --instance-group-region=us-east1 \ --global \ --project=your-gcp-project-id
2. URL Map and Forwarding Rule:
Configure a URL map to route traffic to the backend services. For active-passive, you'll set up a primary and a backup backend service. The global forwarding rule will point to this URL map.
# URL Map gcloud compute url-maps create my-app-url-map \ --default-service=my-app-backend-primary \ --project=your-gcp-project-id # Add a backend for failover gcloud compute url-maps add-backend my-app-url-map \ --default-service=my-app-backend-secondary \ --priority=10 \ --global \ --project=your-gcp-project-id # Global Forwarding Rule (using a static IP) gcloud compute addresses create my-app-global-ip \ --ip-version=IPV4 \ --global \ --project=your-gcp-project-id gcloud compute forwarding-rules create my-app-forwarding-rule \ --address=my-app-global-ip \ --target-http-proxy=$(gcloud compute target-http-proxies create my-app-http-proxy --url-map=my-app-url-map --global --project=your-gcp-project-id --format='value(name)') \ --ports=80 \ --global \ --project=your-gcp-project-id
3. Cloud DNS Configuration:
Point your application's domain name (e.g., app.yourdomain.com) to the static IP address of the global load balancer using Cloud DNS. This ensures that when the IP changes (during failover), DNS propagation is handled efficiently.
Automated Failover and Recovery Procedures
Automating failover is critical for minimizing downtime. This can be achieved using Cloud Functions, Cloud Run, or custom scripts triggered by Cloud Monitoring alerts.
1. Monitoring and Alerting:
Set up Cloud Monitoring alerts for:
- High replication lag on the Cloud SQL read replica.
- Persistent health check failures for the primary region's backend service.
- Unhealthy instances within the primary MIG.
2. Failover Trigger (Example using Cloud Functions):
A Cloud Function can be triggered by a monitoring alert. This function would then execute the necessary steps to promote the secondary resources.
import googleapiclient.discovery
import google.auth
def trigger_failover(event, context):
"""
Cloud Function to trigger multi-region failover.
Assumes it's triggered by a Cloud Monitoring alert.
"""
project_id = 'your-gcp-project-id'
primary_region = 'us-central1'
secondary_region = 'us-east1'
primary_db_instance = 'my-app-db-primary'
replica_db_instance = 'my-app-db-replica'
secondary_mig_name = 'your-cpp-app-mig-secondary'
secondary_template_name = 'your-cpp-app-template-secondary' # Needs to be defined
credentials, project = google.auth.default()
sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta4', credentials=credentials)
compute = googleapiclient.discovery.build('compute', 'v1', credentials=credentials)
print(f"Starting failover process for project: {project_id}")
# 1. Promote Cloud SQL read replica
try:
print(f"Promoting replica {replica_db_instance} in {secondary_region}...")
request = sqladmin.instances().promoteReplica(
project=project_id,
instance=replica_db_instance,
body={'settings': {'tier': 'db-f1-micro'}} # Ensure tier is set
)
response = request.execute()
print(f"Replica promotion initiated: {response}")
# In a real scenario, you'd poll for completion or use a callback.
# For simplicity, we assume it succeeds.
except Exception as e:
print(f"Error promoting replica: {e}")
return
# 2. Update application configuration to point to the new primary DB
# This is application-specific. It might involve updating secrets,
# config files on instances, or a configuration service.
print("Updating application DB connection strings (manual or automated step)...")
# 3. Scale up the secondary MIG and update its template if necessary
try:
print(f"Scaling up MIG {secondary_mig_name} in {secondary_region} to size 2...")
# Ensure the instance template for the secondary region is up-to-date
# You might need to update the template with the latest C++ app image
# before scaling up. This is often done via Cloud Build.
update_template_request = compute.instanceGroupManagers().patch(
project=project_id,
zone=f"{secondary_region}-a", # Assuming zone for MIG
instanceGroupManager=secondary_mig_name,
body={
"instanceTemplate": f"projects/{project_id}/global/instanceTemplates/{secondary_template_name}"
}
)
update_template_request.execute()
resize_request = compute.instanceGroupManagers().resize(
project=project_id,
zone=f"{secondary_region}-a", # Assuming zone for MIG
instanceGroupManager=secondary_mig_name,
size=2
)
resize_request.execute()
print(f"MIG {secondary_mig_name} resize initiated.")
except Exception as e:
print(f"Error scaling up secondary MIG: {e}")
return
# 4. Update Cloud DNS (if IP address of LB changes, though usually it's static)
# If using a static IP for the LB, this step is often not needed unless
# you're switching to a different LB IP.
print("Failover process completed. Manual verification recommended.")
# Example of how to trigger this function (e.g., from a Pub/Sub alert)
# You would configure Cloud Monitoring to send alerts to a Pub/Sub topic,
# and this function would be subscribed to that topic.
3. Manual Recovery Steps:
Even with automation, manual verification and intervention might be necessary. This includes:
- Verifying the promoted database is healthy and accessible.
- Confirming the secondary MIG instances are running and serving traffic.
- Checking application logs for any errors.
- Performing a "rollback" plan if the failover is unsuccessful.
Testing and Validation
Regularly test your disaster recovery plan. This involves simulating failures:
- Database Failover Test: Manually promote the replica and observe application behavior.
- Region Outage Simulation: Temporarily disable network access to the primary region's load balancer or MIGs.
- Application Health Check Manipulation: Temporarily make health checks fail for the primary region to trigger load balancer failover.
Document all test results and update procedures based on lessons learned. Ensure your RTO (Recovery Time Objective) and RPO are met during these tests.
Security Considerations
Ensure secure communication between services using VPC Service Controls, IAM roles, and SSL/TLS certificates. For database access, use private IP connectivity and authorized networks or IAM database authentication where applicable.
Service accounts used by Cloud Build, Cloud Functions, and GCE instances must have the minimum necessary permissions (principle of least privilege).