在本教學課程中,您將瞭解如何使用 Kubernetes、Helm 和 Mcrouter,在 Google Kubernetes Engine (GKE) 上部署分散式 Memcached 伺服器叢集。Memcached 是熱門的開放原始碼多用途快取系統。 通常會做為常用資料的暫時儲存空間,以加快網路應用程式速度並減輕資料庫負載。
Memcached 的特性
Memcached 具有兩個主要的目標:
- 簡單:Memcached 的功能類似大型雜湊表,並提供簡單的 API,可依鍵儲存及擷取任意形狀的物件。
- 速度:Memcached 可以專門保存隨機存取記憶體 (RAM) 中的快取資料,使資料存取速度達到極快的程度。
Memcached 是一套分散式系統,可在一群伺服器之間水平調度其雜湊表的容量。每個 Memcached 伺服器都會與集區中的其他伺服器完全隔離。因此,伺服器之間的轉送和負載平衡必須在用戶端層級完成。Memcached 用戶端應用程式會套用一致性雜湊配置,適當選取目標伺服器。這項計畫可確保符合下列條件:
- 一律針對相同的鍵選取相同的伺服器。
- 伺服器之間的記憶體用量會得到平均分佈。
- 當伺服器集區縮小或擴充時,會搬遷最少數量的鍵。
下圖說明 Memcached 用戶端與 Memcached 伺服器分散式集區之間的高階互動。
目標
- 瞭解 Memcached 分散式架構的一些特性。
- 使用 Kubernetes 與 Helm 將 Memcached 服務部署至 GKE。
- 部署 Mcrouter (一種開放原始碼 Memcached Proxy) 以改善系統效能。
費用
在本文件中,您會使用下列 Google Cloud計費元件:
- Compute Engine
您可以使用 Pricing Calculator,根據預測用量估算費用。
事前準備
- 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自體驗產品的實際應用成效。新客戶還能獲得價值 $300 美元的免費抵免額,用於執行、測試及部署工作負載。
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the Compute Engine and GKE APIs, if any are not already enabled.
Roles required to enable APIs
To enable APIs, you need the
serviceusage.services.enablepermission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the Compute Engine and GKE APIs, if any are not already enabled.
Roles required to enable APIs
To enable APIs, you need the
serviceusage.services.enablepermission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.- 啟動 Cloud Shell 執行個體。
開啟 Cloud Shell
部署 Memcached 服務
如要將 Memcached 服務部署至 GKE,其中一個簡單的方法是使用 Helm 圖表。如要繼續部署,請在 Cloud Shell 中按照下列步驟操作:
建立三個節點的新 GKE 叢集:
gcloud container clusters create demo-cluster --num-nodes 3 --location us-central1-f下載
helm二進位封存檔:HELM_VERSION=3.7.1 cd ~ wget https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz將封存檔案解壓縮至本機系統:
mkdir helm-v${HELM_VERSION} tar zxfv helm-v${HELM_VERSION}-linux-amd64.tar.gz -C helm-v${HELM_VERSION}將
helm二進位檔的目錄新增至PATH環境變數:export PATH="$(echo ~)/helm-v${HELM_VERSION}/linux-amd64:$PATH"這個指令可讓
helm二進位檔在目前的 Cloud Shell 工作階段中,從任何目錄都能找到。如要讓這項設定在多個工作階段中持續生效,請將指令新增至 Cloud Shell 使用者的~/.bashrc檔案。使用高可用性架構安裝新的 Memcached Helm chart 版本。為確保 Mcrouter 能正確探索個別 Memcached Pod,以進行一致性雜湊,請明確將
clusterIP欄位的值設為None,建立無標題服務:helm repo add bitnami https://charts.bitnami.com/bitnami helm install mycache bitnami/memcached \ --set architecture="high-availability" \ --set autoscaling.enabled="true" \ --set service.clusterIP="None"Memcached Helm 圖表使用 StatefulSet 控制器。使用 StatefulSet 控制器的優點之一,是 Pod 的名稱會依序排列且可預測。在本例中,名稱為
mycache-memcached-{0..2}。進行排序可讓 Memcached 更容易參照伺服器。如要查看執行中的 Pod,請執行下列指令:
kubectl get pods控制台輸出內容如下所示: Google Cloud
NAME READY STATUS RESTARTS AGE mycache-memcached-0 1/1 Running 0 45s mycache-memcached-1 1/1 Running 0 35s mycache-memcached-2 1/1 Running 0 25s
探索 Memcached 服務端點
Memcached Helm 圖表使用無頭服務。無標題服務會公開所有 Pod 的 IP 位址,方便個別探索。
確認部署的服務是無介面服務:
kubectl get service mycache-memcached -o jsonpath="{.spec.clusterIP}"輸出內容
None確認服務沒有clusterIP,因此為無頭服務。服務會為下列格式的主機名稱建立 DNS 記錄:
[SERVICE_NAME].[NAMESPACE].svc.cluster.local在本教學課程中,服務名稱為
mycache-memcached。由於未明確定義命名空間,因此系統會使用預設命名空間,整個主機名稱為mycache-memcached.default.svc.cluster.local。這個主機名稱會解析為一組 IP 位址和網域,適用於服務公開的所有三個 Pod。如果日後有部分 Pod 新增至集區,或有舊 Pod 移除,kube-dns會自動更新 DNS 記錄。客戶必須負責探索 Memcached 服務端點,如後續步驟所述。
擷取端點的 IP 位址:
kubectl get endpoints mycache-memcached輸出結果會與下列內容相似:
NAME ENDPOINTS AGE mycache-memcached 10.36.0.32:11211,10.36.0.33:11211,10.36.1.25:11211 3m
請注意,每個 Memcached Pod 分別有不同的 IP 位址,分別是
10.36.0.32、10.36.0.33和10.36.1.25。這些 IP 位址可能與您自己的伺服器執行個體不同。每個 Pod 都會監聽通訊埠11211,這是 Memcached 的預設通訊埠。如要取代步驟 2,請使用 Python 等程式設計語言執行 DNS 檢查:
在您的叢集中啟動 Python 互動式主控台:
kubectl run -it --rm python --image=python:3.10-alpine --restart=Never python在 Python 主控台中,執行下列指令:
import socket print(socket.gethostbyname_ex('mycache-memcached.default.svc.cluster.local')) exit()輸出結果會與下列內容相似:
('mycache-memcached.default.svc.cluster.local', ['mycache-memcached.default.svc.cluster.local'], ['10.36.0.32', '10.36.0.33', '10.36.1.25'])
在通訊埠
11211上,與其中一個執行中的 Memcached 伺服器開啟telnet工作階段,測試部署作業:kubectl run -it --rm busybox --image=busybox:1.33 --restart=Never telnet mycache-memcached-0.mycache-memcached.default.svc.cluster.local 11211在
telnet提示字元中,使用 Memcached ASCII 協定執行下列指令:set mykey 0 0 5 hello get mykey quit
產生的輸出會在此以粗體顯示:
set mykey 0 0 5 hello STORED get mykey VALUE mykey 0 5 hello END quit
實作服務探索邏輯
您現在已經準備好實作如下圖所示的基本服務探索邏輯。
整體來說,服務探索邏輯包含下列步驟:
- 應用程式會向
kube-dns查詢mycache-memcached.default.svc.cluster.local的 DNS 記錄。 - 應用程式會擷取與該記錄相關聯的 IP 位址。
- 應用程式會實例化新的 Memcached 用戶端,並為該用戶端提供擷取的 IP 位址。
- Memcached 用戶端的整合式負載平衡器會連線至位於特定 IP 位址的 Memcached 伺服器。
現在您可以使用 Python 實作這個服務探索邏輯:
在您的叢集中部署新的具有 Python 功能的 Pod,並在該 Pod 中啟動殼層工作階段:
kubectl run -it --rm python --image=python:3.10-alpine --restart=Never sh安裝
pymemcache程式庫:pip install pymemcache執行
python指令,啟動 Python 互動式控制台。在 Python 主控台中,執行下列指令:
import socket from pymemcache.client.hash import HashClient _, _, ips = socket.gethostbyname_ex('mycache-memcached.default.svc.cluster.local') servers = [(ip, 11211) for ip in ips] client = HashClient(servers, use_pooling=True) client.set('mykey', 'hello') client.get('mykey')輸出內容如下所示:
b'hello'
b前置字元代表位元組常值,這是 Memcached 儲存資料的格式。結束 Python 主控台:
exit()如要結束 Pod 的殼層工作階段,請按下
Control+D。
啟用連線集區
隨著您的快取需求的增加,以及集區規模擴充至數十、數百或數千個 Memcached 伺服器,您可能會遇到一些限制。特別的是,大量來自 Memcached 用戶端的公開連線可能會為伺服器增加龐大負載,如下圖所示。
為了減少公開連線數,您必須導入 Proxy 以啟用連線集區,如下圖所示。
Mcrouter (發音為「mick router」) 是一款功能強大的開放原始碼 Memcached Proxy,可以用來啟用連線集區。您可以完美整合 Mcrouter,因為這個 Proxy 使用標準的 Memcached ASCII 通訊協定。對 Memcached 用戶端而言,Mcrouter 的作用與正常 Memcached 伺服器類似。對 Memcached 伺服器而言,Mcrouter 的作用與正常 Memcached 用戶端類似。
如要部署 Mcrouter,請在 Cloud Shell 中執行下列指令。
刪除先前安裝的
mycacheHelm 資訊套件版本:helm delete mycache安裝新的 Mcrouter Helm 圖表版本,部署新的 Memcached Pod 和 Mcrouter Pod:
helm repo add stable https://charts.helm.sh/stable helm install mycache stable/mcrouter --set memcached.replicaCount=3連線至其中一個 Proxy Pod 以測試此設定。在通訊埠
5000上使用telnet指令,這是 Mcrouter 的預設通訊埠。MCROUTER_POD_IP=$(kubectl get pods -l app=mycache-mcrouter -o jsonpath="{.items[0].status.podIP}") kubectl run -it --rm busybox --image=busybox:1.33 --restart=Never telnet $MCROUTER_POD_IP 5000在
telnet提示中執行下列指令:set anotherkey 0 0 15 Mcrouter is fun get anotherkey quit
這些指令會設定及回應您的鍵值。
您現在已經部署了啟用連線集區的 Proxy。
減少延遲時間
為提高韌性,常見做法是使用具有多個節點的叢集。本教學課程使用內含三個節點的叢集。但是,使用多個節點也會因節點之間較繁重的網路流量而帶來增加延遲時間的風險。
並置 Proxy Pod
您只能將用戶端應用程式 Pod 連線至位於同一節點上的 Memcached Proxy Pod 來降低這個風險。下圖說明這個設定。
執行這個設定的方式如下:
- 確保每個節點都包含一個執行中的 Proxy Pod。常見的做法是使用 DaemonSet 控制器部署 Proxy Pod。節點新增至叢集時,系統會自動在節點中新增 Proxy Pod。從叢集移除節點時,這些 Pod 會被當成垃圾回收處理。在本教學課程中,您先前部署的 Mcrouter Helm 圖表預設會使用 DaemonSet 控制器。因此,這個步驟已經完成。
- 在 Proxy 容器的 Kubernetes 參數中設定
hostPort值,讓節點監聽該通訊埠,並將流量重新導向至 Proxy。在本教學課程中,Mcrouter Helm 資訊圖表會預設使用這個參數做為通訊埠5000。因此這個步驟已經完成。 使用
spec.env項目並選取spec.nodeNamefieldRef值,將節點名稱公開為應用程式 Pod 內的環境變數。如要進一步瞭解這個方法,請參閱 Kubernetes 說明文件。部署範例應用程式 Pod。下列指令會套用 Kubernetes Deployment。Deployment 是 Kubernetes API 物件,可讓您執行多個 Pod 副本,並分散在叢集中的節點:
cat <<EOF | kubectl create -f - apiVersion: apps/v1 kind: Deployment metadata: name: sample-application spec: selector: matchLabels: app: sample-application replicas: 9 template: metadata: labels: app: sample-application spec: containers: - name: busybox image: busybox:1.33 command: [ "sh", "-c"] args: - while true; do sleep 10; done; env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName EOF
進入其中一個應用程式範例 Pod 中查看,確認節點名稱是否已公開:
POD=$(kubectl get pods -l app=sample-application -o jsonpath="{.items[0].metadata.name}") kubectl exec -it $POD -- sh -c 'echo $NODE_NAME'這個指令輸出的節點名稱格式如下:
gke-demo-cluster-default-pool-XXXXXXXX-XXXX
連線 Pod
應用程式範例 Pod 現在已經準備好連線至 Mcrouter Pod,該 Mcrouter Pod 在通訊埠 5000 的各自雙向節點上執行,這是 Mcrouter 的預設通訊埠。
開啟
telnet工作階段,為其中一個 Pod 建立連線:POD=$(kubectl get pods -l app=sample-application -o jsonpath="{.items[0].metadata.name}") kubectl exec -it $POD -- sh -c 'telnet $NODE_NAME 5000'在
telnet提示字元中執行下列指令:get anotherkey quit產生的輸出:
Mcrouter is fun
最後,以下 Python 程式碼是範例程式,可透過從環境擷取 NODE_NAME 變數,並使用 pymemcache 程式庫來執行這項連線:
import os
from pymemcache.client.base import Client
NODE_NAME = os.environ['NODE_NAME']
client = Client((NODE_NAME, 5000))
client.set('some_key', 'some_value')
result = client.get('some_key')
清除所用資源
為避免因為本教學課程所用資源,導致系統向 Google Cloud 帳戶收取費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。
執行以下指令來刪除 GKE 叢集:
gcloud container clusters delete demo-cluster --location us-central1-f或者刪除 Helm 二進位檔:
cd ~ rm -rf helm-v3.7.1 rm helm-v3.7.1-linux-amd64.tar.gz
後續步驟
- 除了簡單的連線集區外,Mcrouter 還提供許多其他功能,例如容錯移轉副本、可靠的刪除串流、冷快取暖機、多叢集廣播。
- 如要進一步瞭解各個 Kubernetes 設定,請查看 Memcached 圖表和 Mcrouter 圖表的來源檔案。
- 請參閱這篇文章,瞭解在 App Engine 上使用 Memcached 的有效技巧。其中一些技巧適用於其他平台,例如 GKE。