手把手將 Django 服務送上 GCP
許多人在網路上看了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 產品和服務互動的工具,本篇文章會使用到裡面的 gcloud 與 gsutil,可以直接透過指令來管理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。
基本配置如下,密碼可以自行設定或使用隨機生成,”要記下這組密碼”。
下面設定選項只需要更動「連線」,展開連線頁面,勾選「私人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
),讀者可以參考本篇專案作為基底,再依據自身需求更改。