Frontend + BFF on GKE

This document still works in progress.

Before you begin

Required

  • direnv
  • docker & docker-compose

Before development

(optional) Create the ENV file for Docker

on macOS

BIND_IP_ADDR=192.168.65.1

on Linux

BIND_IP_ADDR=192.168.65.1
UID=1000
GID=100

Generate the key pair for JWT

openssl genrsa -out credentials/jwt.key.pem 4096
openssl rsa -in credentials/jwt.key.pem -pubout -out credentials/jwt.pubkey.pem

Before deploy

Setup your GCP Project

Enable Cloud SQL Admin API. https://console.cloud.google.com/apis/api/sqladmin.googleapis.com/overview

(optional) Generate and Auth your service account

https://cloud.google.com/sdk/gcloud/reference/auth/activate-service-account

gcloud auth activate-service-account

Setup direnv

Edit the .envrc file with direnv edit . command.

Like bellow:

  • PROJECT_UUID
    • Your unique string.
    • e.g. 6e8cfffe-f521-4516-b9dc-719b022b9646
  • PROJECT_BASENAME
    • Your project identifier and subdomain.
    • e.g. 6e8cfffe, my-app
  • PROJECT_BASEDOMAIN
    • Your domainname.
    • e.g. example.com.
  • CLOUDSDK_CORE_PROJECT
    • Your GCP Project ID.
    • e.g. mazgi-sandbox-gcp
  • GOOGLE_APPLICATION_CREDENTIALS_FILENAME
    • Your GCP key file name.
    • e.g. mazgi-sandbox-gcp-1122334455.json
# Project
export PROJECT_UUID='YOUR-UUID'
export PROJECT_BASENAME='YOUR-BASENAME'
export PROJECT_BASEDOMAIN='YOUR-DOMAINNAME'
export PROJECT_LOCATION="us-central1"
# Frontend
export FRONTEND_FQDN="frontend.${PROJECT_BASENAME}.${PROJECT_BASEDOMAIN}"
export FRONTEND_STATIC_ADDRESS_NAME="${PROJECT_BASENAME}-frontend-main"
# BFF
export BFF_FQDN="bff.${PROJECT_BASENAME}.${PROJECT_BASEDOMAIN}"
export BFF_STATIC_ADDRESS_NAME="${PROJECT_BASENAME}-bff-main"
export BFF_EMAIL_SENDER_EMAIL="YOUR-SENDER-EMAIL-ADDRESS"
export BFF_EMAIL_SENDER_PASSWORD="YOUR-SENDER-EMAIL-PASSWORD"
export BFF_ADMIN_EMAIL="YOUR-ADMIN-EMAIL"
export BFF_ADMIN_PASSWORD_PLAINTEXT="YOUR-ADMIN-PASSWORD"
export BFF_OAUTH_GITHUB_CLIENT_ID="YOUR-GITHUB-CLIENT-ID"
export BFF_OAUTH_GITHUB_CLIENT_SECRET="YOUR-GITHUB-CLIENT-SECRET"

# GCP
export CLOUDSDK_CORE_PROJECT='YOUR-GCP-PROJECT'
export GOOGLE_APPLICATION_CREDENTIALS_FILENAME='YOUR-GCP-KEY.json'
export GOOGLE_APPLICATION_CREDENTIALS="${PWD}/credentials/${GOOGLE_APPLICATION_CREDENTIALS_FILENAME}"

# Terraform
export TF_VAR_gcp_project_id="${CLOUDSDK_CORE_PROJECT}"
export TF_VAR_gcp_location="${PROJECT_LOCATION}"
export TF_VAR_basedomain="${PROJECT_BASEDOMAIN}"
export TF_VAR_basename="${PROJECT_BASENAME}"
export TF_VAR_frontend_fqdn="${FRONTEND_FQDN}"
export TF_VAR_frontend_static_address_name="${FRONTEND_STATIC_ADDRESS_NAME}"
export TF_VAR_bff_fqdn="${BFF_FQDN}"
export TF_VAR_bff_static_address_name="${BFF_STATIC_ADDRESS_NAME}"
export TF_VAR_db_user_bff_password="pass"
export TF_VAR_current_external_ipaddr="$(curl -Ls ifconfig.io)/32"

Configure GCR

gcloud auth configure-docker

Create a Cloud Storage bucket for save tfstate.

see https://cloud.google.com/storage/docs/gsutil

gsutil mb gs://${PROJECT_UUID}/
gsutil acl set private gs://${PROJECT_UUID}/
gsutil versioning set on gs://${PROJECT_UUID}/

Setup GCP environment

Setup your subdomain via Terraform

See also provisioning/domain in this repository.

Initialize terraform.

docker-compose run provisioning bash -c 'source .envrc && cd provisioning/domain && terraform init -backend-config="bucket=${PROJECT_UUID}"'

Plan & apply terraform.

docker-compose run provisioning bash -c 'source .envrc && cd provisioning/domain && terraform plan'
docker-compose run provisioning bash -c 'source .envrc && cd provisioning/domain && terraform apply'

Create GKE cluster via Terraform

See also provisioning/gke in this repository.

Initialize terraform.

docker-compose run provisioning bash -c 'source .envrc && cd provisioning/gke && terraform init -backend-config="bucket=${PROJECT_UUID}"'

Plan & apply terraform.

docker-compose run provisioning bash -c 'source .envrc && cd provisioning/gke && terraform plan'
docker-compose run provisioning bash -c 'source .envrc && cd provisioning/gke && terraform apply'

Deploy your app

Setup helm

gcloud container clusters get-credentials --zone us-central1 $GKE_CLUSTER
kubectl --namespace kube-system create serviceaccount tiller
kubectl create clusterrolebinding tiller-admin --clusterrole admin --serviceaccount=kube-system:tiller
kubectl create clusterrolebinding tiller-cluster-admin --clusterrole cluster-admin --serviceaccount=kube-system:tiller
helm init --upgrade --service-account=tiller
kubectl get pods,deployments,services --namespace kube-system -l name=tiller

Deploy the resource

helm install --name NAME provisioning/console