Continuous Deployment Pipeline to Google Container Engine Using Codeship

Written by: Kelly Andrews
7 min read
Stay connected

This article was originally published on Google Cloud Platform by Kelly Andrews. With their kind permission, we’re sharing it here for Codeship readers.

This tutorial explains how to create a continuous deployment pipeline to Google Container Engine using Codeship. You will learn how to deploy a containerized application when new code is merged into the controller branch and all integration tests have passed.

Continuous deployment is the practice of automating the delivery of software to production after passing a series of tests. Although not for everyone, it should be the goal of any software development and DevOps team not restricted by regulatory constraints.

Before You Begin

Take the following steps to enable the Google Container Engine API:

  1. Visit the Container Engine page in the Google Cloud Platform Console.

  2. Create or select a project.

  3. Wait for the API and related services to be enabled, which can take several minutes.

  4. Enable billing for your project.

Make sure you have the following:

Setting Up the Continuous Deployment Pipeline

Step 1: Create service account

The interactions with the Google Cloud Platform API from Codeship require a service account with permissions to the Cloud Storage and Container Engine services.

Follow these steps to create a service account:

  • Visit the Service accounts page in the Google Cloud Platform Console.

  • Select your project.

  • Click Create Service Account.

  • Enter a name.

  • Click Select a Role and choose the following permissions:

    • Project → Service Account Actor

    • Container → Container Engine Developer

    • Storage → Storage Admin

  • Select Furnish a new private key and leave the option on JSON.

  • Click Create, and then close the dialog once it is created.

After the service account is created, a JSON file with your credentials automatically downloads to your computer. This file will be used in the next step.

Step 2: Set up environment variables

The hello-express source code includes the file example.env. Rename this file to .env.

Inside the file, you will replace the ... with your Google Cloud Platform project details as follows:

  • DEFAULT_ZONE: Select a default compute zone like us-central1-b

  • APP_NAME: Give your application a name; in this case use hello-express

  • CONTAINER_CLUSTER: Give your container cluster a name; in this case use hello-express-cluster

  • GOOGLE_PROJECT_ID: The Project ID is found in the Google Cloud Engine dashboard

  • GOOGLE_AUTH_EMAIL: Use the Service Account ID for the service account created in the last step.

  • GOOGLE_AUTH_JSON: Add the credentials downloaded in the previous step here. You must replace the newlines with spaces by running tr '\n' ' ' < your_file_name

Save the .env file once these items are finished.

Step 3: Run initial deployment

You need to create your clusters and push an image in Container Engine initially before you can set up a fully automated pipeline in Codeship.

Create your container clusters using the Google Cloud SDK by running the following command:

gcloud container clusters create hello-express-cluster --zone=us-central1-b --project=google-project-id

This step takes a few minutes to complete. Once completed, you can verify the clusters are available by running the following command:

gcloud compute instances list --project=google-project-id

which should output something like the following:

NAME                                                 ZONE           MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP      STATUS
gke-hello-express-cluste-default-pool-8f1e33a1-2t09  us-central1-a  n1-standard-1               10.128.0.2   130.211.202.173  RUNNING
gke-hello-express-cluste-default-pool-8f1e33a1-nzwp  us-central1-a  n1-standard-1               10.128.0.4   104.197.248.45   RUNNING
gke-hello-express-cluste-default-pool-8f1e33a1-xcd6  us-central1-a  n1-standard-1               10.128.0.3   130.211.196.247  RUNNING

The hello-express source code includes a bin folder with Bash scripts that perform these tasks using the Codeship Jet CLI.

Make sure the scripts in the bin folder are executable. In a terminal window, navigate to the project folder and run the following command:

chmod -R +x ./bin

Update the image line in the codeship-service.yml file with your Google Cloud Platform project ID.

app:
  build:
    dockerfile: Dockerfile
    image: gcr.io/YOUR_PROJECT_IDE/hello-express #update this line using your Google Cloud Platform project ID
...

Update the image_name line in the codeship_steps.yml file with your Google Cloud Platform project ID.

- name: build-image
  service: app
  command: echo "Build completed"
- name: push-image-with-sha
  service: app
  type: push
  image_name: "gcr.io/YOUR_PROJECT_ID/hello-express" #update this line using your Google Cloud Platform project ID
  image_tag: "{{printf \"%.8s\" .CommitID}}"
  registry: https://gcr.io
  dockercfg_service: codeship_gcr_dockercfg
- name: tag-as-master
  service: app
  type: push
  tag: master
  image_name: "gcr.io/YOUR_PROJECT_ID/hello-express" #update this line using your Google Cloud Platform project ID
  image_tag: "master"
  registry: https://gcr.io
  dockercfg_service: codeship_gcr_dockercfg
