Skip to content

Instantly share code, notes, and snippets.

@lynnlangit
Last active July 1, 2022 14:36
Show Gist options
  • Save lynnlangit/725f44779641a0e2c5b2bacb9768e04e to your computer and use it in GitHub Desktop.
Save lynnlangit/725f44779641a0e2c5b2bacb9768e04e to your computer and use it in GitHub Desktop.
GCP CloudBuild CI/CD Demo
We can make this file beautiful and searchable if this error is corrected: Illegal quoting in line 15.
# Start
[https://cloud.google.com/kubernetes-engine/docs/tutorials/gitops-cloud-build](https://cloud.google.com/kubernetes-engine/docs/tutorials/gitops-cloud-build)
gcloud commands as a GitHub gist - [https://gist.github.com/lynnlangit/725f44779641a0e2c5b2bacb9768e04e](https://gist.github.com/lynnlangit/725f44779641a0e2c5b2bacb9768e04e)
# Use GCP test project
gcloud config set project [PROJECT_ID]
# Enable APIs
gcloud services enable container.googleapis.com \
cloudbuild.googleapis.com \
sourcerepo.googleapis.com \
containeranalysis.googleapis.com
# Create GKE (Kubernetes) cluster
gcloud container clusters create hello-cloudbuild \
--num-nodes 1 --zone us-central1-b
# Configure git for cloud shell
git config --global user.email "[YOUR_EMAIL_ADDRESS]"
git config --global user.name "[YOUR_NAME]"
# Create 2 CSR code Repos
# app repository: contains the source code of the application itself
#Â env repository: contains the manifests for the Kubernetes Deployment
gcloud source repos create hello-cloudbuild-app
gcloud source repos create hello-cloudbuild-env
# Clone sample code
cd ~
git clone [https://github.com/GoogleCloudPlatform/gke-gitops-tutorial-cloudbuild](https://github.com/GoogleCloudPlatform/gke-gitops-tutorial-cloudbuild) \
hello-cloudbuild-app
# Review sample app code
from flask import Flask
app = Flask('hello-cloudbuild')
@app.route('/')
def hello():
return "Hello World!\n"
if __name__ == '__main__':
app.run(host = '0.0.0.0', port = 8080)
# Review sample Dockerfile
FROM python:3.7-slim
RUN pip install flask
WORKDIR /app
COPY app.py /app/app.py
ENTRYPOINT ["python"]
CMD ["/app/app.py"]
# Configure CSR code Repo as remote
cd ~/hello-cloudbuild-app
PROJECT_ID=$(gcloud config get-value project)
git remote add google \
"[https://source.developers.google.com/p/](https://source.developers.google.com/p/)${PROJECT_ID}/r/hello-cloudbuild-app"
# Build & Register your image
cd ~/hello-cloudbuild-app
COMMIT_ID="$(git rev-parse --short=7 HEAD)"
gcloud builds submit --tag="gcr.io/${PROJECT_ID}/hello-cloudbuild:${COMMIT_ID}" .
# View CI YAML pipeline code
# This example does NOT include any validation step before deployment
# If using GitHub, etc.. you could modify this file to use Pull Requests (PRs) for this
# You may chose to use Spinnaker - [http://spinnaker.io/](http://spinnaker.io/) for more complex scenarios
# CLOUD BUILDERSÂ -> containers with common languages & tools installed in themÂ
# Use the builders to execute your tasks by including them in build steps
# Examples: bazel, docker, git, go, gcloud, gradle, maven, kubectl, npm
# Src for cloud builders at [https://github.com/GoogleCloudPlatform/cloud-builders](https://github.com/GoogleCloudPlatform/cloud-builders)
steps:
# This step runs the unit tests on the app
- name: 'python:3.7-slim'
id: Test
entrypoint: /bin/sh
args:
- -c
- 'pip install flask && python test_app.py -v'
# This step builds the container image using the Cloud Build docker builder
# Here's a list of all builders -- [https://github.com/GoogleCloudPlatform/cloud-builders](https://github.com/GoogleCloudPlatform/cloud-builders)
- name: 'gcr.io/cloud-builders/docker'
id: Build
args:
- 'build'
- '-t'
- 'gcr.io/$PROJECT_ID/hello-cloudbuild:$SHORT_SHA'
- '.'
# This step pushes the image to Container Registry
# The PROJECT_ID and SHORT_SHA variables are automatically
# replaced by Cloud Build.
- name: 'gcr.io/cloud-builders/docker'
id: Push
args:
- 'push'
- 'gcr.io/$PROJECT_ID/hello-cloudbuild:$SHORT_SHA'
# Create a Cloud Build trigger
Use GCP console -> Cloud Build -> Triggers
# Select CSR (code) as source
Select 'hello-cloudbuild-app' as source
Name: hello-cloudbuild
Branch: master
Build configuration: cloudbuild.yaml
# Push local code into CSR
cd ~/hello-cloudbuild-app
git push google master
# View Cloud Build to verify
View result in Google Console - Cloud Build
# Grant Cloud Build access to GKE (Kubernetes)
PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} --format='get(projectNumber)')"
gcloud projects add-iam-policy-binding ${PROJECT_NUMBER} \
--member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role=roles/container.developer
# Init the 'hello-cloudbuild-env' repo
cd ~
gcloud source repos clone hello-cloudbuild-env
cd ~/hello-cloudbuild-env
git checkout -b production
# Review the cloudbuild-delivery.yaml file
# The candidate branch is a history of the deployment ATTEMPTS
# The production branch is a history of the SUCCESSFUL deployments
# This pipeline uses the sed tool to render the manifest template.
# In prod, you'd use a tool such as kustomize or skaffold for more control over the rendering of the manifest templates
steps:
# This step deploys the new version of our container image
# in the hello-cloudbuild Kubernetes Engine cluster.
- name: 'gcr.io/cloud-builders/kubectl'
id: Deploy
args:
- 'apply'
- '-f'
- 'kubernetes.yaml'
env:
- 'CLOUDSDK_COMPUTE_ZONE=us-central1-b'
- 'CLOUDSDK_CONTAINER_CLUSTER=hello-cloudbuild'
# This step copies the applied kubernetes deployment manifest to the prod branch
# The COMMIT_SHA variable is automatically replaced by Cloud Build.
- name: 'gcr.io/cloud-builders/git'
id: Copy to production branch
entrypoint: /bin/sh
args:
- '-c'
- |
set -x && \
# Configure Git to create commits with Cloud Build's service account
git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)') && \
# Switch to the production branch and copy the kubernetes.yaml file from the candidate branch
git fetch origin production && git checkout production && \
git checkout $COMMIT_SHA kubernetes.yaml && \
# Commit the kubernetes.yaml file with a descriptive commit message
git commit -m "Manifest from commit $COMMIT_SHA
$(git log --format=%B -n 1 $COMMIT_SHA)" && \
# Push the changes back to Cloud Source Repository
git push origin production
# Copy cloudbuild-delivery.yaml & commit
cd ~/hello-cloudbuild-env
cp ~/hello-cloudbuild-app/cloudbuild-delivery.yaml ~/hello-cloudbuild-env/cloudbuild.yaml
git add .
git commit -m "Create cloudbuild.yaml for deployment"
# Grant permissions to Cloud Build Service account
PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} \
--format='get(projectNumber)')"
cat >/tmp/hello-cloudbuild-env-policy.yaml <<EOF
bindings:
- members:
- serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com
role: roles/source.writer
EOF
gcloud source repos set-iam-policy \
hello-cloudbuild-env /tmp/hello-cloudbuild-env-policy.yaml
# Create a candidate branch & push
git checkout -b candidate
git push origin production
git push origin candidate
# Create a Build trigger
Use GCP console, Cloud Build -> Triggers
# Select CSR (code) as source
select 'hello-cloudbuild-env' repo
name: hello-cloudbuild-deploy
branch: candidate
build configuration: cloudbuild.yaml
# Copy extended YAML to CSR (code)
cd ~/hello-cloudbuild-app
cp cloudbuild-trigger-cd.yaml cloudbuild.yaml
# Review the cloudbuild-trigger.yaml code
# The candidate branch is a history of the deployment ATTEMPTS
# The production branch is a history of the SUCCESSFUL deployments
# This pipeline uses the sed tool to render the manifest template.
# In prod, you'd use a tool such as kustomize or skaffold for more control over the rendering of the manifest templates
# This step clones the hello-cloudbuild-env repository
- name: 'gcr.io/cloud-builders/gcloud'
id: Clone env repository
entrypoint: /bin/sh
args:
- '-c'
- |
gcloud source repos clone hello-cloudbuild-env && \
cd hello-cloudbuild-env && \
git checkout candidate && \
git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)')
# This step generates the new kubernetes manifest
- name: 'gcr.io/cloud-builders/gcloud'
id: Generate manifest
entrypoint: /bin/sh
args:
- '-c'
- |
sed "s/GOOGLE_CLOUD_PROJECT/${PROJECT_ID}/g" kubernetes.yaml.tpl | \
sed "s/COMMIT_SHA/${SHORT_SHA}/g" > hello-cloudbuild-env/kubernetes.yaml
# This step pushes the kubernetes manifest back to hello-cloudbuild-env
- name: 'gcr.io/cloud-builders/gcloud'
id: Push manifest
entrypoint: /bin/sh
args:
- '-c'
- |
set -x && \
cd hello-cloudbuild-env && \
git add kubernetes.yaml && \
git commit -m "Deploying image gcr.io/${PROJECT_ID}/hello-cloudbuild:${SHORT_SHA}
Built from commit ${COMMIT_SHA} of repository hello-cloudbuild-app
Author: $(git log --format='%an ' -n 1 HEAD)" && \
git push origin candidate
# Commit & push new yaml
cd ~/hello-cloudbuild-app
git add cloudbuild.yaml
git commit -m "Trigger CD pipeline"
git push google master
# View builds in Cloud Build (CI & CD)
Verify in console -> Cloud Build
# View then Update code
Go to GKE -> 'hello-cloudbuild' service
Click on endpoint, see 'Hello World'
cd ~/hello-cloudbuild-app
sed -i 's/Hello World/Hello Cloud Build/g' app.py
sed -i 's/Hello World/Hello Cloud Build/g' test_app.py
# Commit & Push
git add app.py test_app.py
git commit -m "Hello Cloud Build"
git push google master
# Reload app, see 'Hello Cloud Build'
View in browser
# Test rollback, go to Cloud Build
Use GCP console, Cloud Build
# Mirror a GitHub Repo and use Cloud Build
[https://cloud.google.com/source-repositories/docs/mirroring-a-github-repository](https://cloud.google.com/source-repositories/docs/mirroring-a-github-repository)
# Connect Cloud Build to a GitHub Repo
[https://cloud.google.com/cloud-build/docs/run-builds-on-github](https://cloud.google.com/cloud-build/docs/run-builds-on-github)
# Deploy with Spinnaker and Cloud Build
[https://cloud.google.com/solutions/continuous-delivery-spinnaker-kubernetes-engine](https://cloud.google.com/solutions/continuous-delivery-spinnaker-kubernetes-engine)
# Build CI/CD for bioinformatics
[https://read.acloud.guru/cloud-based-ci-cd-on-gcp-6b07fde7222d](https://read.acloud.guru/cloud-based-ci-cd-on-gcp-6b07fde7222d)
# Delete Git Repos
cd ~
rm -rf ~/hello-cloudbuild-app
rm -rf ~/hello-cloudbuild-env
# Delete Git CSRs
gcloud source repos delete hello-cloudbuild-app --quiet
gcloud source repos delete hello-cloudbuild-env --quiet
# Delete Cloud Build Triggers
In console
# Delete images in GCR
gcloud beta container images list-tags \
gcr.io/${PROJECT_ID}/hello-cloudbuild \
--format="value(tags)" | \
xargs -I {} gcloud beta container images delete \
--force-delete-tags --quiet \
gcr.io/${PROJECT_ID}/hello-cloudbuild:{}
# Remove Cloud Build permissions in GKE
PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} \
--format='get(projectNumber)')"
gcloud projects remove-iam-policy-binding ${PROJECT_NUMBER} \
--member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role=roles/container.developer
# Delete GKE Cluster
gcloud container clusters delete hello-cloudbuild \
--zone us-central1-b
@lynnlangit
Copy link
Author

make csv

@lynnlangit
Copy link
Author

added more comments about yaml files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment