Skip to content

Latest commit

 

History

History
164 lines (122 loc) · 7.09 KB

README.md

File metadata and controls

164 lines (122 loc) · 7.09 KB

Ed-Fi Deployed via Kubernetes

This repository looks at deploying Ed-Fi via Google Kubernetes Engine. Historically I have maintained this repo that contains all code necessary to deploy Ed-Fi via Google Cloud Run and Cloud SQL. Utilizing Cloud Run is the recommend route for most people looking to implement Ed-Fi. Cloud Run requires less management overhead and is a great fully managed serverless platform. If you're simply looking to deploy Ed-Fi in Google Cloud, go there.

This repo was started for a few reasons:

  • I wanted to place pgbouncer, a connection pooler, between the API and ODS to reduce the number of connections to the Cloud SQL instance allowing for smaller (AKA less expensive) instances.
  • I plan to deploy Dagster and Apache Superset as well, and having all of that in one kubernetes cluster was interesting to me.
  • I wanted to learn kubernetes and needed a project.

In this design the Ed-Fi ODS databases are deployed to a PostgreSQL Cloud SQL instance. Reading this documentation from Google, I felt that Cloud SQL was a better option than GKE due to the management overhead that running PostgreSQL in kubernetes would add.

Ed-Fi

Ed-Fi Component Version
Ed-Fi API & ODS v5.3
Ed-Fi Admin App v2.3.2

This repo is designed to be cloned to Google Cloud Shell and all commands can be run from there.

Cloud SQL

gcloud services enable artifactregistry.googleapis.com;
gcloud services enable compute.googleapis.com;
gcloud services enable container.googleapis.com;
gcloud services enable sqladmin.googleapis.com;
gcloud services enable cloudbuild.googleapis.com;
gcloud services enable servicenetworking.googleapis.com;

# download database backup files
bash cloud_sql/download_db_backups.sh;

gcloud compute addresses create google-managed-services-default \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=16 \
    --description="peering range" \
    --network=default;

gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=google-managed-services-default \
    --network=default \
    --project=$GOOGLE_CLOUD_PROJECT;

# create cloud sql instance
gcloud beta sql instances create \
  --zone us-central1-c \
  --database-version POSTGRES_11 \
  --memory 7680MiB \
  --cpu 2 \
  --storage-auto-increase \
  --network=projects/$GOOGLE_CLOUD_PROJECT/global/networks/default \
  --backup-start-time 08:00 edfi-ods-db;

gcloud sql databases create 'EdFi_Admin' --instance=edfi-ods-db;
gcloud sql databases create 'EdFi_Security' --instance=edfi-ods-db;
gcloud sql databases create 'EdFi_Ods_2023' --instance=edfi-ods-db;
gcloud sql databases create 'EdFi_Ods_2022' --instance=edfi-ods-db;
gcloud sql databases create 'EdFi_Ods_2021' --instance=edfi-ods-db;

gcloud sql users set-password postgres --password <POSTGRES_PASSWORD> --instance=edfi-ods-db;

# connect to cloud sql instance via cloud sql proxy
# keep proxy running while executing the next command
cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:5432;

bash +x cloud_sql/seed_databases.sh <POSTGRES_PASSWORD>;

Google Kubernetes Engine

gcloud config set compute/region us-central1;

# create artifact registry repository
gcloud artifacts repositories create my-repository \
    --project=$GOOGLE_CLOUD_PROJECT \
    --repository-format=docker \
    --location=us-central1 \
    --description="Docker repository";

gcloud builds submit \
    --tag us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/my-repository/edfi-admin-app kubernetes/admin_app/.;

# create service account with access to cloud sql
gcloud iam service-accounts create cloud-sql-proxy;
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
    --member="serviceAccount:cloud-sql-proxy@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
    --role=roles/cloudsql.client;

# create static external ip address
gcloud compute addresses create edfi --global;

# DEV TODO configure the dns records for your domain to point to external ip address
# @ A record to external ip
# www A record to external ip
# admin A record to external ip

# create gke autopilot cluster
gcloud container clusters create-auto my-cluster;

# get auth credentials so kubectl can interact with the cluster
gcloud container clusters get-credentials my-cluster;

# create secret storing cloud sql credentials
kubectl create secret generic cloud-sql-creds \
  --from-literal=username=postgres \
  --from-literal=password=<POSTGRES_PASSWORD>;

# create secret storing admin app encryption key
kubectl create secret generic edfi-admin-app-creds \
  --from-literal=key=$(/usr/bin/openssl rand -base64 32);

cd kubernetes;

# create kubernetes service account
kubectl apply -f service-account.yaml;

# bind kubernetes service account to google service account
gcloud iam service-accounts add-iam-policy-binding \
  --role="roles/iam.workloadIdentityUser" \
  --member="serviceAccount:$GOOGLE_CLOUD_PROJECT.svc.id.goog[default/cloud-sql-proxy]" \
  cloud-sql-proxy@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com;

kubectl annotate serviceaccount \
  cloud-sql-proxy \
  iam.gke.io/gcp-service-account=cloud-sql-proxy@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com;

# deploy pgbouncer with cloud sql proxy sidecar
# DEV TODO replace <INSTANCE_CONNECTION_NAME> in deployment-pgbouncer.yaml
kubectl apply -f deployment-pgbouncer.yaml;
kubectl apply -f service-pgbouncer.yaml;

# deploy edfi api and create managed cert for ssl
# DEV TODO replace domain names in managed-cert.yaml;
kubectl apply -f managed-cert.yaml;

kubectl apply -f deployment-edfi-api.yaml;
kubectl apply -f service-edfi-api.yaml;

# DEV TODO replace <GOOGLE_PROJECT_ID> in deployment-edfi-admin-app.yaml
# DEV TODO replace <DOMAIN_NAME> in deployment-edfi-admin-app.yaml
kubectl apply -f deployment-edfi-admin-app.yaml;
kubectl apply -f service-admin-app.yaml;

# DEV TODO replace <DOMAIN_NAME> in managed-cert-ingress.yaml
kubectl apply -f managed-cert-ingress.yaml;

# check status of certificate
# wait until certificate status says "Active"
kubectl describe managedcertificate managed-cert;

Resources