- name: gke-initial-deployment
  service: codeship_gce_service
  tag: master
  command: bin/create-deploy
...

This pipeline runs each step in series. The build-image step instructs Codeship to build the hello-express Docker image on the CI server. After Codeship builds the Docker image, the push-image-with-sha step will push the image to Google Container Registry using the name gcr.io/YOUR_PROJECT_ID/hello-express, adding a tag using the first eight characters of the commit SHA for every commit to the repository.

The third and fourth step will run only if the branch is tagged as controller. The tag-as-controller step will add the controller tag to the image pushed to Google Container Registry. This indicates the image in Google Container Registry that is currently deployed.

The following step, gke-initial-deployment, builds the Container Engine cluster and deploys the gcr.io/YOUR_PROJECT_ID/hello-express Docker image.

You will run this pipeline locally using the Codeship Jet CLI. Since there is no git commit or branch to reference, use the ci-commit-id and tag flags with the Codeship Jet CLI to pass in test strings at runtime, (for example, 1234ABCD and controller). The build on the Codeship CI server populates ci-commit-id with the git commit SHA, and tag with the branch or tag name.

Finally, the --push flag instructs the Codeship Jet CLI to run the push steps in the codeship-steps.yml file.

jet steps --ci-commit-id 1234ABCD --tag master --push

This command creates your initial deployment and exposes the application. Once completed, navigate to the Discovery page in the Google Cloud Platform Console to verify the status is ok. Click the endpoint to open the application in the browser. You should see Hello Express!.

Step 4: Create a Codeship project

Now that you have set up the container cluster and deployed the application, you can create the Codeship project. This project will connect to your source control management service. Codeship integrates with the following services:

Use the following steps to create a Codeship project:

  1. Create a new repository.

  2. Copy the clone URL.

  3. Visit the Projects page in the Codeship dashboard.

  4. Click New Project.

  5. Select the service where you created the repository.

  6. Paste the clone URL in the Repository Clone URL field and click Connect.

  7. Click Select Pro Project. Select Pro Project.

Step 5: Encrypt environment variables

You will now encrypt the .env file using the Codeship AES key provided in the project.

Follow these steps to create an encrypted environment file:

  1. Navigate to the new project's General page.

  2. Scroll down to find the AES Key header.

  3. Click Download Key.

  4. Move the downloaded file to the hello-express source code root folder.

  5. Rename this file to codeship.aes.

After you have codeship.aes in the hello-express source code root folder, you can run the encrypt command:

jet encrypt .env encrypted.env

After you encrypt the .env file, you need to update the codeship-services.yml file to use the encrypted file:

app:
  build:
    dockerfile: Dockerfile
    image: gcr.io/YOUR_PROJECT_ID/hello-express
codeship_gcr_dockercfg:
  image: codeship/gcr-dockercfg-generator
  encrypted_env_file: encrypted.env
  add_docker: true
codeship_gce_service:
  image: codeship/google-cloud-deployment
  encrypted_env_file: encrypted.env
  add_docker: true
  working_dir: /deploy
  volumes:
    - ./:/deploy

Step 6: Commit code to run Codeship build

Codeship will trigger a new build when you push a commit to the remote repository. Before you commit the changes, ensure the following files are listed in .gitignore:

codeship.aes
.env
/path/to/your/service-account.json

These three files should not be included in your remote repository, as they contain sensitive data. Be sure to exclude them from any commits.

You also need to update your codeship-steps.yml file to use the gke-update-services step.

...
#- name: gke-initial-deployment
#  service: codeship_gce_service
#  tag: master
#  command: bin/create-deploy
- name: gke-update-services
  service: codeship_gce_service
  tag: master
  command: bin/deploy

After you save these changes, stage all of these files for a commit. Commit the changes to the controller branch, and push to your remote repository. After the push is complete, return to the Codeship project dashboard and watch for a green build.

Step 7: Deploy an update to your application (optional)

You can now modify the code in the server.js file to return something different. Change 'Hello Express!' to something like 'Hello World!'. Once you have changed the application, commit the change and push to your remote repository.

After the Codeship process is completed, navigate to the application endpoint to verify your changes have taken effect.

Cleaning Up

After completing the tutorial, follow these steps to remove the resources from your Google Cloud Platform account to prevent any charges:

Delete the service -- this will deallocate the Cloud Load Balancer created for your Service:

kubectl delete service hello-express

Wait for the load balancer provisioned for the hello-web service to be deleted. The load balancer is deleted asynchronously in the background when you run kubectl delete. Wait until the load balancer is deleted by watching the output of the following command:

gcloud compute forwarding-rules list

Delete the container cluster. This will delete the resources that make up the container cluster, such as the compute instances, disks and network resources.

gcloud container clusters delete hello-cluster

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.