`gcloud beta run services replace`
- 3 minutes read - 441 wordsTL;DR I’m working on a project that includes multiple Cloud Run services. I’ve been putting my
gcloud
head on to deploy these services thinking that it’s curious there’s no way to write the specs as YAML configs. Today, I learned that there is:gcloud beta run services replace
.
What prompted the discovery was some frustration trying to deploy a JSON-valued environment variable to Cloud Run:
local FIREBASE_CONFIG="{
apiKey: ${FIREBASE_API_KEY},
authDomain: ${FIREBASE_AUTH_DOMAIN},
projectId: ${FIREBASE_PROJECT},
storageBucket: ${FIREBASE_STORAGE_BUCKET},
messagingSenderId: ${FIREBASE_MESSAGING_SENDER},
appId: ${FIREBASE_APP}}"
gcloud run deploy ${SRV_NAME} \
--image=${IMAGE} \
--command="/server" \
--args="--endpoint=:${PORT}" \
--set-env-vars=FIREBASE_CONFIG="${FIREBASE_CONFIG}" \
--max-instances=1 \
--memory=256Mi \
--ingress=all \
--platform=managed \
--port=${PORT} \
--allow-unauthenticated \
--region=${REGION} \
--project=${PROJECT}
gcloud
balks at this.
Curiously, I was able to craft – what I think is – the equivalent command using the Cloud Console and it is able to apply the service correctly.
Unfortunately, there’s a bug in Cloud Console and it’s not possible (for me!?) to use the “SHOW COMMAND LINE” feature to render the equivalent gcloud
command so that path was fruitless:
I tried:
- various permutations of
FIREBASE_CONFIG
- gcloud topic escaping
--flags-file
All to no avail.
I was thinking, it would be so much easier if I could just apply a Kubernetes (Knative) config to Cloud Run!
Then I stumbled upon a question about this on Stack overflow that I’m no longer able to find which included the hitherto unknown to me gcloud beta services replace
command, et voila! It worked first time.
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: SRV_NAME
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/maxScale: '1'
spec:
containers:
- command:
- /server
args:
- --endpoint=:8080
env:
- name: FIREBASE_CONFIG
value: |
{
"apiKey": "API_KEY",
"authDomain": "AUTH_DOMAIN",
"projectId": "PROJECT_ID",
"storageBucket": "STORAGE_BUCKET",
"messagingSenderId": "MESSAGING_SENDER_ID",
"appId": "APP_ID"
}
image: IMAGE
ports:
- containerPort: PORT
name: http1
resources:
limits:
cpu: 1000m
memory: 512Mi
Previously I’ve used the excellent jsonnet to manage templated YAML and I suspect I should become more familiar with kustomize because it’s built-in to kubectl
but, I’ve been using sed:
sed \
--expression="s|SRV_NAME|${SRV_NAME}|g" \
--expression="s|IMAGE|${IMAGE}|g" \
--expression="s|PORT|${PORT}|g" \
--expression="s|API_KEY|${API_KEY}|g" \
--expression="s|AUTH_DOMAIN|${AUTH_DOMAIN}|g" \
--expression="s|PROJECT_ID|${PROJECT_ID}|g" \
--expression="s|STORAGE_BUCKET|${STORAGE_BUCKET}|g" \
--expression="s|MESSAGING_SENDER|${MESSAGING_SENDER}|g" \
--expression="s|APP_ID|${APP_ID}|g" \
${PWD}/cloudrun.${SRV_NAME}.tmpl > ${PWD}/cloudrun.${SRV_NAME}.yaml
gcloud beta run services replace ${PWD}/cloudrun.${SRV_NAME}.yaml \
--platform=managed \
--region=${REGION} \
--project=${PROJECT}
Which, I’ll admit is a little gnarly but it does the trick!
IIUC (!?) gcloud run deploy --allow-unauthenticated
is not replicated in gcloud beta services replace
. The gcloud run deploy
flag effectively applies a binding to the service for allUsers
to be able to invoke the service (i.e. run.invoker
) and so a second command is necessary to replicate this when using gcloud beta services replace
, namely:
gcloud run services add-iam-policy-binding ${SRV_NAME} \
--member="allUsers" \
--role="roles/run.invoker" \
--region=${REGION} \
--project=${PROJECT}