容器簡介

如果您完全不熟悉容器化工作負載,這篇教學課程非常適合您。本指南會逐步說明如何從原始碼設定簡單的應用程式,到在 GKE 上執行的容器,藉此介紹容器和容器自動化調度管理。

本教學課程不需要任何容器或 Kubernetes 相關經驗。不過,如果您想在開始本教學課程前,先瞭解 Kubernetes 的核心術語,請參閱「開始瞭解 Kubernetes」(或者,如果您想以漫畫形式瞭解 Kubernetes,請參閱我們的 Kubernetes 漫畫)。如需更詳細的資源,請參閱本教學課程結尾的「後續步驟」一節。

如果您已熟悉容器和 Kubernetes,可以略過本教學課程,直接開始瞭解 GKE 本身

下載程式碼範例

  1. 下載 helloserver 原始碼:

    git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
    
  2. 變更為範例程式碼目錄:

    cd anthos-service-mesh-samples/docs/helloserver
    

探索多服務應用程式

範例應用程式是以 Python 編寫。其中包含下列元件,這些元件會使用 REST 通訊:

  • server:基本伺服器,其中包含一個 GET 端點 /,可將「hello world」列印至終端機視窗。
  • loadgen:將流量傳送至 server 的指令碼,每秒要求數 (RPS) 可設定。

應用程式範例

從來源執行應用程式

