手把手將 Django 服務送上 GCP

PeerOne CTO
PeerOne Technology 皮偶玩互動科技
15 min readAug 23, 2020

許多人在網路上看了Django、Docker、Kubernetes 等等教學,卻可能還不知道實際使用時,該如何將這些框架、技術整合起來應用,本篇文章使用最陽春的 Django 專案,結合各項 Google Cloud Platform 提供的服務,包含 GKE、CloudSQL、GCR等等,配合 Google Manage Certificate 提供的SSL憑證,將一個 Web Server 架設在雲端。

程式語言、框架以及技術

  • Python 3.8
  • Django(以 python 為基底的 web 框架)
    - Gunicorn(WSGI server)
  • PostgresSQL
  • Docker
  • Kubernetes (會用到的 k8s resource 如下:
    - Deployment
    - Service
    - Ingress
    - Secret
    - Managed Certificate (Google SSL憑證代管)
  • Google Cloud Platform
    - Kubernetes Engine
    - CloudSQL
    - Container Registry
    - Managed Certificate (用於SSL憑證)

注意事項

  • 本文不會針對任何 Docker、Kubernetes 等等技術的原理進行講解,網路上有許多實用的教學可以讓你了解這些技術背後的原理,建議先了解前一節提及的技術,再閱讀本文章。
  • 本文不會針對專案內的檔案進行詳細解說,然而本專案使用的django 與 k8s 的 yaml 檔案,皆盡量精簡而不做其他細部配置,讀者稍微 trace code 應該就可以輕易了解每個檔案的用途。

必備條件

購買網域名稱

本篇文章會使用 https 協定,因此需要一組網域名稱,可以自行購買或是搜尋網路上有些提供免費網域的服務商 。

安裝 Docker

本文預期讀者對docker有一定程度的了解,還沒安裝docker的人可以在網路上找到許多的安裝教學,這邊提供幾篇簡易教學給尚未安裝的人參考:
- Install Docker Engine (官方文件)
- Docker 學習筆記(二) — 安裝 Docker

安裝 Google Cloud SDK

Google Cloud SDK 是與 Google Cloud 產品和服務互動的工具,本篇文章會使用到裡面的 gcloudgsutil,可以直接透過指令來管理GCP上的資源,安裝的方式可以查看官方文檔

安裝 k8s 相關套件

本文需要安裝 kubectl 與 kubectx:
- kubectl :k8s 官方釋出的 command-line tool。
- kubectx:方便切換 cluster 與 namespace 的小工具。

linux 與 windows 系統可以參照官方文件
- Install and Set Up kubectl

macOS 可以直接透過下列指令安裝k8s工具

$brew install kubectl
$brew install kubectx

Google Cloud Platform 設定

進入 Google Cloud Platform Console,第一次使用GCP(Google Cloud Platform)的帳號,可以透過綁定一張信用卡來免費獲得 $300美金(效期 90天)的額度,建議大家先將環境配置好之後,再領取試用額度。

創建專案

打開 GCP console,點擊「選取專案」後,選取「新增專案」。

這裡專案名稱設定為 k8s-demo,系統會自動生成一組隨機的專案 ID,也可以自行設定專案ID,這組專案 ID 要記下來,等等會用到。

釘選功能(optional)

以下幾個功能是這次專案會用到的,可以先將這幾個功能釘選起來,等下就不會找太久。

創建叢集

建立完專案後,第一步是建立一個 cluster(叢集),左上角選單點選 Kubernetes Engine後,即可來到下列面,點選「建立叢集」。

進入設定,叢集基本資訊的配置如下圖所示(asia-east1–1為台灣)

點選左列選單的 default-pool 選單,將節點數量的大小設定為1。

選擇 default-pool 子選單的「節點數」,這邊因為只是範例使用,選擇便宜的機器使用即可。
- 機器設定選擇「N1」系列,機器類型選擇 n1-standard-1

其餘設定維持預設即可,接下來就按下底部的藍色「create」按鈕來完成創建 cluster

創建 Cloud SQL instance

打開左上角選單,選擇「SQL」後,點擊「建立執行個體」,

本範例搭配 Django 使用的資料庫是 PostgresSQL。

基本配置如下,密碼可以自行設定或使用隨機生成,”要記下這組密碼”

Cloud SQL instance 基本配置

下面設定選項只需要更動「連線」,展開連線頁面,勾選「私人IP」,並取消勾選「公開IP」。

第一次設定會跳出下列彈窗,勾選啟用「API」即可。

建立完成後,在 SQL instance 的「總覽」左下方可以看到「私人IP位址」,必須記下來,等下會用到。

預約靜態 IP 位置

必須為 server 之ingress 配置一個供外部連線的靜態IP。
展開左上角選單,點選 VPC 網路的「外部IP位置」,點擊預約靜態位置

配置如下圖,類型記得選通用,名稱設定為 web-server-ip-address

建立完成之後,可以在「外部 IP 位置」的列表看到剛建立的 IP 位址,這組IP位址記下來。

啟用 Container Registry API

為了之後要將打包好的 docker image 推送到 GCR(Google Container Registry,用來儲存、管理和保護 Docker 容器映像檔),必須先進入 Google Container Registry API,點選啟用並選擇目前的專案。

建立 service-account(服務帳戶)

需要建立一個服務帳戶,作為 server 與 storage 之間的憑證。

左上角選單選擇 「IAM 與管理」的子選單「服務帳戶」,點選「建立服務帳戶」,配置如下圖,按下建立之後即可。

建立服務帳戶的金鑰

左上角選單選擇 「IAM 與管理」的子選單「服務帳戶」,在列表中可以看到剛剛建立的 bucket-admin,先將左邊的電子郵件記下來(k8s-admin開頭的),接著點選右邊的 … 符號,點選「建立金鑰」,選擇「JSON」格式並點選建立,瀏覽器會自動下載一個JSON的檔案。

務必將此 JSON 檔案保管好不要外流!

建立 Cloud Storage bucket

需要儲存空間來存放靜態檔案,包含 django admin 的 css 等靜態檔案。

左上角選單選擇 「Storage」 的子選單「瀏覽器」選擇建立值區,其中值區的名字,也就是 bucket name 需要設定全域不重複的名字,自行設定後需要將這個 bucket-name 記下來。

Cloud Storage bucket 之 service-account 權限設定

「Storage」的子選單瀏覽器的列表中,點選剛剛建立的bucket,並點選「權限」頁籤後選擇建立,新增成員的地方填入服務帳戶的電子郵件,角色選擇「Storage 繼承 Bucket 擁有者」,點選儲存

進行到這裏,Google CLoud Platform 這邊的設定大致就結束了。

必須紀錄的值與檔案

如果有正確完成剛剛的步驟,應該會記下以下幾個值:

  • <project-id>:專案 ID
  • <pg-password>:postgres 使用者密碼。
  • <postgres-private-ip>:postgresSQL 私人IP位置。
  • <bucket-name>:Cloud Storage bucket 的值區名稱。
  • <web-server-ip-address> ingress 所對應的外部 IP
  • service-account 金鑰:JSON格式檔案(切記勿外流!)

這些值非常重要,下一步驟會用到,確保都有記下來再往下一個步驟前進。

將 Web Server 部署至 Google Kubernetes Engine

使用 Cloud SDK 連線至帳號、專案以及 Cluster

在 terminal 輸入下列指令,連線至此專案的 google 帳號。

gcloud auth login

註:輸入完之後可以使用,gcloud auth list 確認是否有切換到該帳號,active 的帳號左邊會有一個 * 的符號。

將環境設置為當前的專案連結至前面創建的 cluster

gcloud config set project <project-id>  # 設定專案
gcloud container clusters get-credentials demo --zone asia-east1-a --project <project-id> # 連結cluster

<project-id>需要替換成前面記下來的「專案 ID」

將 Cloud Storage bucket 設定為公開讀取

可以先使用 gsutil ls 列出現有的 bucket list,應該會看到剛剛創建的bucket,如果沒有看到的話代表剛剛沒有創建成功,使用下列指令將該 bucket 設定為公開讀取。

gsutil defacl set public-read gs://<bucket-name>

<bucket-name>需要替換成前面記下來的 cloud storage bucket 的值區名稱。

Clone demo 專案

先將本次用的 Django 專案 clone 下來,cd 切換至 repo 資料夾內。

git clone https://github.com/riley-peerone/k8s-demo.git
cd k8s-demo

蒐集 Django 靜態檔案並上傳至 Cloud Storage bucket

在 k8s-demo 資料夾會看到一個 docker-compose.yaml,使用 docker-compose up -d啟動整個專案,並使用 docker exec 進入demo_server 這個image 對應的 container。

# 確認目前的資料夾為 "k8s-demo"
docker-compose up -d
docker exec -it <demo-server-container-id> bash

進入 container 的 shell 以後,將靜態蒐集至 static 資料夾,執行完畢後,輸入 exit 離開container shell。

python manage.py collectstatic  # 蒐集靜態檔案exit

此時 cd web 後,可以發現 web 裡面多了一個 static 的資料夾,裡面放了 Django 的靜態檔案,利用 rsync 指令將靜態檔案上傳至 Cloud Storage bucket

cd web
gsutil rsync -R static/ gs://<bucket-name>/static

Build & Push Image

輸入下列指令配置與驗證 gcr 的權限。

gcloud auth configure-docker

透過下列指令 build image 並 push 至 Google Container Registry。

docker build -t asia.gcr.io/<project-id>/server .
docker push asia.gcr.io/<project-id>/server

<project-id>需要替換成前面記下來的「專案 ID」

Secret 配置

開啟 k8s-demo/k8s/secrets.yaml,裡面存放的資源皆是以 Secret 形式存放,顧名思義是提供開發者存放敏感資訊的檔案,其中敏感內容必須以 base64編碼存放。

  • 先將前面的 postgresSQL的密碼透過 https://www.base64encode.org/ 網站編碼成 base64 的形式,並替換 <pg-password-b64encode>
  • 將前面 service-account 的金鑰(JSON格式),將內容一樣透過 https://www.base64encode.org/ 網站編碼成 base64 的形式,並替換 <credentials-b64encode>

接下來 apply 該 yaml 檔案。

kubectl apply -f k8s/secrets.yaml

應該會看到下列訊息:

環境變數配置 與 部署

打開 k8s-demo/k8s/deployment.yaml,總共有四個地方需要替換成剛剛記下來的值,分別是:

  • <project-id> # 專案ID,位於 docker image 的 value 。
  • <postgres-private-ip> # cloudSQL 的私人ip位置,位於POSTGRES_SERVICE 的 value。
  • <bucket-name> # storage bucket name,分別在 GS_BUCKET_NAME 與 STATIC URL 兩處。

替換完成後, apply 該 yaml 檔案,稍待片刻可以看到一個running的pod。

kubectl apply -f k8s/deployment.yaml
kubectl get pod

透過 kubectl exec -it <pod-name> bash連線進該 pod 的 container shell,。

輸入 python manage.py migrate,如果 CloudSQL DB 連線沒問題的話,migrate 應該會成功。

最後輸入 exit,離開 container 的 shell。

打開 k8s/certificate.yaml,將<your-domain-name>替換成購買的域名,範例如下:

存擋後,接下來 apply 剩下的 yaml files。

kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml
kubectl apply -f k8s/certificate.yaml

以上步驟完成後,請去網域代管商將域名綁定 <web-server-ip-address>!!

約靜待 15 至 30 分鐘後,等 ingress 與 certificate 生效之後,進入 https://<your-domain-name>/admin/就可以看到熟悉的 Django後台畫面了。

結語

本篇文章主要是讓新手感受一下將一個簡易的 django 服務推送上雲端的流程與步驟,並體驗所有服務幾乎都在 GCP 上完成的威力,因此本 django 服務非常的陽春,基本上只是 django-admin startproject ,並在 settings.py裡面加上幾個環境變數、google credentials 以及Postgres資料庫設定而已。

跟著本篇文章實作完之後,如果已經不使用的話,記得去 Kubernetes Engine把 cluster 關閉、把靜態 IP 釋放、停止 CloudSQL Instance 等等,避免專案繼續扣錢。

要注意的是,本篇將許多使用了許多默認值作為配置,在 Production 的環境仍然需要更多細部的設定與調整(例如:DEBUG = False),讀者可以參考本篇專案作為基底,再依據自身需求更改。

--

--