Cloud Run with a gRPC probe
- 3 minutes read - 428 wordsCloud Run supports gRPC startup|liveness probes which I’d not used before.
I’m using Cloud Run v2 and specifically projects.locations.services.create
and Service
PROJECT="..."
REGION="..."
REPO=".."
# Must be in an Artifact Registry repo
IMAGE="${REGION}-docker.pkg.dev/${PROJECT}/${REPO}/..."
# Run v2
ENDPOINT="https://run.googleapis.com/v2"
PARENT="projects/${PROJECT}/locations/${REGION}"
SERVICE="..."
I like to use Jsonnet (specifically go-jsonnet
) to help templating Kubernetes(-like) deployments.
cloudrun.jsonnet
:
local project = std.extVar("project");
local region = std.extVar("region");
local service = std.extVar("service");
local image = std.extVar("image");
local port = 8080;
local health_checking_service = "foo";
{
"labels":{
"type": "test"
},
"annotations": {
"type": "test"
},
"template":{
"containers": {
"name": service,
"image": image,
"args": [],
"resources": {
"limits": {
"cpu": "1000m",
"memory": "512Mi"
}
},
"ports": [
{
"name": "http1",
"containerPort": port
}
],
"startupProbe": {
"grpc": {
"port": port,
"service": health_checking_service
}
}
},
"scaling": {
"maxInstanceCount": 1
}
}
}
And deploy it using:
# Once every hour
TOKEN=$(gcloud auth print-access-token)
jsonnet cloudrun.jsonnet \
--ext-str image="${IMAGE}" \
--ext-str project="${PROJECT}" \
--ext-str region="${REGION}" \
--ext-str service="${SERVICE}" \
| curl \
--request POST \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data @- \
"${ENDPOINT}/${PARENT}/services?serviceId=${SERVICE}&validateOnly=false"
NOTE You can’t combine
--data-urlencode
with--request POST
and so the querystring parameters are embedded in the URL.
The output will be an Operation:
{
"name": "projects/{PROJECT}/locations/{REGION}/operations/{ID}}",
"metadata": {
"@type": "type.googleapis.com/google.cloud.run.v2.Service",
"name": "projects/{PROJECT}/locations/{REGION}/services/{SERVICE}",
"uid": "{UID}",
"generation": "1",
"labels": {},
"annotations": {},
"createTime": "YYYY-MM-DDTHH:MM:SS.000000Z",
"updateTime": "YYYY-MM-DDTHH:MM:SS.000000Z",
"creator": "my@email.com",
"lastModifier": "my@email.com",
"launchStage": "GA",
"template": {
"scaling": {
"maxInstanceCount": 1
},
"timeout": "300s",
"serviceAccount": "{EMAIL}",
"containers": [
{
"name": "{SERVICE}",
"image": "{REGION}-docker.pkg.dev/{PROJECT}/{REPO}/{IMAGE}",
"args": [],
"resources": {
"limits": {
"cpu": "1000m",
"memory": "512Mi"
}
},
"ports": [
{
"name": "http1",
"containerPort": 8080
}
],
"startupProbe": {
"timeoutSeconds": 1,
"periodSeconds": 10,
"failureThreshold": 3,
"grpc": {
"port": 8080,
"service": "foo"
}
}
}
],
"maxInstanceRequestConcurrency": 80
},
"traffic": [
{
"type": "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST",
"percent": 100
}
],
"urls": [
"https://{SERVICE}-{NUMBER}.{REGION}.run.app"
],
"terminalCondition": {
"state": "CONDITION_PENDING"
},
"reconciling": true,
"etag": "..."
}
}
Doing this, I notice that Cloud Run now provides deterministic ({SERVICE}-{NUMBER}.{REGION}.run.app
) URLs which is good.
You can grab the service’s logs:
FILTER="
resource.type=\"cloud_run_revision\"
resource.labels.service_name=\"${SERVICE}\"
resource.labels.location=\"${REGION}\"
textPayload=~\"^STARTUP GRPC probe\"
"
gcloud logging read "${FILTER}" \
--project=${PROJECT} \
--format="value(textPayload)" \
--order=asc
STARTUP GRPC probe succeeded after 1 attempt for container "{SERVICE}" on port {PORT}.
STARTUP GRPC probe succeeded after 1 attempt for container "{SERVICE}" on port {PORT}.
STARTUP GRPC probe succeeded after 1 attempt for container "{SERVICE}" on port {PORT}.
STARTUP GRPC probe succeeded after 1 attempt for container "{SERVICE}" on port {PORT}.
If necessary, delete the Service once you’re done:
gcloud run services delete ${SERVICE} \
--region=${REGION} \
--project=${PROJECT} \
--quiet
That’s all!