Route traffic from Cloud Run Services to Cloud Service Mesh workloads on GKE
This page shows you how to securely route network traffic from Cloud Run Services to Cloud Service Mesh workloads on GKE to use Istio APIs and make use of a fully-managed Envoy sidecar.
Before you begin
The following sections assume that you have a GKE cluster with Cloud Service Mesh enabled.
If you don't have a GKE Service deployed, use the following command to deploy a sample service:
cat <<EOF > /tmp/service.yaml
apiVersion: v1
kind: Service
metadata:
name: ads
spec:
ports:
- port: 9999
targetPort: 8000
selector:
run: ads
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ads
spec:
replicas: 1
selector:
matchLabels:
run: ads
template:
metadata:
labels:
run: ads
spec:
containers:
- image: docker.io/waip/simple-http:v1.0.1
name: my-http2-svc
ports:
- protocol: TCP
containerPort: 8000
securityContext:
fsGroup: 1337
EOF
kubectl apply -f /tmp/service.yaml
Configure a Custom Domain for VirtualService
hosts
A virtual service defines traffic routing rules. Any matched traffic is then sent to a named destination service
Create a new managed zone:
gcloud dns managed-zones create ZONE_NAME \ --description="zone for service mesh routes" \ --dns-name=DNS_SUFFIX. \ --networks=default \ --visibility=private
where:
- ZONE_NAME is a name for your zone (example: 'prod').
- DNS_SUFFIX is any valid DNS host (example: 'mesh.private').
Create a resource record set:
IP=10.0.0.1 gcloud dns record-sets create '*.'"DNS_SUFFIX." --type=A --zone="ZONE_NAME" \ --rrdatas=10.0.0.1 --ttl 3600
Ensure the IP (RFC 1918 required) is unused. Alternatively, reserve a static internal IP.
Export a
VirtualService
for External Cloud Run Clients:cat <<EOF > virtual-service.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: VIRTUAL_SERVICE_NAME namespace: NAMESPACE spec: hosts: - GKE_SERVICE_NAME.DNS_SUFFIX gateways: - external-mesh http: - route: - destination: host: GKE_SERVICE_NAME EOF kubectl apply -f virtual-service.yaml
where:
- VIRTUAL_SERVICE_NAME is a name for your
VirtualService
. - NAMESPACE is
default
if you're using the provided example service; otherwise, replace NAMESPACE with your namespace name. - GKE_SERVICE_NAME is
ads
if you're using the provided example service; otherwise, replace GKE_SERVICE_NAME with a name for your GKE service.
- VIRTUAL_SERVICE_NAME is a name for your
While it is feasible to add an external-mesh
gateway as a target to a
pre-existing VirtualService
, you should establish a distinct VirtualService
to export a Kubernetes service to external Cloud Run clients. Having a
separate VirtualService
facilitates the management of exported services and
their configurations without affecting existing GKE clients.
Additionally, some fields in VirtualServices
are disregarded for mesh external
VirtualServices
but continue to function as anticipated for GKE
services. So managing and troubleshooting VirtualServices
separately may be
advantageous.
For GKE clients to also receive the VirtualService
configuration,
the mesh
or mesh/default
gateway must be added.
The mesh external VirtualService
must be defined in the same namespace as the
Kubernetes Service in the VirtualService
destination.
Configure a Cloud Run Service to join a service mesh
To join a Cloud Run Service to a service mesh, perform the following steps:
Determine the mesh ID backing the Cloud Service Mesh GKE cluster:
MESH=$(kubectl get controlplanerevision --namespace istio-system -o json | jq -r '.items[0].metadata.annotations["mesh.cloud.google.com/external-mesh"]')
Deploy a Cloud Run Service using the mesh ID, making sure to also connect to the cluster's VPC network:
gcloud alpha run deploy --mesh "$MESH" --network default \ mesh-svc --image=fortio/fortio \ --region=REGION --project=PROJECT_ID --no-allow-unauthenticated
Verify that the Cloud Run service is able to send a request to the GKE workload:
TEST_SERVICE_URL=$(gcloud run services describe mesh-svc --region REGION --format="value(status.url)" --project=PROJECT_ID) curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" "$TEST_SERVICE_URL/fortio/fetch/GKE_SERVICE_NAME.DNS_SUFFIX"
The output should be a valid HTTP 200 response.
Troubleshooting
This section shows you how to troubleshoot common errors with Cloud Service Mesh and Cloud Run.
Cloud Run Sidecar Logs
Envoy errors are logged in Cloud Logging.
For example an error such as the following will be logged if the Cloud Run service account is not given the trafficdirector client role in the mesh project:
StreamAggregatedResources gRPC config stream to trafficdirector.googleapis.com:443 closed: 7, Permission 'trafficdirector.networks.getConfigs' denied on resource '//trafficdirector.googleapis.com/projects/525300120045/networks/mesh:test-mesh/nodes/003fb3e0c8927482de85f052444d5e1cd4b3956e82b00f255fbea1e114e1c0208dbd6a19cc41694d2a271d1ab04b63ce7439492672de4499a92bb979853935b03d0ad0' (or it may not exist).
CSDS
The trafficdirector client state can be retrieved using CSDS:
gcloud alpha container fleet mesh debug proxy-status --membership=<CLUSTER_MEMBERSHIP> --location=<CLUSTER_LOCATION>
External Clients:
....