容器简介


如果您对容器化工作负载完全不熟悉,不妨参阅本教程。本课程将引导您将简单的应用从源代码设置为在 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 Editor,您可以通过点击 Cloud Shell 窗口顶部的 Open Editor 访问该编辑器。

    • 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
    

    从网络的角度来看,整个应用目前在同一主机上运行,这样您就可以使用 localhostserver 发送请求。

  11. 如需停止 loadgenserver,请在每个终端窗口中按 Ctrl-c

  12. loadgen 终端窗口中,停用虚拟环境:

    deactivate
    

将应用容器化

如需在 GKE 上运行应用,您需要将示例应用的两个组件打包到容器中。容器是一个软件包,其中包含应用在任何环境中运行所需的所有元素。本教程使用 Docker 将应用容器化。

如需使用 Docker 将应用容器化,您需要一个 DockerfileDockerfile 是一个文本文件,用于定义将应用源代码及其依赖项汇编到容器映像中所需的命令。构建映像后,您可以将其上传到容器注册表,例如 Artifact Registry

本教程的源代码包含一个 Dockerfile 用于 serverloadgen,后者具有构建映像所需的所有命令。以下是 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 替换为您的 Google Cloud 项目的 ID。

    -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 虚拟机上运行容器即可。但是,若要运行可靠的生产工作负载,您需要以更统一的方式管理容器。例如,您需要确保容器在发生故障时重启,并且需要一种方法来纵向扩容和启动容器的其他实例,以便处理流量增加。

GKE 可帮助您满足这些需求。GKE 是一个容器编排平台,其工作方式是将虚拟机连接到集群。每个虚拟机称为一个节点。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 提供所需状态。例如,Kubernetes 会根据需要启动和终止 Pod,以使实际系统状态与所需状态匹配。

您可以在名为清单的文件中指定所需状态。清单使用 YAML 或 JSON 等语言编写,并包含一个或多个 Kubernetes 对象的规范。

该示例包含 serverloadgen 各自的清单。每个清单都指定 Kubernetes Deployment 对象(用于管理作为 Kubernetes Pod 打包并运行的容器)和 Service(用于为 Pod 提供 IP 地址)的所需状态。Pod 是您可以在 Kubernetes 中创建和管理的最小可部署计算单元,可容纳一个或多个容器。

下图显示在 GKE 上运行的应用:

在 GKE 上运行的容器化应用

您可以参阅开始学习 Kubernetes,或参阅本页末尾的资源,详细了解 Pod、部署和服务。

服务器

首先,查看“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 地址发送请求,网络负载平衡器具有稳定的 IP 地址,并且可从集群外部访问。
  • targetPort:回想一下,Dockerfile 中的 EXPOSE 8080 命令不会实际公开任何端口。您可以公开端口 8080,以便访问集群外部的 server 容器。在这种情况下,hellosvc.default.cluster.local:80(简称:hellosvc)映射到 helloserver Pod IP 的端口 8080
  • port:这是在发送请求时集群中的其他服务使用的端口号。

负载生成器

loadgen.yaml 中的 Deployment 对象类似于 server.yaml。一个显著区别是,loadgen 部署的 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。此类 Service 提供集群中的实体可以使用的稳定 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 Editor(或首选文本编辑器)中打开 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 Editor,系统会自动保存文件。点击打开终端,返回终端窗口。
    • 如果您在 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. 再次将 image 字段中的名称替换为您的 Docker 映像的名称。

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

    PROJECT_ID 替换为您的 Google Cloud 项目 ID。

    • 如果您使用的是 Cloud Shell Editor,系统会自动保存文件。点击打开终端,返回终端窗口。
    • 如果您在 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
    

后续步骤