Deploying Your Service to Cloud Run
Here’s how you deploy your service to cloud run (and then have it use a Cloud Endpoint API Gateway).
Create a Basic Service
Let’s say you have a basic service with some endpoints.
from flask import Flask
app = Flask(__name__)
@app.route('/hello')
def hello():
return 'Hello, World!'
@app.route('/goodbye')
def goodbye():
return 'Goodbye, World!'
if __name__ == '__main__':
app.run()
Basic Deploy
You can deploy your service to Cloud Run by running the following command:
gcloud run deploy --image gcr.io/PROJECT_ID/IMAGE_NAME --platform managed --concurrency 20 --allow-unauthenticated
Where:
--image
specifies the docker image of your service.--platform managed
tells GCP to automatically scale the number of instances based on volume of requests.--concurrency
specifies the max number of concurrent requests each instance should handle. GCP will spin a new instance if the number of requests exceeds this limit. Defaults to 80.--allow-unauthenticated
allows unauthenticated access to your service.
You can optionally add --region REGION
to deploy to a specific region.
This command returns a URL for your deployed service, which you can use to access it via HTTP.
Adding API Gateway (Cloud Endpoints)
Create an OpenAPI spec for Cloud Endpoints.
swagger: '2.0'
info:
title: My Service
description: My Service API
version: 1.0.0
host: YOUR_API_GATEWAY_HOST
x-google-endpoints:
- name: YOUR_API_GATEWAY_HOST
allowCors: true
paths:
/hello:
get:
summary: Hello World
operationId: hello
responses:
'200':
description: A successful response
schema:
type: string
/goodbye:
get:
summary: Goodbye World
operationId: goodbye
responses:
'200':
description: A successful response
schema:
type: string
“Deploy” your API spec to cloud endpoints:
gcloud endpoints services deploy OPENAPI_SPEC.yaml
Deploy ESP (proxy HTTP server) to Cloud Run (in front of your service, which is also running in a Cloud Run instance):
gcloud run deploy espv2-gateway \
--image=gcr.io/endpoints-release/endpoints-runtime:latest \
--args="--config=/etc/endpoints/OPENAPI_SPEC.yaml,--backend=https://YOUR_CLOUD_RUN_URL" \ # <-- the URL of your service
--platform managed \
--allow-unauthenticated \
--region REGION
This returns the URL of the ESP (proxy HTTP server), which is what you should ask clients to use when accessing your API.
Adding Authentication
In your OpenAPI spec, specify that authentication is required and the type(s) of authentication.
securityDefinitions:
api_key:
type: "apiKey"
name: "key"
in: "query"
firebase_auth:
type: "oauth2"
flow: "implicit"
authorizationUrl: "https://your-auth-server.com/auth" # documentation purpose only, clients must know this themselves
x-google-issuer: "https://your-auth-server.com/"
x-google-jwks_uri: "https://your-auth-server.com/.well-known/jwks.json"
x-google-audiences: "https://your-auth-server.com/"
paths:
/api/hello:
get:
security:
- api_key: []
/api/goodbye:
get:
security:
- api_key: []
- firebase_auth: []
Redeploy your service in cloud run but be sure to not specify --allow-unauthenticated
.
Diagrams
Here are some diagrams that visually depict this “architecture”.
An API Gateway (ESP) sits between your clients and your service. Note that ESP is also running in cloud run:
flowchart LR
Client[Client]
ESP[ESP]
Service[Service]
Client --> ESP --> Service
The ESP just forwards requests from clients to the service:
sequenceDiagram
participant Client
participant ESP as ESP
participant Service
Client->>ESP: HTTP Request e.g., /hello
ESP->>Service: Forwarded Request
Service-->>ESP: Response
ESP-->>Client: Response
If you have setup your ESP to authenticate (via the OpenAPI spec of your API), here is how authentication flow happens:
sequenceDiagram
participant Client
participant ESP as ESP
participant Service
Client->>ESP: HTTP Request e.g., /hello
ESP->>ESP: Validate Token Using public Key
alt Token Valid
ESP->>Service: Forwarded Request
Service-->>ESP: Response
ESP-->>Client: Response
else Token Invalid or Missing
ESP-->>Client: 401 Unauthorized
end
If token is missing/invalid, it is the job of the client to redirect to the identity provider, get a token, and try the HTTP request again:
sequenceDiagram
participant Client
participant Auth as Auth Server
Client->>Auth: Redirect for Token
Auth-->>Client: Token
Client->>ESP: HTTP Request e.g., /hello
Summary
Basic (no authentication):
- Upload the docker image of your service to Google’s artifact registry.
gcloud run deploy
your service to deploy it in cloud run; you get back a URL to access it through.With Authentication:
- Create an OpenAPI spec for your API, specifying the authentication methods you want to support (token-based, external identity provider, etc.)
gcloud run deploy
your service to deploy it in cloud run; you get back a URL to access it through, don’t provide this to clients.gcloud endpoints services deploy
your OpenAPI spec to create/update the API config.gcloud run deploy
your ESP (proxy) service to Cloud Run. You’ll need to specify the URL of your service as the target of the proxy.