Cloud Run: Env Variables, Security and Deployment Pipeline
In my previous post, I wrote about deploying an application to Cloud Run and how Cloud Build can be used to package and Cloud Deploy can be used to build a deployment pipeline. As I deployed the pipeline solution, I came across some challenges which I wanted to cover to close some of the loose ends.
Environment configuration
In the previous blog post, I covered about deploying the application but mentioned about using the pipeline to deliver the same code across all the environment going all the way to TEST and PROD. For a container image, a good practice is to migrate the same image without building one for different environment. This is handled in Kubernetes by externalizing changing values as Environment Variables and Cloud Run has provision for Environment Variables as well. Not to be outdone, just as K8 has configurations for secrets, Cloud Run has as well.
In this scenario, a spring boot application’s application.properties have been externalized. A thing to note, the variables need to be upper cased and a dot(.) is replaced by an underscore(_) so in this case, spring.jpa.show-sql becomes SPRING_JPA_SHOW-SQL
Cloud SQL Connectivity
If an application uses a Cloud SQL instance as its backend-like this one, Cloud Run provides an out of the box configuration. The configuration differs depending on the ip associated with the Cloud SQL instance. If its Private IP-which is suggested and recommended approach, a Serverless VPC Configuration is used.
For a Public IP Cloud SQL instance, Cloud Run utilizes a Cloud SQL Auth Proxy that connects the application with the backend DB.
Security
Cloud Run uses the default Compute Engine service account to run services created for the project i.e. (project-id)-compute@developer.gserviceaccount.com. This account may carry more permissions than desired and is not a recommended approach. The suggested approach is to create a Service Account for the service with fine grained permissions as required by the service and is configured in here —
Deployment Pipelines
Finally, the configuration mentioned is being done via cloud console, which may be ok to do for a PoC but in practice with CI/CD and pipeline based delivery, the properties and configurations are set to avoid manual intervention. It takes us back to skaffold.yaml and the environment yaml configuration being used by Cloud Deploy.
Skaffold.yaml
apiVersion: skaffold/v3alpha1
kind: Config
metadata:
name: spring-api #name of the cloud run service
profiles:
- name: dev
manifests:
rawYaml:
- run-dev.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: spring-api
selfLink: /apis/serving.knative.dev/v1/namespaces/756278427423/services/webapps
labels:
cloud.googleapis.com/location: us-west1
spec:
template:
metadata:
annotations:
run.googleapis.com/client-name: cloud-console
run.googleapis.com/vpc-access-egress: private-ranges-only
run.googleapis.com/cloudsql-instances: dev-project-id:us-west1:instance-name
autoscaling.knative.dev/maxScale: '100'
run.googleapis.com/vpc-access-connector: projects/dev-project-id/locations/us-west1/connectors/postgresql-connector
spec:
serviceAccountName: spring-api@dev-project-id.iam.gserviceaccount.com
containers:
- image: spring-api-image
env:
- name: SPRING_CLOUD_GCP_SQL_INSTANCE-CONNECTION-NAME
value: dev-project-id:us-west1:instance-name
- name: SPRING_CLOUD_GCP_PROJECT-ID
value: dev-project-id
- name: SPRING_JPA_SHOW-SQL
value: 'false'
In the run-dev.yaml file, the configurations are specified which were done using the cloud console. Similar configuration will be set for other environments to avoid a human intervention.
Summary
To summarize the features of Cloud Run we walked thru -
- Externalize application properties via Environment Variables
- Connectivity with Cloud SQL with Public or Private IP
- Service Account association with Cloud Run
- Using Service YAML file for deployment via Cloud Deploy