如要熟悉範例應用程式,請在 Cloud Shell 中執行:

  1. sample-apps/helloserver 目錄執行 server

    python3 server/server.py
    

    啟動時,server 會顯示下列內容:

    INFO:root:Starting server...
    
  2. 開啟另一個終端機視窗,以便將要求傳送至 server。 如要在 Cloud Shell 中執行這項操作,請按一下「開啟新分頁」 ,開啟另一個工作階段。

  3. 在新終端機視窗中,將要求傳送至 server

    curl http://localhost:8080
    

    server 的輸出內容如下:

    Hello World!
    
  4. 在同一個分頁中,變更為包含 loadgen 指令碼的目錄:

    cd anthos-service-mesh-samples/docs/helloserver/loadgen
  5. 建立下列的環境變數:

    export SERVER_ADDR=http://localhost:8080
    export REQUESTS_PER_SECOND=5
    
  6. 開始時間 virtualenv

    virtualenv --python python3 env
    
  7. 啟用虛擬環境:

    source env/bin/activate
    
  8. 安裝 loadgen 的需求項目:

    pip3 install -r requirements.txt
    
  9. 執行 loadgen 應用程式,為 server 產生流量:

    python3 loadgen.py
    

    啟動時,loadgen 的輸出內容會與下列內容類似:

    Starting loadgen: 2024-10-11 09:49:51.798028
    5 request(s) complete to http://localhost:8080
    
  10. 現在請開啟執行 server 的終端機視窗。您會看到類似下方顯示的訊息:

    127.0.0.1 - - [11/Oct/2024 09:51:28] "GET / HTTP/1.1" 200 -
    INFO:root:GET request,
    Path: /
    Headers:
    Host: localhost:8080
    User-Agent: python-requests/2.32.3
    Accept-Encoding: gzip, deflate
    Accept: */*
    Connection: keep-alive
    

    從網路的角度來看,整個應用程式現在都在同一個主機上執行,因此您可以使用 localhost 將要求傳送至 server

  11. 如要停止 loadgenserver,請在每個終端機視窗中按下 Ctrl-c

  12. loadgen 終端機視窗中停用虛擬環境:

    deactivate
    

裝載應用程式

如要在 GKE 上執行應用程式,您需要將範例應用程式的兩個元件封裝到容器中。容器是套件,內含應用程式在任何環境中執行的所有必要元素。本教學課程使用 Docker 將應用程式容器化。

如要使用 Docker 將應用程式容器化,您需要 DockerfileDockerfile 是文字檔案,定義將應用程式原始碼及其依附元件組合成容器映像檔所需的指令。建構映像檔後,請將映像檔上傳至容器登錄檔,例如 Artifact Registry

本教學課程的原始碼包含 serverloadgenloadgen,其中包含建構映像檔所需的所有指令。Dockerfile以下是 serverDockerfile

FROM python:3.14-slim as base
FROM base as builder
RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        g++ \
    && rm -rf /var/lib/apt/lists/*

# Enable unbuffered logging
FROM base as final
ENV PYTHONUNBUFFERED=1

RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        wget

WORKDIR /helloserver

# Grab packages from builder
COPY --from=builder /usr/local/lib/python3.* /usr/local/lib/

# Add the application
COPY . .

EXPOSE 8080
ENTRYPOINT [ "python", "server.py" ]

您可以在這個檔案中查看下列內容:

  • FROM python:3-slim as base 指令會告知 Docker 使用最新的 Python 3 映像檔做為基本映像檔。
  • COPY . . 指令會將目前工作目錄 (在本例中為 server.py) 中的來源檔案複製到容器的檔案系統。
  • ENTRYPOINT 會定義用於執行容器的指令。在本範例中,指令與您用來從原始碼執行 server.py 的指令類似。
  • EXPOSE 指令指定 server 監聽通訊埠 8080。 這項指令不會公開任何通訊埠,但會做為文件,說明您在執行容器時需要開啟通訊埠 8080

準備裝載應用程式

在將應用程式容器化之前,您需要為要使用的工具和服務進行一些設定:

  1. 設定 Google Cloud CLI 的預設 Google Cloud 專案。

    gcloud config set project PROJECT_ID
  2. 設定 Google Cloud CLI 的預設區域。

    gcloud config set compute/region us-central1
    

建立存放區

如要在 Artifact Registry 中建立 Docker 容器映像檔的新存放區,請按照下列步驟操作:

  1. 請確認您已在Google Cloud 專案中啟用 Artifact Registry 服務。

    gcloud services enable artifactregistry.googleapis.com
    
    
  2. 建立 Artifact Registry 存放區:

    gcloud artifacts repositories create container-intro --repository-format=docker \
        --location=us-central1 \
        --description="My new Docker repository"
    
  3. 使用 Google Cloud CLI 設定 Docker 對 Artifact Registry 的驗證:

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

server 容器化

現在可以將應用程式容器化了。首先,將「hello world」server 容器化,然後將映像檔推送至 Artifact Registry:

  1. 變更為範例 server 所在的目錄:

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. 使用 Dockerfile 建構映像檔:

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1 .
    
    • PROJECT_ID 替換為專案 ID。 Google Cloud

    -t 旗標代表 Docker 標記。這是您部署容器時使用的映像檔名稱。

  3. 將映像檔推送至 Artifact Registry:

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

loadgen 容器化

接著,以相同方式將負載產生器服務容器化:

  1. 變更為範例 loadgen 所在的目錄:

    cd ../loadgen
    
  2. 建構映像檔:

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1 .
    
  3. 將映像檔推送至 Artifact Registry:

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
    

列出圖片

取得存放區中的映像檔清單,確認映像檔已推送:

gcloud container images list --repository us-central1-docker.pkg.dev/PROJECT_ID/container-intro

輸出內容應會列出您推送的映像檔名稱,如下所示:

NAME
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen

建立 GKE 叢集

此時,您可以使用 docker run 指令,在 Cloud Shell VM 上執行容器。不過,如要執行可靠的正式環境工作負載,您需要以更統一的方式管理容器。舉例來說,您需要確保容器在失敗時重新啟動,並需要擴充及啟動其他容器執行個體,以處理流量增加的情況。

GKE 可協助您滿足這些需求。GKE 是容器編排平台,可將 VM 連線至叢集。每個 VM 都稱為「節點」。GKE 叢集是由 Kubernetes 開放原始碼叢集管理系統提供技術支援。此外,也可以透過 Kubernetes 提供的機制與叢集互動

如要在 GKE 上執行容器,您必須先建立叢集,然後連線至該叢集:

  1. 建立叢集:

    gcloud container clusters create-auto container-intro
    

    gcloud 指令會在您先前設定的預設 Google Cloud 專案和區域中建立叢集。

    建立叢集的指令需要幾分鐘才能完成。叢集就緒後,輸出內容會類似於下列內容:

     NAME: container-intro
     LOCATION: us-central1
     MASTER_VERSION: 1.30.4-gke.1348000
     MASTER_IP: 34.44.14.166
     MACHINE_TYPE: e2-small
     NODE_VERSION: 1.30.4-gke.1348000
     NUM_NODES: 3
     STATUS: RUNNING
    
  2. kubectl 指令列工具提供憑證,以便使用該工具管理叢集:

    gcloud container clusters get-credentials container-intro
    

檢查 Kubernetes 資訊清單

從原始碼執行應用程式時,您使用了命令式指令:python3 server.py

命令式是指以動詞為主的語氣:「執行這項操作」。

相較之下,Kubernetes 採用宣告式模型。 也就是說,您不必明確指示 Kubernetes 執行作業,只需提供所需狀態。舉例來說,Kubernetes 會視需要啟動及終止 Pod,確保實際系統狀態符合所需狀態。

您可以在名為資訊清單的檔案中指定所需狀態。資訊清單以 YAML 或 JSON 等語言編寫,內含一或多個 Kubernetes 物件的規格。

範例包含 serverloadgen 各自的資訊清單。每個資訊清單都會指定 Kubernetes Deployment 物件的所需狀態 (該物件會管理容器的執行作業,並將容器封裝為 Kubernetes Pod 以利管理),以及 Service (該物件會為 Pod 提供 IP 位址)。Pod 是 Kubernetes 中可建立及管理的最小運算部署單位,內含一或多個容器。

下圖說明在 GKE 上執行的應用程式:

在 GKE 上執行的容器化應用程式

如要進一步瞭解 Pod、Deployment 和 Service,請參閱「開始學習 Kubernetes」或本頁結尾的資源。

伺服器

首先,請查看「hello world」的資訊清單 server

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloserver
  template:
    metadata:
      labels:
        app: helloserver
    spec:
      containers:
      - image: gcr.io/google-samples/istio/helloserver:v0.0.1
        imagePullPolicy: Always
        name: main
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

這個資訊清單包含下列欄位:

  • kind 表示物件類型。
  • metadata.name 會指定 Deployment 的名稱。
  • 第一個 spec 欄位包含所需狀態的說明。
  • spec.replicas 指定所需的 Pod 數量。
  • spec.template 部分會定義 Pod 範本。Pod 的規格包含 image 欄位,這是要從 Artifact Registry 提取的映像檔名稱。在下一個步驟中,您將更新這個值, 改為剛才建立的新圖片。

hellosvc 服務的定義如下:

apiVersion: v1
kind: Service
metadata:
  name: hellosvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: helloserver
  type: LoadBalancer
  • LoadBalancer:用戶端會將要求傳送至網路負載平衡器的 IP 位址,該位址具有穩定性,且可從叢集外部連線。
  • targetPort:請注意,Dockerfile 中的 EXPOSE 8080 指令實際上不會公開任何連接埠。公開通訊埠 8080,以便在叢集外部連線至 server 容器。在本例中,「hellosvc.default.cluster.local:80」(簡短名稱:hellosvc) 會對應至「helloserver」Pod IP 的通訊埠「8080」。
  • port:這是叢集中其他服務傳送要求時使用的通訊埠號碼。

負載產生器

loadgen.yaml 中的 Deployment 物件與 server.yaml 類似。值得注意的差異是,loadgen Deployment 的 Pod 規格具有名為 env 的欄位。本節定義 loadgen 所需的環境變數,您先前從來源執行應用程式時已設定這些變數。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: loadgenerator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: loadgenerator
  template:
    metadata:
      labels:
        app: loadgenerator
    spec:
      containers:
      - env:
        - name: SERVER_ADDR
          value: http://hellosvc:80/
        - name: REQUESTS_PER_SECOND
          value: '10'
        image: gcr.io/google-samples/istio/loadgen:v0.0.1
        imagePullPolicy: Always
        name: main
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 300m
            memory: 256Mi
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

由於 loadgen 不接受傳入要求,因此 type 欄位會設為 ClusterIP。這類服務會提供叢集中的實體可使用的穩定 IP 位址,但不會向外部用戶端公開 IP 位址。

apiVersion: v1
kind: Service
metadata:
  name: loadgensvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: loadgenerator
  type: ClusterIP

將容器部署至 GKE

如要部署容器,請使用 kubectl套用資訊清單,指定所需狀態。

部署 server

  1. 變更為範例 server 所在的目錄:

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. Cloud Shell 編輯器 (或您偏好的文字編輯器) 中開啟 server.yaml

  3. 將「image」欄位中的名稱換成 Docker 映像檔名稱。

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

    PROJECT_ID 替換為您的 Google Cloud 專案 ID。

    • 如果您使用 Cloud Shell 編輯器,系統會自動儲存檔案。按一下「開啟終端機」,返回終端機視窗。
    • 如果您在 Cloud Shell 中使用文字編輯器,請儲存並關閉 server.yaml
  4. 將資訊清單部署至 Kubernetes:

    kubectl apply -f server.yaml
    

    輸出結果會與下列內容相似:

    deployment.apps/helloserver created
    service/hellosvc created
    

部署 loadgen

  1. 切換至 loadgen 所在的目錄。

    cd ../loadgen
    
  2. 如先前所述,在文字編輯器中開啟 loadgen.yaml

  3. 再次將「name」(名稱) 欄位中的名稱替換為 Docker 映像檔名稱。image

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
    

    PROJECT_ID 替換為您的 Google Cloud 專案 ID。

    • 如果您使用 Cloud Shell 編輯器,系統會自動儲存檔案。按一下「開啟終端機」,返回終端機視窗。
    • 如果您在 Cloud Shell 中使用文字編輯器,請儲存並關閉 loadgen.yaml
  4. 將資訊清單部署至叢集:

    kubectl apply -f loadgen.yaml
    

    成功後,指令會傳回下列內容:

    deployment.apps/loadgenerator created
    service/loadgensvc created
    

驗證部署作業

將資訊清單部署至叢集後,請確認容器已成功部署:

  1. 檢查叢集中 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
    
  2. loadgen Pod 取得應用程式記錄。將 POD_ID 替換為上一個輸出內容中的負載產生器 Pod 識別碼。

    kubectl logs POD_ID
    
  3. 取得 hellosvc 的外部 IP 位址:

    kubectl get service hellosvc
    

    輸出結果會與下列內容相似:

    NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
    hellosvc     LoadBalancer   10.81.15.158   192.0.2.1       80:31127/TCP   33m
    
  4. hellosvc 傳送要求。將 EXTERNAL_IP 替換為 hellosvc 的外部 IP 位址。

    curl http://EXTERNAL_IP
    

    您應該會看到伺服器傳送的「Hello World!」訊息。