Cloud Service Mesh 是管理及監控分散式應用程式的強大工具。如要充分運用 Cloud Service Mesh,瞭解其基礎抽象化機制 (包括容器和 Kubernetes) 會很有幫助。本教學課程說明如何準備應用程式,從原始碼到在 GKE 上執行的容器,再到安裝 Cloud Service Mesh 之前,都適用於 Cloud Service Mesh。
如果您已熟悉 Kubernetes 和服務網格概念,可以略過本教學課程,直接參閱 Cloud Service Mesh 安裝指南。
下載程式碼範例
下載
helloserver原始碼:git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples變更為範例程式碼目錄:
cd anthos-service-mesh-samples/docs/helloserver
探索多服務應用程式
應用程式範例是以 Python 編寫,包含兩個使用 REST 通訊的元件:
server:簡單的伺服器,其中包含一個GET端點/,可將「hello world」列印到控制台。loadgen:將流量傳送至server的指令碼,每秒要求數 (RPS) 可設定。
從來源執行應用程式
如要熟悉範例應用程式,請在 Cloud Shell 中執行。
從
sample-apps/helloserver目錄執行server:python3 server/server.py啟動時,
server會顯示下列內容:INFO:root:Starting server...
開啟另一個終端機視窗,以便將要求傳送至
server。 按一下 開啟另一個工作階段。向
server傳送要求:curl http://localhost:8080server會回應:Hello World!
從下載範例程式碼的目錄,變更為包含
loadgen的目錄:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/loadgen
建立下列的環境變數:
export SERVER_ADDR=http://localhost:8080 export REQUESTS_PER_SECOND=5開始時間
virtualenv:virtualenv --python python3 env啟用虛擬環境:
source env/bin/activate安裝
loadgen的需求項目:pip3 install -r requirements.txt執行
loadgen:python3 loadgen.py啟動時,
loadgen會輸出類似以下的訊息:Starting loadgen: 2019-05-20 10:44:12.448415 5 request(s) complete to http://localhost:8080
在另一個終端機視窗中,
server會將訊息寫入主控台,類似於下列訊息:127.0.0.1 - - [21/Jun/2019 14:22:01] "GET / HTTP/1.1" 200 - INFO:root:GET request, Path: / Headers: Host: localhost:8080 User-Agent: python-requests/2.22.0 Accept-Encoding: gzip, deflate Accept: */*
從網路的角度來看,整個應用程式現在都在同一部主機上執行。因此,您可以使用
localhost將要求傳送至server。如要停止
loadgen和server,請在每個終端機視窗中輸入Ctrl-c。在
loadgen終端機視窗中停用虛擬環境:deactivate
裝載應用程式
如要在 GKE 上執行應用程式,您需要將範例應用程式 (server 和 loadgen) 封裝為容器。容器可封裝應用程式,使其與基礎環境隔離。
如要裝載應用程式,您需要 Dockerfile。Dockerfile 是文字檔案,定義將應用程式原始碼及其依附元件組合成 Docker 映像檔所需的指令。建構映像檔後,請將其上傳至容器登錄服務,例如 Docker Hub 或 Container Registry。
這個範例隨附 server,適用於 server 和 loadgen,並包含建構映像檔所需的所有指令。Dockerfile以下是 server 的 Dockerfile:
FROM python:3-slim as base指令會告知 Docker 使用最新的 Python 3 映像檔做為基本映像檔。COPY . .指令會將目前工作目錄中的來源檔案 (在本例中只有server.py) 複製到容器的檔案系統。ENTRYPOINT會定義用於執行容器的指令。在本例中,這個指令與您用來從原始碼執行server.py的指令幾乎相同。EXPOSE指令會指定server監聽通訊埠8080。 這個指令不會公開任何通訊埠,但可做為文件,說明您在執行容器時需要開啟通訊埠8080。
準備裝載應用程式
設定下列環境變數。將
PROJECT_ID替換為專案 ID。Google Cloudexport PROJECT_ID="PROJECT_ID"
export GCR_REPO="asm-ready"
建構 Docker 映像檔並推送至私人 Container Registry 時,您會使用
PROJECT_ID和GCR_REPO的值標記映像檔。設定 Google Cloud CLI 的預設 Google Cloud 專案。
gcloud config set project $PROJECT_ID
設定 Google Cloud CLI 的預設可用區。
gcloud config set compute/zone us-central1-b請確認您已在Google Cloud 專案中啟用 Container Registry 服務。
gcloud services enable containerregistry.googleapis.com
將 server 容器化
變更為範例
server所在的目錄:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
使用
Dockerfile和先前定義的環境變數建構映像檔:docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1 .-t旗標代表 Docker 標記。這是您部署容器時使用的映像檔名稱。將映像檔推送至 Container Registry:
docker push gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1
將 loadgen 容器化
變更為範例
loadgen所在的目錄:cd ../loadgen建構映像檔:
docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1 .將映像檔推送至 Container Registry:
docker push gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1
列出圖片
取得存放區中的映像檔清單,確認映像檔已推送:
gcloud container images list --repository gcr.io/$PROJECT_ID/asm-ready
指令會傳回您剛推送的映像檔名稱:
NAME gcr.io/PROJECT_ID/asm-ready/helloserver gcr.io/PROJECT_ID/asm-ready/loadgen
建立 GKE 叢集
您可以使用 docker run 指令,在 Cloud Shell VM 上執行這些容器。但在實際運作環境中,您需要以更統一的方式協調容器。舉例來說,您需要確保容器一律處於執行狀態的系統,以及擴大並啟動容器其他執行個體以處理流量增加情況的方法。
您可以使用 GKE 執行容器化應用程式。GKE 是容器編排平台,可將 VM 連線至叢集。每個 VM 都稱為「節點」。GKE 叢集是由 Kubernetes 開放原始碼叢集管理系統提供技術支援。您可以透過 Kubernetes 提供的機制與叢集互動。
如要建立 GKE 叢集,請按照下列步驟操作:
建立叢集:
gcloud container clusters create asm-ready \ --cluster-version latest \ --machine-type=n1-standard-4 \ --num-nodes 4
gcloud指令會在您先前設定的Google Cloud 專案和可用區中建立叢集。如要執行 Cloud Service Mesh,建議至少使用 4 個節點和 n1-standard-4 機器類型。建立叢集的指令需要幾分鐘才能完成。叢集就緒後,指令會輸出類似下列的訊息:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS asm-ready us-central1-b 1.13.5-gke.10 203.0.113.1 n1-standard-2 1.13.5-gke.10 4 RUNNING
向
kubectl指令列工具提供憑證,以便使用該工具管理叢集:gcloud container clusters get-credentials asm-ready現在您可以使用
kubectl與 Kubernetes 通訊。舉例來說,您可以執行下列指令來取得節點狀態:kubectl get nodes指令會傳回節點清單,如下所示:
NAME STATUS ROLES AGE VERSION gke-asm-ready-default-pool-dbeb23dc-1vg0 Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-36z5 Ready <none> 100s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-fj7s Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-wbjw Ready <none> 99s v1.13.6-gke.13
瞭解 Kubernetes 的重要概念
下圖說明在 GKE 上執行的應用程式:
將容器部署至 GKE 之前,建議先瞭解一些重要的 Kubernetes 概念。本教學課程的結尾會提供連結,方便您進一步瞭解各項概念。
節點和叢集:在 GKE 中,節點是 VM。在其他 Kubernetes 平台上,節點可以是實體或虛擬機器。叢集是一組節點,可視為單一機器,您可以在其中部署容器化應用程式。
Pod:在 Kubernetes 中,容器會在 Pod 內執行。Pod 是 Kubernetes 中的最小單位。Pod 包含一或多個容器。您會將
server和loadgen容器分別部署到各自的 Pod。如果 Pod 執行多個容器 (例如應用程式伺服器和Proxy 伺服器),系統會將這些容器視為單個實體進行管理,這些容器也共用 Pod 的資源。部署作業:部署作業是 Kubernetes 物件,代表一組相同的 Pod。Deployment 會執行多個 Pod 副本,並將這些副本分散到叢集的節點中。Deployment 會自動取代失敗或無法回應的 Pod。
Kubernetes Service:在 GKE 中執行應用程式程式碼會改變
loadgen和server之間的網路。在 Cloud Shell VM 中執行服務時,您可以使用localhost:8080位址,將要求傳送至server。部署至 GKE 後,系統會排定 Pod 在可用節點上執行。根據預設,您無法控制 Pod 執行的節點,因此 Pod 沒有穩定的 IP 位址。如要取得
server的 IP 位址,您必須在 Pod 上方定義稱為 Kubernetes Service 的網路抽象化。Kubernetes Service 可為一組 Pod 提供穩定的網路端點。 Service 分為幾種類型。server使用LoadBalancer,公開外部 IP 位址,讓您從叢集外部連線至server。Kubernetes 也有內建的 DNS 系統,可將 DNS 名稱 (例如
helloserver.default.cluster.local) 指派給 Service。這樣一來,叢集內的 Pod 就能透過穩定位址連線至叢集中的其他 Pod。您無法在叢集外部使用這個 DNS 名稱,例如從 Cloud Shell。
Kubernetes 資訊清單
從原始碼執行應用程式時,您使用了命令式指令:python3 server.py
命令式是指以動詞為主的語氣:「執行這項操作」。
相較之下,Kubernetes 採用宣告式模型。 也就是說,您不必明確指示 Kubernetes 執行作業,只需提供所需狀態。舉例來說,Kubernetes 會視需要啟動及終止 Pod,確保實際系統狀態符合所需狀態。
您可以在一組資訊清單或 YAML 檔案中指定所需狀態。YAML 檔案包含一或多個 Kubernetes 物件的規格。
範例包含 server 和 loadgen 的 YAML 檔案。每個 YAML 檔案都會指定 Kubernetes Deployment 物件和服務的所需狀態。
伺服器
kind表示物件類型。metadata.name會指定 Deployment 的名稱。- 第一個
spec欄位包含所需狀態的說明。 spec.replicas指定所需的 Pod 數量。spec.template部分會定義 Pod 範本。Pod 的規格包含image欄位,這是要從 Container Registry 提取的映像檔名稱。
「服務」定義如下:
LoadBalancer:用戶端會將要求傳送至網路負載平衡器的 IP 位址,該位址具有穩定性,且可從叢集外部連線。targetPort:請注意,Dockerfile中的EXPOSE 8080指令實際上不會公開任何連接埠。公開通訊埠8080,以便在叢集外部連線至server容器。在本例中,「hellosvc.default.cluster.local:80」(簡短名稱:hellosvc) 會對應至「helloserver」Pod IP 的通訊埠「8080」。port:這是叢集中其他服務傳送要求時使用的通訊埠號碼。
負載產生器
loadgen.yaml 中的 Deployment 物件與 server.yaml 類似。值得注意的是,Deployment 物件包含名為 env 的區段。本節定義 loadgen 要求的環境變數,您先前從來源執行應用程式時已設定這些變數。
由於 loadgen 不接受傳入要求,因此 type 欄位會設為 ClusterIP。這類 IP 位址穩定,叢集中的服務可以使用,但不會向外部用戶端公開。
將容器部署至 GKE
變更為範例
server所在的目錄:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
在文字編輯器中開啟
server.yaml。將「
image」欄位中的名稱換成 Docker 映像檔名稱。image: gcr.io/PROJECT_ID/asm-ready/helloserver:v0.0.1
並將
PROJECT_ID改成您的專案 ID。 Google Cloud儲存並關閉
server.yaml。將 YAML 檔案部署至 Kubernetes:
kubectl apply -f server.yaml成功後,指令會傳回下列內容:
deployment.apps/helloserver created service/hellosvc created
切換至
loadgen所在的目錄。cd ../loadgen在文字編輯器中開啟
loadgen.yaml。將「
image」欄位中的名稱換成 Docker 映像檔名稱。image: gcr.io/PROJECT_ID/asm-ready/loadgen:v0.0.1
並將
PROJECT_ID改成您的專案 ID。 Google Cloud儲存並關閉
loadgen.yaml,然後關閉文字編輯器。將 YAML 檔案部署至 Kubernetes:
kubectl apply -f loadgen.yaml成功後,指令會傳回下列內容:
deployment.apps/loadgenerator created service/loadgensvc created
檢查 Pod 的狀態:
kubectl get pods指令會傳回類似以下的狀態:
NAME READY STATUS RESTARTS AGE helloserver-69b9576d96-mwtcj 1/1 Running 0 58s loadgenerator-774dbc46fb-gpbrz 1/1 Running 0 57s
從
loadgenPod 取得應用程式記錄。將POD_ID替換為上一個輸出內容中的 ID。kubectl logs loadgenerator-POD_ID
取得
hellosvc的外部 IP 位址:kubectl get service該指令會輸出類似以下的結果:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hellosvc LoadBalancer 10.81.15.158 192.0.2.1 80:31127/TCP 33m kubernetes ClusterIP 10.81.0.1 <none> 443/TCP 93m loadgensvc ClusterIP 10.81.15.155 <none> 80/TCP 4m52s
向
hellosvc傳送要求。將EXTERNAL_IP替換為hellosvc的外部 IP 位址。curl http://EXTERNAL_IP
準備好使用 Cloud Service Mesh
您現在已將應用程式部署至 GKE。loadgen 可以使用 Kubernetes DNS (hellosvc:80) 將要求傳送至 server,您也可以使用外部 IP 位址將要求傳送至 server。雖然 Kubernetes 提供許多功能,但缺少服務的某些資訊:
- 服務如何互動?這兩項服務之間的關係為何?服務之間的流量如何流動?您知道
loadgen會將要求傳送至server,但假設您不熟悉該應用程式,您無法查看 GKE 上執行的 Pod 清單來回答這些問題。 - 指標:
server回應傳入要求需要多久時間? 傳入server的每秒要求數 (RPS) 為多少?是否有任何錯誤回應? - 安全性資訊:
loadgen與server之間的流量是純文字HTTP還是 mTLS?
Cloud Service Mesh 可提供這些問題的解答。Cloud Service Mesh 是 Google Cloud代管版本的 開放原始碼 Istio 專案。Cloud Service Mesh 會在每個 Pod 中放置 Envoy 補充 Proxy,Envoy Proxy 會攔截應用程式容器的所有傳入和傳出流量。也就是說,server 和 loadgen 各自取得 Envoy 補充 Proxy,且從 loadgen 到 server 的所有流量都會由 Envoy Proxy 媒介。這些 Envoy Proxy 之間的連線會形成服務網格。這項服務網格架構會在 Kubernetes 上方提供控制層。
由於 Envoy 代理程式會在自己的容器中執行,因此您可以在 GKE 叢集上安裝 Cloud Service Mesh,不必大幅變更應用程式程式碼。不過,您準備應用程式以透過 Cloud Service Mesh 進行檢測時,有幾種主要做法:
- 所有容器的服務:
server和loadgenDeployment 都已附加 Kubernetes 服務。即使是loadgen(未收到任何傳入要求),也有服務。 - 服務中的通訊埠必須命名:雖然 GKE 允許您定義未命名的服務通訊埠,但 Cloud Service Mesh 要求您為通訊埠提供名稱,且該名稱須與通訊埠的通訊協定相符。在 YAML 檔案中,
server的通訊埠命名為http,因為server使用HTTP通訊協定。如果service使用gRPC,您會將通訊埠命名為grpc。 - 部署作業會加上標籤:方便您使用 Cloud Service Mesh 流量管理功能,例如在同一服務的不同版本之間拆分流量。
安裝 Cloud Service Mesh
請參閱 Cloud Service Mesh 安裝指南,按照說明在叢集上安裝 Cloud Service Mesh。