Regional Cloud Service Mesh
With regional isolation, clients connecting to a specific region of the Cloud Service Mesh control plane can only access resources within that region. Similarly, API resources within a specific region can only refer to other resources in that region.
Regional Cloud Service Mesh has the following Limitations:
- The Istio API not supported. You cannot use Kubernetes with the Istio API using regional Traffic Director. Only Google Cloud APIs are supported in this preview.
- The existing considerations and limitations of the global service routing APIs apply.
- The minimum Envoy version to support xdSTP naming schemes is v1.31.1.
- Gateway for Mesh API is not supported.
- The minimum gRPC version is v1.65.
Only the following regions are supported:
africa-south1 asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1 asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2 europe-central2 europe-north1 europe-north2 europe-southwest1 europe-west10 europe-west12 europe-west1 europe-west2 europe-west3 europe-west4 europe-west6 europe-west8 europe-west9 me-central1 me-central2 me-west1 northamerica-northeast1 northamerica-northeast2 northamerica-south1 southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-east5 us-south1 us-west1 us-west2 us-west3 us-west4
Pricing
Each region in which regional Cloud Service Mesh is supported will have a regional SKU when this feature is Generally Available. For now, the pricing is the same as global.
Prepare xDS client for Cloud Service Mesh
Compute VM Envoy xDS
Manual
The manual steps build on
Set up VMs using manual Envoy deployment.
The main difference is that ENVOY_CONTROL_PLANE_REGION is set and injected
into the bootstrap.
Create the instance template:
gcloud compute instance-templates create td-vm-templategcloud compute instance-templates create td-vm-template \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=http-td-tag,http-server,https-server \ --image-family=debian-11 \ --image-project=debian-cloud \ --metadata=startup-script='#! /usr/bin/env bash # Set variables export ENVOY_CONTROL_PLANE_REGION="us-central1" export ENVOY_USER="envoy" export ENVOY_USER_UID="1337" export ENVOY_USER_GID="1337" export ENVOY_USER_HOME="/opt/envoy" export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml" export ENVOY_PORT="15001" export ENVOY_ADMIN_PORT="15000" export ENVOY_TRACING_ENABLED="false" export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt" export ENVOY_ACCESS_LOG="/dev/stdout" export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)" export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml" export GCE_METADATA_SERVER="169.254.169.254/32" export INTERCEPTED_CIDRS="*" export GCP_PROJECT_NUMBER=PROJECT_NUMBER export VPC_NETWORK_NAME=mesh:sidecar-mesh export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4) # Create system user account for Envoy binary sudo groupadd ${ENVOY_USER} \ --gid=${ENVOY_USER_GID} \ --system sudo adduser ${ENVOY_USER} \ --uid=${ENVOY_USER_UID} \ --gid=${ENVOY_USER_GID} \ --home=${ENVOY_USER_HOME} \ --disabled-login \ --system # Download and extract the Cloud Service Mesh tar.gz file cd ${ENVOY_USER_HOME} sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \ -C bootstrap_template.yaml \ --strip-components 1 sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \ -C iptables.sh \ --strip-components 1 sudo rm traffic-director-xdsv3.tar.gz # Generate Envoy bootstrap configuration cat "${BOOTSTRAP_TEMPLATE}" \ | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \ | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \ | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \ | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \ | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \ | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \ | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \ | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \ | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \ | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \ | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \ | sudo tee "${ENVOY_CONFIG}" # Install Envoy binary wget -O envoy_key https://apt.envoyproxy.io/signing.key cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list sudo apt-get update sudo apt-get install envoy # Run Envoy as systemd service sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \ --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \ bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee" # Configure iptables for traffic interception and redirection sudo ${ENVOY_USER_HOME}/iptables.sh \ -p "${ENVOY_PORT}" \ -u "${ENVOY_USER_UID}" \ -g "${ENVOY_USER_GID}" \ -m "REDIRECT" \ -i "${INTERCEPTED_CIDRS}" \ -x "${GCE_METADATA_SERVER}"
Compute VM gRPC xDS
Similar to global Cloud Service Mesh, gRPC clients need to configure a bootstrap in order to tell it how to connect to Regional Cloud Service Mesh.
You can use the gRPC bootstrap generator
to generate this bootstrap. To set it to use regional Cloud Service Mesh,
specify a new flag: --xds-server-region.
In this example, setting xds-server-region to us-central1 automatically
determines the regional Cloud Service Mesh endpoint:
trafficdirector.us-central1.rep.googleapis.com:443.
K8s Manual Envoy Injection
The manual steps build on Set up Google Kubernetes Engine Pods using manual Envoy injection. However, you only need to modify the section about manual pod injection.
Change the control plane from global to regional:
wget -q -O - https://storage.googleapis.com/traffic-director/demo/trafficdirector_client_new_api_sample_xdsv3.yaml sed -i "s/PROJECT_NUMBER/PROJECT_NUMBER/g" trafficdirector_client_new_api_sample_xdsv3.yaml sed -i "s/MESH_NAME/MESH_NAME/g" trafficdirector_client_new_api_sample_xdsv3.yaml sed -i "s|trafficdirector.googleapis.com|trafficdirector.${REGION}.rep.googleapis.com|g" trafficdirector_client_new_api_sample_xdsv3.yaml sed -i "s|gcr.io/google-containers/busybox|busybox:stable|g" trafficdirector_client_new_api_sample_xdsv3.yamlApply the changes:
kubectl apply -f trafficdirector_client_new_api_sample_xdsv3.yaml ```
Setup guides
The section covers five independent configurations and deployment models. These are all regionalized versions of existing global service routing API setup guides.
- Configuring Proxyless gRPC services with regional GRPCRoute and regional Cloud Service Mesh
- Configuring Envoy sidecar proxy configuration with HTTP services with regional HTTPRoute and regional Cloud Service Mesh
- Configuring TCP services with regional TCPRoute
- Gateway TLS routing
- Configuring cross-project references for regional Cloud Service Mesh and regional Route
Configure Proxyless gRPC services with regional GRPCRoute and regional Cloud Service Mesh
This sections explains how to configure a proxyless gRPC service mesh with regional Cloud Service Mesh and regional GRPCRoute resources.
For your convenience, store the Google Cloud project number you perform configuration in, so that all examples in this guide can be copy-pasted in the command line:
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"
Replace PROJECT_NUMBER with your project number.
Optionally, you can replace the following:
- us-central1 with a different region you want to use.
- us-central1-a with a different zone you want to use.
- default with a different VPC_NAME.
Mesh configuration
When a proxyless gRPC application connects to an xds://hostname, the gRPC
client library establishes a connection to the Cloud Service Mesh to get the
routing configuration required to route requests for the hostname.
Create a Mesh specification and store it in the mesh.yaml file:
cat <<EOF > mesh.yaml name: grpc-mesh EOFCreate a Mesh using the mesh.yaml specification:
gcloud network-services meshes import grpc-mesh \ --source=mesh.yaml \ --location=${REGION}After the regional mesh is created, Cloud Service Mesh is ready to serve the configuration. However, because no services are defined yet, the configuration is empty.
gRPC service configuration
For demonstration purposes you will create a regional Backend Service with
auto-scaled VMs (using Managed instance groups - MIG)
that will serve hello world using the gRPC protocol on port 50051.
Create the Compute Engine VM instance template with a
helloworldgRPC service that is exposed on port 50051:gcloud compute instance-templates create grpc-td-vm-template \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=allow-health-checks \ --image-family=debian-11 \ --image-project=debian-cloud \ --metadata-from-file=startup-script=<(echo '#! /bin/bash set -e cd /root sudo apt-get update -y sudo apt-get install -y openjdk-11-jdk-headless curl -L https://github.com/grpc/grpc-java/archive/v1.38.0.tar.gz | tar -xz cd grpc-java-1.38.0/examples/example-hostname ../gradlew --no-daemon installDist # Server listens on 50051 sudo systemd-run ./build/install/hostname-server/bin/hostname-server')Create a MIG based on the template:
gcloud compute instance-groups managed create grpc-td-mig-us-central1 \ --zone=${ZONE} \ --size=2 \ --template=grpc-td-vm-templateConfigure a named port for the gRPC service. This is the port on which the gRPC service is configured to listen for requests.
gcloud compute instance-groups set-named-ports grpc-td-mig-us-central1 \ --named-ports=grpc-helloworld-port:50051 \ --zone=${ZONE}In this example, the port is 50051.
Create gRPC health checks.
gcloud compute health-checks create grpc grpc-helloworld-health-check \ --use-serving-port --region=${REGION}The services must implement the gRPC health checking protocol for gRPC health checks to function properly. For more information, see Creating health checks.
Create a firewall rule to allow incoming health check connections to instances in your network:
gcloud compute firewall-rules create grpc-vm-allow-health-checks \ --network default --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \ --target-tags allow-health-checks \ --rules tcp:50051Create a regional Backend Service with a load balancing scheme of
INTERNAL_SELF_MANAGEDand add the health check and a managed instance group created earlier to the Backend Service. The port in the port-name specified is used to connect to the VMs in the managed instance group.gcloud compute backend-services create grpc-helloworld-service \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --protocol=GRPC \ --port-name=grpc-helloworld-port \ --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/grpc-helloworld-health-check" \ --region=${REGION}Add the managed instance group to the
BackendService:gcloud compute backend-services add-backend grpc-helloworld-service \ --instance-group=grpc-td-mig-us-central1 \ --instance-group-zone=${ZONE} \ --region=${REGION}
Setup routing with regional GRPCRoute
At this point the regional mesh and gRPC server service are configured. Now you can set up the required routing.
Create regional GRPCRoute specification and store it in the grpc_route.yaml file:
cat <<EOF > grpc_route.yaml name: helloworld-grpc-route hostnames: - helloworld-gce meshes: - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/grpc-mesh rules: - action: destinations: - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/grpc-helloworld-service EOFCreate regional GRPCRoute using the grpc_route.yaml specification:
gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=${REGION}Cloud Service Mesh is now configured to load balance traffic for the services specified in the gRPC Route across backends in the managed instance group.
Create gRPC client service
To verify the configuration, instantiate a client application with a proxyless gRPC data plane. This application must specify (in its bootstrap file) the name of the mesh.
Once configured, this application can send a request to the instances or endpoints
associated with the helloworld-gce using the xds:///helloworld-gce service URI.
In the following examples, use the grpcurl tool to test the gRPC service.
Create a client VM:
gcloud compute instances create grpc-client \ --zone=${ZONE}\ --scopes=https://www.googleapis.com/auth/cloud-platform \ --image-family=debian-11 \ --image-project=debian-cloud \ --metadata-from-file=startup-script=<(echo '#! /bin/bash set -ex export PROJECT=PROJECT_NUMBER export REGION=us-central1 export GRPC_XDS_BOOTSTRAP=/run/td-grpc-bootstrap.json echo export GRPC_XDS_BOOTSTRAP=$GRPC_XDS_BOOTSTRAP | sudo tee /etc/profile.d/grpc-xds-bootstrap.sh curl -L https://storage.googleapis.com/traffic-director/td-grpc-bootstrap-0.18.0.tar.gz | tar -xz ./td-grpc-bootstrap-0.18.0/td-grpc-bootstrap --config-mesh=grpc-mesh --xds-server-uri=trafficdirector.${REGION}.rep.googleapis.com:443 --gcp-project-number=${PROJECT} | sudo tee $GRPC_XDS_BOOTSTRAP sudo sed -i "s|\"authorities\": {|\"authorities\": {\n \"traffic-director.${REGION}.xds.googleapis.com\": {\"xds_servers\":[{\"server_uri\": \"trafficdirector.${REGION}.rep.googleapis.com:443\", \"channel_creds\": [ { \"type\": \"google_default\" } ], \"server_features\": [ \"xds_v3\", \"ignore_resource_deletion\" ]}], \"client_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com/envoy.config.listener.v3.Listener/${PROJECT}/mesh:grpc-mesh/%s\"},|g" $GRPC_XDS_BOOTSTRAP sudo sed -i "s|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director-global.xds.googleapis.com|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com|g" $GRPC_XDS_BOOTSTRAP')
Set up the environment variable and bootstrap file
The client application needs a bootstrap configuration file. The startup script
in the previous section sets the GRPC_XDS_BOOTSTRAP environment variable and
uses a helper script to generate the bootstrap file. The values for
TRAFFICDIRECTOR_GCP_PROJECT_NUMBER and zone in the generated bootstrap file
are obtained from the metadata server that knows these details about your
Compute Engine VM instances.
You can provide these values to the helper
script manually by using the -gcp-project-number option. You must provide a
mesh name that matches the mesh resource using the -config-mesh-experimental
option.
To verify the configuration, sign in to the client:
gcloud compute ssh grpc-client --zone=${ZONE}Download and install the
grpcurltool:curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_x86_64.tar.gz | tar -xzRun the
grpcurltool withxds:///helloworld-gceas the service URI andhelloworld.Greeter/SayHelloas the service name and method to invoke../grpcurl --plaintext \ -d '{"name": "world"}' \ xds:///helloworld-gce helloworld.Greeter/SayHelloThe parameters to the SayHello method are passed using the -d option.
You should see output similar to this, where
INSTANCE_NAMEis the name of the VM instance:Greeting: Hello world, from INSTANCE_HOSTNAME
This verifies that the proxyless gRPC client successfully connected to Cloud Service Mesh and learned about the backends for the helloworld-gce service using the xDS name resolver. The client sent a request to one of the service's backends without needing to know about the IP address or performing DNS resolution.
Configuring Envoy sidecar proxy configuration with HTTP services with regional HTTPRoute and regional Mesh
This section explains how to configure an Envoy proxy-based service mesh with regional mesh and regional HTTPRoute resources.
For your convenience, store the Google Cloud project number you perform configuration in, so that all examples in this guide can be copy-pasted in the command line:
export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"
Replace the following
- PROJECT_ID with your project ID.
- PROJECT_NUMBER with your project number.
Optionally, you can replace the following:
- us-central1 with a different region you want to use.
- us-central1-a with a different zone you want to use.
Mesh configuration
The sidecar Envoy proxy receives the service routing configuration from Cloud Service Mesh. The sidecar presents the name of the regional mesh resource to identify the specific service mesh configured. The routing configuration received from Cloud Service Mesh is used to direct the traffic going through the sidecar proxy to various regional Backend Services depending on request parameters, such as the hostname or headers, configured in the Route resource(s).
Note that the mesh name is the key that the sidecar proxy uses to request the configuration associated with this mesh.
Create regional mesh specification and store it in the mesh.yaml file:
cat <<EOF > mesh.yaml name: sidecar-mesh EOFThe interception port defaults to 15001 if unspecified.
Create regional mesh using the mesh.yaml specification:
gcloud network-services meshes import sidecar-mesh \ --source=mesh.yaml \ --location=${REGION}After the regional mesh is created, Cloud Service Mesh is ready to serve the configuration. However, because no services are defined yet, the configuration will be empty.
HTTP server configuration
For demonstration purposes you will create a regional Backend Service with auto-scaled VMs (using Managed instance groups - MIG) that will serve "hello world" using the gRPC protocol on port 80.
Create the Compute Engine VM instance template with a
helloworldHTTP service that is exposed on port 80:gcloud compute instance-templates create td-httpd-vm-template \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=http-td-server \ --image-family=debian-11 \ --image-project=debian-cloud \ --metadata=startup-script="#! /bin/bash sudo apt-get update -y sudo apt-get install apache2 -y sudo service apache2 restart echo '<!doctype html><html><body><h1>'\`/bin/hostname\`'</h1></body></html>' | sudo tee /var/www/html/index.html"Create a MIG based on the template:
gcloud compute instance-groups managed create http-td-mig-us-central1 \ --zone=${ZONE} \ --size=2 \ --template=td-httpd-vm-templateCreate the health checks:
gcloud compute health-checks create http http-helloworld-health-check --region=${REGION}Create a firewall rule to allow incoming health check connections to instances in your network:
gcloud compute firewall-rules create http-vm-allow-health-checks \ --network default --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \ --target-tags http-td-server \ --rules tcp:80Create a regional Backend Service with a load balancing scheme of
INTERNAL_SELF_MANAGED:gcloud compute backend-services create http-helloworld-service \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --protocol=HTTP \ --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/http-helloworld-health-check" \ --region=${REGION}Add the health check and a managed or unmanaged instance group to the backend service:
gcloud compute backend-services add-backend http-helloworld-service \ --instance-group=http-td-mig-us-central1 \ --instance-group-zone=${ZONE} \ --region=${REGION}This example uses the managed instance group with the Compute Engine VM template that runs the sample HTTP service we created earlier.
Set up routing with regional HTTPRoute
The mesh resource and HTTP server are configured. You can now connect them using an HTTPRoute resource that associates a hostname with a Backend Service.
Create HTTPRoute specification and store as http_route.yaml:
cat <<EOF > http_route.yaml name: helloworld-http-route hostnames: - helloworld-gce meshes: - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/sidecar-mesh rules: - action: destinations: - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/http-helloworld-service EOFCreate the HTTPRoute using the http_route.yaml specification:
gcloud network-services http-routes import helloworld-http-route \ --source=http_route.yaml \ --location=${REGION}Cloud Service Mesh is now configured to load balance traffic for the services specified in the HTTPRoute across backends in the managed instance group.
Create HTTP client with Envoy sidecar
In this section you instantiate a client VM with Envoy sidecar proxy to request
Cloud Service Mesh configuration created earlier. Note that the mesh
parameter in the Google Cloud CLI command references the mesh resource created earlier.
gcloud compute instance-templates create td-vm-template \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--tags=http-td-tag,http-server,https-server \
--image-family=debian-11 \
--image-project=debian-cloud \
--metadata=startup-script='#! /usr/bin/env bash
# Set variables
export ENVOY_CONTROL_PLANE_REGION="us-central1"
export ENVOY_USER="envoy"
export ENVOY_USER_UID="1337"
export ENVOY_USER_GID="1337"
export ENVOY_USER_HOME="/opt/envoy"
export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
export ENVOY_PORT="15001"
export ENVOY_ADMIN_PORT="15000"
export ENVOY_TRACING_ENABLED="false"
export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
export ENVOY_ACCESS_LOG="/dev/stdout"
export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
export GCE_METADATA_SERVER="169.254.169.254/32"
export INTERCEPTED_CIDRS="*"
export GCP_PROJECT_NUMBER=PROJECT_NUMBER
export VPC_NETWORK_NAME=mesh:sidecar-mesh
export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
# Create system user account for Envoy binary
sudo groupadd ${ENVOY_USER} \
--gid=${ENVOY_USER_GID} \
--system
sudo adduser ${ENVOY_USER} \
--uid=${ENVOY_USER_UID} \
--gid=${ENVOY_USER_GID} \
--home=${ENVOY_USER_HOME} \
--disabled-login \
--system
# Download and extract the Cloud Service Mesh tar.gz file
cd ${ENVOY_USER_HOME}
sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
-C bootstrap_template.yaml \
--strip-components 1
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
-C iptables.sh \
--strip-components 1
sudo rm traffic-director-xdsv3.tar.gz
# Generate Envoy bootstrap configuration
cat "${BOOTSTRAP_TEMPLATE}" \
| sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
| sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
| sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
| sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
| sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
| sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
| sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
| sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
| sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
| sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
| sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
| sudo tee "${ENVOY_CONFIG}"
# Install Envoy binary
wget -O envoy_key https://apt.envoyproxy.io/signing.key
cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
sudo apt-get update
sudo apt-get install envoy
# Run Envoy as systemd service
sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
--working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
# Configure iptables for traffic interception and redirection
sudo ${ENVOY_USER_HOME}/iptables.sh \
-p "${ENVOY_PORT}" \
-u "${ENVOY_USER_UID}" \
-g "${ENVOY_USER_GID}" \
-m "REDIRECT" \
-i "${INTERCEPTED_CIDRS}" \
-x "${GCE_METADATA_SERVER}"
'
gcloud compute instances create td-vm-client \
--zone=${ZONE} \
--source-instance-template td-vm-template
Login to the created VM:
gcloud compute ssh td-vm-client --zone=${ZONE}Verify HTTP connectivity to the created test services:
curl -H "Host: helloworld-gce" http://10.0.0.1/The command returns a response from one of the VMs in the Managed Instance Group with its hostname printed to the console.
Configuring TCP services with regional TCPRoute
This configuration flow is very similar to Set up Envoy proxies with HTTP services with an exception that Backend Service provides a TCP service and routing based on the TCP/IP parameters is used rather than based on the HTTP protocol.
For your convenience, store the Google Cloud project number you perform configuration in, so that all examples in this guide can be copy-pasted in the command line:
export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"
Replace the following
- PROJECT_ID with your project ID.
- PROJECT_NUMBER with your project number.
Optionally, you can replace the following:
- us-central1 with a different region you want to use.
- us-central1-a with a different zone you want to use.
Mesh configuration
Create regional mesh specification and store it in the mesh.yaml file:
cat <<EOF > mesh.yaml name: sidecar-mesh EOFCreate regional mesh using the mesh.yaml specification:
gcloud network-services meshes import sidecar-mesh \ --source=mesh.yaml \ --location=${REGION}
TCP server configuration
For demonstration purposes you will create a regional Backend Service with auto-scaled VMs (using Managed instance groups - MIG) that will serve "hello world" using the gRPC protocol on port 10000.
Create the Compute Engine VM instance template with a test service on port 10000 using netcat utility:
gcloud compute instance-templates create tcp-td-vm-template \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=allow-health-checks \ --image-family=debian-11 \ --image-project=debian-cloud \ --metadata=startup-script="#! /bin/bash sudo apt-get update -y sudo apt-get install netcat -y while true; do echo 'Hello from TCP service' | nc -l -s 0.0.0.0 -p 10000; done &"Create a MIG based on the template:
gcloud compute instance-groups managed create tcp-td-mig-us-central1 \ --zone=${ZONE} \ --size=1 \ --template=tcp-td-vm-templateSet the named ports on the created managed instance group to
port 10000:gcloud compute instance-groups set-named-ports tcp-td-mig-us-central1 \ --zone=${ZONE} --named-ports=tcp:10000Create a regional health check:
gcloud compute health-checks create tcp tcp-helloworld-health-check --port 10000 --region=${REGION}Create a firewall rule to allow incoming health check connections to instances in your network:
gcloud compute firewall-rules create tcp-vm-allow-health-checks \ --network default --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \ --target-tags allow-health-checks \ --rules tcp:10000Create a regional Backend Service with a load balancing scheme of INTERNAL_SELF_MANAGED and add the health check and a managed or unmanaged instance group to the backend service.
gcloud compute backend-services create tcp-helloworld-service \ --region=${REGION} \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --protocol=TCP \ --port-name=tcp \ --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/tcp-helloworld-health-check"Add the MIG to the BackendService:
gcloud compute backend-services add-backend tcp-helloworld-service \ --instance-group tcp-td-mig-us-central1 \ --instance-group-zone=${ZONE} \ --region=${REGION}
Set up routing with regional TCPRoute
Create TCPRoute specification and store it in the tcp_route.yaml file:
cat <<EOF > tcp_route.yaml name: helloworld-tcp-route meshes: - projects/$PROJECT_NUMBER/locations/$REGION/meshes/sidecar-mesh rules: - action: destinations: - serviceName: projects/$PROJECT_NUMBER/locations/$REGION/backendServices/tcp-helloworld-service matches: - address: '10.0.0.1/32' port: '10000' EOFCreate TCPRoute using the tcp_route.yaml specification:
gcloud network-services tcp-routes import helloworld-tcp-route \ --source=tcp_route.yaml \ --location=${REGION}
Create TCP client with Envoy sidecar
Create a VM with Envoy connected to Cloud Service Mesh:
gcloud compute instance-templates create td-vm-template \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=http-td-tag,http-server,https-server \ --image-family=debian-11 \ --image-project=debian-cloud \ --metadata=startup-script='#! /usr/bin/env bash # Set variables export ENVOY_CONTROL_PLANE_REGION="us-central1" export ENVOY_USER="envoy" export ENVOY_USER_UID="1337" export ENVOY_USER_GID="1337" export ENVOY_USER_HOME="/opt/envoy" export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml" export ENVOY_PORT="15001" export ENVOY_ADMIN_PORT="15000" export ENVOY_TRACING_ENABLED="false" export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt" export ENVOY_ACCESS_LOG="/dev/stdout" export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)" export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml" export GCE_METADATA_SERVER="169.254.169.254/32" export INTERCEPTED_CIDRS="*" export GCP_PROJECT_NUMBER=PROJECT_NUMBER export VPC_NETWORK_NAME=mesh:sidecar-mesh export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4) # Create system user account for Envoy binary sudo groupadd ${ENVOY_USER} \ --gid=${ENVOY_USER_GID} \ --system sudo adduser ${ENVOY_USER} \ --uid=${ENVOY_USER_UID} \ --gid=${ENVOY_USER_GID} \ --home=${ENVOY_USER_HOME} \ --disabled-login \ --system # Download and extract the Cloud Service Mesh tar.gz file cd ${ENVOY_USER_HOME} sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \ -C bootstrap_template.yaml \ --strip-components 1 sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \ -C iptables.sh \ --strip-components 1 sudo rm traffic-director-xdsv3.tar.gz # Generate Envoy bootstrap configuration cat "${BOOTSTRAP_TEMPLATE}" \ | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \ | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \ | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \ | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \ | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \ | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \ | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \ | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \ | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \ | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \ | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \ | sudo tee "${ENVOY_CONFIG}" # Install Envoy binary wget -O envoy_key https://apt.envoyproxy.io/signing.key cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list sudo apt-get update sudo apt-get install envoy # Run Envoy as systemd service sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \ --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \ bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee" # Configure iptables for traffic interception and redirection sudo ${ENVOY_USER_HOME}/iptables.sh \ -p "${ENVOY_PORT}" \ -u "${ENVOY_USER_UID}" \ -g "${ENVOY_USER_GID}" \ -m "REDIRECT" \ -i "${INTERCEPTED_CIDRS}" \ -x "${GCE_METADATA_SERVER}" ' gcloud compute instances create td-vm-client \ --zone=${ZONE} \ --source-instance-template td-vm-templateLogin to the created VM:
gcloud compute ssh td-vm-client --zone=${ZONE}Verify connectivity to the created test services:
curl 10.0.0.1:10000 --http0.9 -vYou should see a text
Hello from TCP servicereturned to you as well as be able to see any text you type returned back to you by the netcat service running on the remote VM.
Regional mesh configuration in the host project
Designate a project as the host project. Any service account with permission to create/update/delete meshes in this project can control the routing configurations attached to regional meshes in this project.
Define a variable that will be used throughout the example:
export REGION="us-central1"Optionally, you can replace us-central1 with a different region you want to use.
Create mesh specification and store it in the mesh.yaml file:
cat <<EOF > mesh.yaml name: shared-mesh EOFDefine a mesh resource in this project with the required configuration:
gcloud network-services meshes import shared-mesh \ --source=mesh.yaml \ --location=${REGION}Note the full URI of this mesh resource. Service owners will need it in the future in to attach their routes to this Mesh.
Grant the
networkservices.meshes.useIAM permission to this mesh and to the cross-project service accounts that should be able to attach their services information to this mesh:gcloud projects add-iam-policy-binding HOST_PROJECT_NUMBER --member='HTTP_ROUTE_SERVICE_OWNER_ACCOUNT' --role='roles/compute.networkAdmin'Now all service owners that have
networkservices.meshes.usepermission granted to them are able to add their routing rules to this mesh.
Route configuration in service projects
Each service owner needs to create regional Backend Service(s) and regional
Route resources in their project similar to
Set up Envoy proxies with HTTP services.
The only difference is that each HTTPRoute/GRPCRoute/TCPRoute would have the URI
of the host project's mesh resource in the meshes field.
Create a sharedvpc-http-route:
echo "name: sharedvpc-http-route hostnames: - helloworld-gce meshes: - /projects/HOST_PROJECT_NUMBER/locations/${REGION}/meshes/shared-mesh rules: - action: destinations: - serviceName: \"SERVICE_URL\"" | \ gcloud network-services http-routes import sharedvpc-http-route \ --source=- \ --location=${REGION}
Configuring client services in service projects
While configuring a Cloud Service Mesh client (Envoy proxy or proxyless) that is located in a service project needs to specify the project number where the mesh resource is located and the mesh name in its bootstrap configuration:
TRAFFICDIRECTOR_GCP_PROJECT_NUMBER=HOST_PROJECT_NUMBER
TRAFFICDIRECTOR_MESH_NAME=MESH_NAME
Gateway TLS routing
This section demonstrates how to set up an Envoy proxy-based ingress gateway with regional Gateway and regional TLSRoute resources.
A regional external passthrough Network Load Balancer directs traffic to Envoy proxies that act as an ingress gateway. The Envoy proxies use TLS passthrough routing and direct traffic to HTTPS servers running on the backend VM instances.
Define some variables that will be used throughout the example.
export PROJECT_ID="PROJECT_ID"
export PROJECT_NUMBER="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-b"
export NETWORK_NAME = "default"
Replace the following: default
- PROJECT_ID with your project ID.
- PROJECT_NUMBER with your project number.
Optionally, you can replace the following:
- us-central1 with a different region you want to use.
- us-central1-b with a different zone you want to use.
- default with a different network name you want to use.
Cross-referencing regional mesh and regional route resources in multi-project Shared VPC environment
There are scenarios where service mesh configuration consists of services that are owned by different projects. For example, in Shared VPC or peered VPC deployments it is possible for each project owner to define their own set of services with a purpose for these services to be available to all other projects.
This configuration is "cross-project" because multiple resources defined in different projects are combined together to form a single configuration that can be served to a proxy or proxyless client.
Configure firewall rules
Configure firewall rules to allow traffic from any source. Edit the commands for your ports and source IP address ranges.
gcloud compute firewall-rules create allow-gateway-health-checks \ --network=${NETWORK_NAME} \ --direction=INGRESS \ --action=ALLOW \ --rules=tcp \ --source-ranges="35.191.0.0/16,209.85.152.0/22,209.85.204.0/22" \ --target-tags=gateway-proxy
Configure IAM permissions
Create a service account identity for the gateway proxies:
gcloud iam service-accounts create gateway-proxyAssign the required IAM roles to the service account identity:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/trafficdirector.client"gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/logging.logWriter"
Configure the regional Gateway:
In a file called gateway8443.yaml, create the Gateway specification for HTTP traffic:
cat <<EOF > gateway8443.yaml name: gateway8443 scope: gateway-proxy-8443 ports: - 8443 type: OPEN_MESH EOFCreate the regional Gateway resource using the gateway8443.yaml specification:
gcloud network-services gateways import gateway8443 \ --source=gateway8443.yaml \ --location=${REGION}
Create a managed instance group with Envoy proxies
In this section you create an instance template for a VM running an
automatically deployed Envoy service proxy. The Envoys have the scope set to
gateway-proxy. Don't pass the serving port as a parameter of the
--service-proxy flag.
Create a managed instance group with Envoy proxies:
gcloud beta compute instance-templates create gateway-proxy \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=gateway-proxy,http-td-tag,http-server,https-server \ --image-family=debian-11 \ --image-project=debian-cloud \ --network-interface=network=${NETWORK_NAME} \ --service-account="gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \ --metadata=startup-script='#! /usr/bin/env bash # Set variables export ENVOY_CONTROL_PLANE_REGION="us-central1" export GCP_PROJECT_NUMBER=PROJECT_NUMBER export VPC_NETWORK_NAME=scope:gateway-proxy-8443 export ENVOY_USER="envoy" export ENVOY_USER_UID="1337" export ENVOY_USER_GID="1337" export ENVOY_USER_HOME="/opt/envoy" export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml" export ENVOY_PORT="15001" export ENVOY_ADMIN_PORT="15000" export ENVOY_TRACING_ENABLED="false" export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt" export ENVOY_ACCESS_LOG="/dev/stdout" export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)" export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml" export GCE_METADATA_SERVER="169.254.169.254/32" export INTERCEPTED_CIDRS="*" export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4) # Create system user account for Envoy binary sudo groupadd ${ENVOY_USER} \ --gid=${ENVOY_USER_GID} \ --system sudo adduser ${ENVOY_USER} \ --uid=${ENVOY_USER_UID} \ --gid=${ENVOY_USER_GID} \ --home=${ENVOY_USER_HOME} \ --disabled-login \ --system # Download and extract the Cloud Service Mesh tar.gz file cd ${ENVOY_USER_HOME} sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \ -C bootstrap_template.yaml \ --strip-components 1 sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \ -C iptables.sh \ --strip-components 1 sudo rm traffic-director-xdsv3.tar.gz # Generate Envoy bootstrap configuration cat "${BOOTSTRAP_TEMPLATE}" \ | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \ | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \ | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \ | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \ | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \ | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \ | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \ | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \ | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \ | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \ | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \ | sudo tee "${ENVOY_CONFIG}" # Install Envoy binary wget -O envoy_key https://apt.envoyproxy.io/signing.key cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list sudo apt-get update sudo apt-get install envoy # Run Envoy as systemd service sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \ --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \ bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee" # Configure iptables for traffic interception and redirection sudo ${ENVOY_USER_HOME}/iptables.sh \ -p "${ENVOY_PORT}" \ -u "${ENVOY_USER_UID}" \ -g "${ENVOY_USER_GID}" \ -m "REDIRECT" \ -i "${INTERCEPTED_CIDRS}" \ -x "${GCE_METADATA_SERVER}" 'Create a regional managed instance group from the instance template:
gcloud compute instance-groups managed create gateway-proxy \ --region=${REGION} \ --size=1 \ --template=gateway-proxySet the serving port name for the managed instance group:
gcloud compute instance-groups managed set-named-ports gateway-proxy \ --named-ports=https:8443 \ --region=${REGION}
Set up the regional external passthrough network load balancer
Create a static external regional IP address:
gcloud compute addresses create xnlb-${REGION} \ --region=${REGION}Obtain the IP address that is reserved for the external load balancer:
gcloud compute addresses describe xnlb-${REGION} \ --region=${REGION} --format='value(address)'Create a health check for the gateway proxies:
gcloud compute health-checks create tcp xnlb-${REGION} \ --region=${REGION} \ --use-serving-portCreate a backend service for the gateway proxies:
gcloud compute backend-services create xnlb-${REGION} \ --health-checks=xnlb-${REGION} \ --health-checks-region=${REGION} \ --load-balancing-scheme=EXTERNAL \ --protocol=TCP \ --region=${REGION} \ --port-name=httpsAdd the managed instance group as a backend:
gcloud compute backend-services add-backend xnlb-${REGION} \ --instance-group=gateway-proxy \ --instance-group-region=${REGION} \ --region=${REGION}Create a forwarding rule to route traffic to the gateway proxies:
gcloud compute forwarding-rules create xnlb-${REGION} \ --region=${REGION} \ --load-balancing-scheme=EXTERNAL \ --address=${IP_ADDRESS} \ --ip-protocol=TCP \ --ports=8443 \ --backend-service=xnlb-${REGION} \ --backend-service-region=${REGION}
Configure a managed instance group running an HTTPS service
Create an instance template with an HTTPS service that is exposed on port 8443:
gcloud compute instance-templates create td-https-vm-template \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --tags=https-td-server \ --image-family=debian-11 \ --image-project=debian-cloud \ --metadata=startup-script='#! /bin/bash sudo rm -rf /var/lib/apt/lists/* sudo apt-get -y clean sudo apt-get -y update sudo apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common sudo curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" sudo apt-get -y update sudo apt-get -y install docker-ce sudo which docker echo "{ \"registry-mirrors\": [\"https://mirror.gcr.io\"] }" | sudo tee -a /etc/docker/daemon.json sudo service docker restart sudo docker run -e HTTPS_PORT=9999 -p 8443:9999 --rm -dt mendhak/http-https-echo:22'Create a managed instance group based on the instance template:
gcloud compute instance-groups managed create https-td-mig-us-${REGION} \ --zone=${ZONE} \ --size=2 \ --template=td-https-vm-templateSet the name of the serving port for the managed instance group:
gcloud compute instance-groups managed set-named-ports https-td-mig-us-${REGION} \ --named-ports=https:8443 \ --zone=${ZONE}Create a health check:
gcloud compute health-checks create https https-helloworld-health-check \ --port=8443 --region=${REGION}Create a firewall rule to allow incoming health check connections to instances in your network:
gcloud compute firewall-rules create https-vm-allow-health-checks \ --network ${NETWORK_NAME} --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,130.211.0.0/22 \ --target-tags https-td-server \ --rules tcp:8443Create a regional backend service with a load balancing scheme of
INTERNAL_SELF_MANAGEDand add the health check:gcloud compute backend-services create https-helloworld-service \ --region=${REGION} \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --port-name=https \ --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/https-helloworld-health-check"Add the managed instance group as a backend to the backend service:
gcloud compute backend-services add-backend https-helloworld-service \ --instance-group=https-td-mig-us-${REGION} \ --instance-group-zone=${ZONE} \ --region=${REGION}
Set up routing with a TLSRoute resource
In a file called tls_route.yaml, create the TLSRoute specification:
cat <<EOF > tls_route.yaml name: helloworld-tls-route gateways: - projects/${PROJECT_NUMBER}/locations/${REGION}/gateways/gateway8443 rules: - matches: - sniHost: - example.com alpn: - h2 action: destinations: - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/https-helloworld-service EOFIn the previous instruction, TLSRoute matches example.com as SNI and h2 as ALPN. If the matches are changed as follows, TLSRoute matches SNI or ALPN:
- matches: - sniHost: - example.com - alpn: - h2Use the tls_route.yaml specification to create the TLSRoute resource:
gcloud network-services tls-routes import helloworld-tls-route \ --source=tls_route.yaml \ --location=${REGION}
Validate the deployment
Run the following curl command to verify HTTP connectivity to the test services that you created:
curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -kThe command returns a response from one of the VMs in the managed instance group. The output is similar to the following:
{ "path": "/", "headers": { "host": "example.com:8443", "user-agent": "curl/8.16.0", "accept": "*/*" }, "method": "GET", "body": "", "fresh": false, "hostname": "example.com", "ip": "::ffff:10.128.0.59", "ips": [], "protocol": "https", "query": {}, "subdomains": [], "xhr": false, "os": { "hostname": "19cd7812e792" }, "connection": { "servername": "example.com" }
Verify with a negative verification
In the following command, the SNI does not match example.com, so the Gateway rejects the connection:
curl https://invalid-server.com:8443 --resolve invalid-server.com:8443:${IP_ADDRESS} -kIn the following command, the ALPN does not match h2 (HTTP2 protocol), so the Gateway rejects the connection:
curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k --http1.1The previous commands all return the following error:
curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection.In the following command, the client is creating a plain text (unencrypted) connection, so the Gateway rejects the connection with a 404 Not Found error:
curl example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k