在本教學課程中,您會瞭解如何使用 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。
事前準備
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine and GKE APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine and GKE APIs.
- 啟動 Cloud Shell 執行個體。
開啟 Cloud Shell
部署 Memcached 服務
有一種簡單的方法可以將 Memcached 服務部署至 GKE,那就是使用 Helm chart。如要繼續部署,請在 Cloud Shell 中按照下列步驟操作:
建立三個節點的新 GKE 叢集:
gcloud container clusters create demo-cluster --num-nodes 3 --zone 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"
這個指令讓您在目前的 Cloud Shell 工作階段期間,從任何目錄探索到
helm
二進位檔。如要在多個工作階段中持續維持這個設定,請將指令加到您的 Cloud Shell 使用者的~/.bashrc
檔案。安裝具有高可用性架構的新 Memcached Helm chart 版本:
helm repo add bitnami https://charts.bitnami.com/bitnami helm install mycache bitnami/memcached --set architecture="high-availability" --set autoscaling.enabled="true"
Memcached Helm chart 使用 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 chart 使用無介面服務。無介面服務會公開其所有 Pod 的 IP 位址,以便能夠單獨探索到這些 Pod。
確認部署的服務是無介面服務:
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
。這個主機名稱會解析為服務公開的全部三個 Pod 的一組 IP 位址及網域。如果未來某些 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
的 DNS 記錄。mycache-memcached.default.svc.cluster.local
- 應用程式會擷取與該記錄相關聯的 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()
按下
Control
+D
鍵結束 Pod 的殼層工作階段。
啟用連線集區
隨著您的快取需求的增加,以及集區規模擴充至數十、數百或數千個 Memcached 伺服器,您可能會遇到一些限制。特別的是,大量來自 Memcached 用戶端的公開連線可能會為伺服器增加龐大負載,如下圖所示。
為了減少公開連線數,您必須導入 Proxy 以啟用連線集區,如下圖所示。
Mcrouter (發音為「mick router」) 是一款功能強大的開放原始碼 Memcached Proxy,可以用來啟用連線集區。您可以完美整合 Mcrouter,因為這個 Proxy 使用標準的 Memcached ASCII 通訊協定。對 Memcached 用戶端而言,Mcrouter 的作用與正常 Memcached 伺服器類似。對 Memcached 伺服器而言,Mcrouter 的作用與正常 Memcached 用戶端類似。
如要部署 Mcrouter,請在 Cloud Shell 中執行下列指令。
刪除先前安裝的
mycache
Helm chart 版本:helm delete mycache
安裝新的 Mcrouter Helm chart 版本以部署新的 Memcached Pod 與 Mcrouter Pod:
helm repo add stable https://charts.helm.sh/stable helm install mycache stable/mcrouter --set memcached.replicaCount=3
Proxy Pod 現在已經準備好接受來自用戶端應用程式的要求。
連線至其中一個 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 chart 根據預設使用 DaemonSet 控制器。因此,這個步驟已經完成。
- 在 Proxy 容器的 Kubernetes 參數中設定
hostPort
值,使節點接聽該通訊埠,並將流量重新導向至 Proxy。在本教學課程中,Mcrouter Helm chart 根據預設針對通訊埠5000
使用這個參數,因此這個步驟已經完成。 使用
spec.env
項目並選取spec.nodeName
fieldRef
值,將節點名稱公開為應用程式 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 --zone us-central1-f
或者刪除 Helm 二進位檔:
cd ~ rm -rf helm-v3.7.1 rm helm-v3.7.1-linux-amd64.tar.gz
後續步驟
- 除了簡單的連線集區以外,您也可以探索 Mcrouter 提供的其他許多功能,例如容錯移轉備用資源、可靠的刪除串流、冷快取暖機、多叢集廣播。
- 探索 Memcached chart 與 Mcrouter chart 的原始碼檔案,進一步瞭解各個 Kubernetes 設定。
- 進一步瞭解在 App Engine 上使用 Memcached 的有效技巧。其中一些技巧適用於其他平台,例如 GKE。