Background
I was able to get these two services to play nice together after a little bit of effort. I stumbled a lot when it came to configuring the roles and permissions due to GCP’s unpredictable behavior behind their roles, but thankfully wrote down every step that I went through to get a workable solution so that you don’t need to do spend the hours of trial an error to accomplish an integration between Github Actions and Google Cloud Run.
There’s a lot of overlap between the projects I work on in my own time, and when I am on the clock working with the team to develop solutions when it comes to two aspects. Due to my limited free time when developing on my own, and our team’s smaller size the solutions I will always favor are ones that are simple, and scale down to zero with no operational effort. So when looking for a CI/CD solution that would support one of my favorite products that Google Cloud Platform (GCP) offers called Cloud Run I wanted to take a look at Github Actions. Github Actions is very similar to Cloud Run in this way as you are only charged for what you use.
Getting started
The example I will be stepping you through will be a simple Flask server deployed via Github Actions to Google Cloud Run. Before I step through the example I have provided a number of concepts, and some requirements that are needed to run this locally.
Concepts
- Github Actions — Github’s automation solution that allows you to supply a yaml configuration to automate tasks such as CI/CD operations.
- Google Cloud Run — A managed serverless platform provided by Google that scales down to zero. The user just needs to provide a Dockerfile for the container to be run.
- Flask — A Python micro web framework commonly used by Python developers.
Requirements
In the example I will be stepping you through you will need two things to run it locally: Python 3.9 and Flask. As with all of my examples your life will be a lot less painful if you install your requirements in a virtual environment via pip. If you are familiar with both of those I would also encourage using virtualenvwrapper which has some really nice extensions that simplify your development environment’s workflow even further.
Step 1: Enable Google Cloud Run
If you skip this step you will actually be presented with the following error which actually is pretty informative.
Otherwise, just click on the link below, and enable the API.
https://console.developers.google.com/apis/library/run.googleapis.com
You should see a screen that contains the following. Make sure that you have your the project you want to deploy to selected which you should see on the navigation bar near the left side.
Step 2: Setup Google Authentication
In this step we will need to create a service account that has a set of permissions needed to deploy to Cloud Run from Github Actions. So navigate to your Google Project, and create this service account. Once the service account is created you will need to select the following roles. I tried a number of different ways to remove the very permissive project viewer role, but at the time of this writing this your service account will need this role or the deployment will appear to fail in Github even if it is successfully deployed to Cloud Run.
All that’s left is just to export a credential for your service account you will need to keep this handy because we will use this later to provide a credential that will allow the Github Action to deploy our web server to Cloud Run.
Step 3: Create or Clone Sample Code to Deploy
Now we could have lead with this step, but since the code really isn’t the valuable part of our process I am planning on focusing more on the integration between Google Cloud Run and Github Actions. For this step, you can do one of two things. Create your own Github repository from scratch or clone the repository below.
https://github.com/dylanroy/google-cloud-run-github-actions
After you have done that note or create a simple hello world endpoint. The example below is from our Github repo, and just provides a simple example that will allow us to see if our integration was successful.
import os from flask import Flask, request app = Flask(__name__) @app.route('/') def hello_world(): name = request.args.get('name', 'World') return f'Hello {name}!' if __name__ == "__main__": app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
The requirements needed to run the project locally, and in the Docker container we will be spinning up are as followed.
Flask gunicorn
A requirements.txt file will need to be created at the base level of your project with those permissions so that we can easily install them in our container.
Step 4: Create Dockerfile for container
If you have already cloned the repo in the previous step the example provided below is identical. If not below is a Dockerfile that worked for me to get a simple Flask server running on Google Cloud Run.
FROM python:3.9-slim # Allow statements and log messages to immediately appear in the Knative logs ENV PYTHONUNBUFFERED True # Copy local code to the container image. COPY . /src WORKDIR /src # Install Python Requirements RUN pip install -r requirements.txt # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
As you can see we provided the slim image for Python 3.9, but this may cause issues or need some updating if you are looking to get something running that was previously running on something such as the latest image of Ubuntu.
The example just configures python to immediately log to Google’s logging telemetry from Cloud Run, install the Python requirements, and serve our Flask server on gunicorn.
Step 5: Create Github Action Workflow
This is just a simple little toy project I just deploy when I push to master. You will likely want your Github Action to trigger on a different action depending on your deployment workflow.
name: cloudrun-deploy on: push: branches: - main jobs: setup-build-publish-deploy: name: Setup, Build, Publish, and Deploy runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@master # Setup gcloud CLI - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master with: service_account_email: ${{ secrets.GCP_EMAIL }} service_account_key: ${{ secrets.GCP_CREDENTIALS }} export_default_credentials: true # Configure Docker with Credentials - name: Configure Docker run: | gcloud auth configure-docker # Build the Docker image - name: Build & Publish run: | gcloud config set project ${{ secrets.GCP_PROJECT }} gcloud builds submit --tag gcr.io/${{ secrets.GCP_PROJECT }}/${{ secrets.GCP_APPLICATION }} gcloud config set run/region us-central1 # Deploy the Docker image to the GKE cluster - name: Deploy run: | gcloud run deploy ${{ secrets.GCP_APPLICATION }} --image gcr.io/${{ secrets.GCP_PROJECT }}/${{ secrets.GCP_APPLICATION }} \ --platform managed \ --allow-unauthenticated \ --memory 512M
The above example is provided in the repo that you may have cloned in a previous step, and will need to exist in the .github/workflows directory in a file that I named deploy.yml, but you can name whatever you please. The Github Action workflow executes the following when code is deployed to main.
In the Action’s first step the action checks out the code that has just been deployed. If you end up using Github Actions frequently you will likely have some sort of step like this “committed” to memory.
In the second step that I forgot to name, but has the comment Setup gcloud CLI does just that. It sets up the gcloud command line interface with the credentials we previously created, and will be storing within Github as secrets.
In the step named Configure Docker
Now that we have the CLI and permissions setup we can now build, and publish our image to GCP.
In our final step we can finally complete our workflow with the Action’s intended purpose, and deploy to Google Cloud Run.
As you can see we have a number of secrets that we haven’t supplied yet in our workflow. Now that we have a Github Action provided that executes the steps needed to deploy to Cloud Run it’s time to safely configure our Github Secrets.
Step 6: Populate Github Secrets
Remember this credential that we downloaded earlier in our first step when we were creating a service account on GCP? This is the step where we place it in its final resting place.
You will next need to navigate to the Settings Dashboard where you can add the following Github secrets. For the cloned repo the link would be the following if you want to navigate directly to the location for your repo. Otherwise, you can just click on Settings in the repo navigation bar, and then click on the Secrets tab.
Here we setup the following Github secrets:
- GCP_APPLICATION — Your Google service account application name for your Cloud Run service.
- GCP_CREDENTIALS — This is your service account credentials that you will need to generate in the Google Cloud Console. You downloaded these in step one. Copy the contents of the JSON file you created, provide that as a value to this secret, and delete that file.
- GCP_EMAIL — This is the email that identifies the service account that you have provided credentials for in the secret labeled GCP_CREDENTIALS.
- GCP_PROJECT — Your Google Project that you will deploying to Cloud Run.
Completion: Run Your New Action
At this point, all that’s needed to test this is to do a sample push to your main branch, and watch the Action run through its steps.
GCP Exam Dumps:
If you wish buy Google Cloud Exam Dumps, I highly recommended this site: https://www.gcp-examquestions.com
Source: Dylan – Medium