容器簡介


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

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

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

目標

  1. 探索簡單的多服務「Hello World」應用程式。
  2. 從來源執行應用程式。
  3. 將應用程式容器化。
  4. 建立 Kubernetes 叢集。
  5. 將容器部署至叢集。

事前準備

請依照下列步驟啟用 Kubernetes Engine API:
  1. 前往 Google Cloud 控制台的 Kubernetes Engine 頁面
  2. 建立或選取專案。
  3. 等待 API 和相關服務完成啟用。 這可能需要幾分鐘的時間。
  4. Make sure that billing is enabled for your Google Cloud project.

準備 Cloud Shell

本教學課程使用 Cloud Shell,這會佈建執行 Debian 型 Linux 作業系統的 g1-small Compute Engine 虛擬機器 (VM)。

使用 Cloud Shell 的優點如下:

  • 已完整設定 Python 3 開發環境 (包括 virtualenv)。
  • 本教學課程使用的 gclouddockergitkubectl 指令列工具已安裝完畢。
  • 您可以選擇使用內建的文字編輯器

    • Cloud Shell 編輯器:按一下 Cloud Shell 視窗頂端的「開啟編輯器」即可存取。

    • Emacs、Vim 或 Nano,可透過 Cloud Shell 的指令列存取。

In the Google Cloud console, activate Cloud Shell.

Activate Cloud Shell

At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

下載程式碼範例

  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.13-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 編輯器,系統會自動儲存檔案。按一下「Open terminal」(開啟終端機),返回終端機視窗。
    • 如果您在 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 編輯器,系統會自動儲存檔案。按一下「Open terminal」(開啟終端機),返回終端機視窗。
    • 如果您在 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!」訊息。

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程中所用資源的相關費用,請刪除含有該項資源的專案,或者保留專案但刪除個別資源。

如果不想刪除整個專案:

  • 刪除 GKE 叢集。刪除叢集會一併刪除組成叢集的所有資源,例如 Compute Engine 執行個體、磁碟和網路資源。

     gcloud container clusters delete container-intro
    
  • 刪除 Artifact Registry 存放區:

     gcloud artifacts repositories delete container-intro --location=us-central1
    

後續步驟