Skip to content

[GCP][PROD] Deploy to GKE via Helm #321

[GCP][PROD] Deploy to GKE via Helm

[GCP][PROD] Deploy to GKE via Helm #321

# This workflow build and push a Docker container to Google Artifact Registry and deploy it on Google Kubernetes Engine when a commit is pushed to the "develop" branch
# You can start your commit with `#update` and the workflow will just trigger an update of the Helm installation, without building a new image
#
# To configure this workflow:
#
# 1. Ensure the required Google Cloud APIs are enabled in the project:
#
# Cloud Build cloudbuild.googleapis.com
# Kubernetes Engine API container.googleapis.com
# Artifact Registry artifactregistry.googleapis.com
#
# 2. Create a service account (if you don't have one) with the following fields:
#
# Service Account Name <PROJECT-NAME>-github-actions
# Service Account ID <PROJECT-NAME>-github-actions
#
# 3. Ensure the service account have the required IAM permissions granted:
#
# Kubernetes Engine Developer
# roles/container.developer (kubernetes engine developer)
#
# Artifact Registry
# roles/artifactregistry.repoAdmin (artifact registry repository administrator)
# roles/artifactregistry.admin (artifact registry administrator)
#
# Service Account
# roles/iam.serviceAccountUser (act as the Cloud Run runtime service account)
#
# Basic Roles
# roles/viewer (viewer)
#
# NOTE: You should always follow the principle of least privilege when assigning IAM roles
#
# 4. Ensure you have the following GitHub Secrets and Variables:
#
# GitHub Secrets
# GCP_SA_KEY (Google Cloud Project Service Account Key) ref visit https://github.com/Datawheel/company/wiki/Setting-Up-a-Service-Account-for-Workflows#use-the-service-account-on-github-secrets
#
# GitHub Variables
# GCP_PROJECT_ID (Google Cloud Project ID)
# GCP_ARTIFACT_REGISTRY_NAME (Google Cloud Articaft Registry Repository Name)
# GCP_ARTIFACT_REGISTRY_LOCATION (Google Cloud Artifact Registry Reposotiry Location)
#
# 5. Ensure you have the following GitHub Variables for each environment that you will set up:
#
# GitHub Variables
# GCP_IMAGE_NAME (Docker Image Name)
# GKE_APP_NAME (Google Kubernetes Engine Deployment Name)
# GKE_APP_NAMESPACE (Google Kubernetes Engine Deployment Namespace)
# GKE_CLUSTER (Google Kubernetes Engine Cluster Name)
# GKE_ZONE (Google Kubernetes Engine Cluster Zone)
#
# Further reading:
# Kubernetes Developer - https://cloud.google.com/iam/docs/understanding-roles#container.developer
# Artifact Registry IAM permissions - https://cloud.google.com/artifact-registry/docs/access-control#roles
# Container Registry vs Artifact Registry - https://cloud.google.com/blog/products/application-development/understanding-artifact-registry-vs-container-registry
# Principle of least privilege - https://cloud.google.com/blog/products/identity-security/dont-get-pwned-practicing-the-principle-of-least-privilege
# Deploy CloudRun Github Actions - https://github.com/google-github-actions/deploy-cloudrun
name: "[GCP][PROD] Deploy to GKE via Helm"
on:
workflow_dispatch:
inputs:
release:
description: 'Production Release Name'
required: true
type: string
date:
description: 'Production Release Date'
required: true
type: string
update_release:
description: 'Check if you are updating the production release name of the latest image'
required: true
type: boolean
env:
GCP_PROJECT_ID: ${{ vars.GCP_PROJECT_ID }}
GCP_ARTIFACT_REGISTRY_NAME: ${{ vars.GCP_ARTIFACT_REGISTRY_NAME }}
GCP_ARTIFACT_REGISTRY_LOCATION: ${{ vars.GCP_ARTIFACT_REGISTRY_LOCATION }}
GCP_IMAGE_NAME: ${{ vars.GCP_IMAGE_NAME }}
GKE_APP_NAME: ${{ vars.GKE_APP_NAME }}
GKE_APP_NAMESPACE: ${{ vars.GKE_APP_NAMESPACE }}
GKE_CLUSTER: ${{ vars.GKE_CLUSTER }}
GKE_ZONE: ${{ vars.GKE_ZONE }}
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
jobs:
deploy:
environment: production
runs-on: ubuntu-latest
# runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v3
# Authentication via credentials json
- name: Google Auth
id: auth
uses: google-github-actions/auth@v2
with:
project_id: ${{ env.GCP_PROJECT_ID }}
credentials_json: ${{ secrets.GCP_SA_KEY }}
# Get google kubernetes engine credentials
- name: Get GKE Credentials
uses: google-github-actions/get-gke-credentials@v2
with:
cluster_name: ${{ env.GKE_CLUSTER }}
location: ${{ env.GKE_ZONE }}
## INSTALL NGINX INSTANCE FOR THE ENVIRONMENT ON THE CLUSTER
# Add nginx repo to Helm
# - name: Add NGINX repo to Helm
# uses: WyriHaximus/github-action-helm3@v2
# with:
# exec: helm repo add nginx-stable https://helm.nginx.com/stable
# Update Helm repos
# - name: Update Helm repos
# uses: WyriHaximus/github-action-helm3@v2
# with:
# exec: helm repo update
# Install Helm chart
- name: Update NGINX instance for the canon instance in the cluster
uses: WyriHaximus/github-action-helm3@v2
env:
CACHE_IP: ${{ secrets.CACHE_IP }}
with:
exec: bash ./helm/nginx/helm-installation.sh
# Update NGINX Prod Config
- name: Update NGINX Configuration
run: kubectl apply --namespace nginx-ingress-canon -f ./helm/nginx/prod-conf.yaml
# Retag latest image
- name: Retag Image to Production Release
if: ${{ inputs.update_release }}
run: |-
gcloud beta artifacts docker tags add \
--quiet \
${{ env.GCP_ARTIFACT_REGISTRY_LOCATION }}-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/${{ env.GCP_ARTIFACT_REGISTRY_NAME }}/${{ env.GCP_IMAGE_NAME }}:${{ env.GKE_APP_NAMESPACE }} \
${{ env.GCP_ARTIFACT_REGISTRY_LOCATION }}-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/${{ env.GCP_ARTIFACT_REGISTRY_NAME }}/${{ env.GCP_IMAGE_NAME }}:${{ inputs.release }}-${{ inputs.date }}
# Transform GitHub secrets to base64 encoded
- name: Set encoded secret values
run: |
echo "ENCODED_CANON_DB_HOST=$(echo -n "${{ secrets.CANON_DB_HOST }}" | base64 | tr -d '\n')" >> $GITHUB_ENV
echo "ENCODED_CANON_DB_PW=$(echo -n "${{ secrets.CANON_DB_PW }}" | base64 | tr -d '\n')" >> $GITHUB_ENV
echo "ENCODED_CANON_HOTJAR=$(echo -n "${{ secrets.CANON_HOTJAR }}" | base64 | tr -d '\n')" >> $GITHUB_ENV
# Install Helm chart
# for secrets, use --set secrets.DB_USER=$ENCODED_DB_USER
- name: Helm install
uses: WyriHaximus/github-action-helm3@v2
with:
exec: |
helm upgrade --install --create-namespace \
--namespace ${{ env.GKE_APP_NAMESPACE }} \
--set app.environment=${{ env.GKE_APP_NAMESPACE }} \
--set app.release=${{ env.GKE_APP_NAMESPACE }} \
--set image.repository=${{ env.GCP_ARTIFACT_REGISTRY_LOCATION }}-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/${{ env.GCP_ARTIFACT_REGISTRY_NAME }}/${{ env.GCP_IMAGE_NAME }} \
--set image.tag=${{ inputs.release }}-${{ inputs.date }} \
--set nameOverride=${{ env.GKE_APP_NAME }}-${{ inputs.release }} \
--set fullnameOverride=${{ env.GKE_APP_NAME }}-${{ inputs.release }} \
--set secrets.CANON_DB_HOST=$ENCODED_CANON_DB_HOST \
--set secrets.CANON_DB_PW=$ENCODED_CANON_DB_PW \
--set secrets.CANON_HOTJAR=$ENCODED_CANON_HOTJAR \
${{ env.GKE_APP_NAME }}-${{ inputs.release }} --values=./helm/${{ inputs.release }}.yaml ./helm
# Install Cache Helm chart
# - name: Add Helm cache repo
# uses: WyriHaximus/github-action-helm3@v2
# with:
# exec: |
# helm repo add mittwald https://helm.mittwald.de
# - name: Helm Cache install
# uses: WyriHaximus/github-action-helm3@v2
# with:
# exec: |
# helm upgrade --install --create-namespace \
# --namespace ${{ env.GKE_APP_NAMESPACE }} \
# --set app.environment=${{ env.GKE_APP_NAMESPACE }} \
# --set app.release=${{ env.GKE_APP_NAMESPACE }} \
# --set image.repository=quay.io/mittwald/kube-httpcache \
# --set image.tag=stable \
# --set nameOverride=${{ env.GKE_APP_NAME }}-${{ inputs.release }}-cache \
# --set fullnameOverride=${{ env.GKE_APP_NAME }}-${{ inputs.release }}-cache \
# --set secrets.TESSERACT_BACKEND=$ENCODED_TESSERACT_BACKEND \
# ${{ env.GKE_APP_NAME }}-${{ inputs.release }}-cache --values=./helm/${{ inputs.release }}-cache.yaml mittwald/kube-httpcache