涉及操作

  1. 使用 Cloud Build 将应用封装到容器映像中。
  2. 在 Google Kubernetes Engine (GKE) 中创建一个集群。
  3. 将容器映像部署到该集群。

准备工作

  1. 登录您的 Google Cloud 账号。如果您没有 Google Cloud 账号,可以选择创建一个 Google账号来继续操作。新客户还可获享 $300 赠金,用于运行、测试和部署工作负 载。
  2. 创建或选择一个项目。
  3. 检测并确保您的项目已启用结算功能。
  4. 启用 Artifact Registry, Cloud Build, and Google Kubernetes Engine API。
  5. 安装 Google Cloud CLI,如果您之前安装了 gcloud CLI,请确保通过运行 gcloud components update 获得最新版本。
  6. 使用 gcloud 安装 kubectl,用于管理Kubernetes(即 GKE 使用的集群编排系统)
  7. 创建或选择一个应用

相关操作

使用 Cloud Build 将应用容器化

  1. 如需将应用容器化,请在与源文件相同的目录中创建一个名为 Dockerfile 的 新文件,并将以下内容复制到此文件中:

    Go
    # Use the offical Go image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang:1.22.0 as builder
    WORKDIR /app
    # Initialize a new Go module.
    RUN go mod init quickstart-go
    # Copy local code to the container image.
    COPY *.go ./
    # Build the command inside the container.
    RUN CGO_ENABLED=0 GOOS=linux go build -o /quickstart-go
    # Use a Docker multi-stage build to create a lean production image.
    #
    https://docs.docker.com/develop/develop-images/multistage-build/#use-mul
    ti-stage-builds
    FROM gcr.io/distroless/base-debian11
    # Change the working directory.
    WORKDIR /
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /quickstart-go /quickstart-go
    # Run the web service on container startup.
    USER nonroot:nonroot
    ENTRYPOINT ["/quickstart-go"]
                                

    Node.js
    # Use the official lightweight Node.js 16 image.
    # https://hub.docker.com/_/node
    FROM node:21-slim
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    # Copy application dependency manifests to the container image.
    # A wildcard is used to ensure both package.json AND package-lock.json
    are copied.
    # Copying this separately prevents re-running npm install on every code
    change.
    COPY package*.json ./
    # Install production dependencies.
    RUN npm install --omit=dev
    # Copy local code to the container image.
    COPY . ./
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
    

    再添加一个 .dockerignore 文件,以确保本地文件不会影响容器的构建过程:

    Dockerfile
    README.md
    node_modules
    npm-debug.log

    Python
        # Use the official lightweight Python image.
     # https://hub.docker.com/_/python
     FROM python:3.12-slim
     # Copy local code to the container image.
     ENV APP_HOME /app
     WORKDIR $APP_HOME
     COPY . ./
     # Install production dependencies.
     RUN pip install Flask gunicorn
     # Run the web service on container startup. Here we use the gunicorn
     # webserver, with one worker process and 8 threads.
     # For environments with multiple CPU cores, increase the number of
     workers
     # to be equal to the cores available.
     CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 app:app
    

    再添加一个 .dockerignore 文件,以确保本地文件不会影响容器的构建过程:

    Dockerfile
    README.md
    *.pyc
    *.pyo
    *.pyd
    __pycache__

    C#
    # Use Microsoft's official lightweight .NET images.
    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
    WORKDIR /app
    # Install production dependencies.
    # Copy csproj and restore as distinct layers.
    COPY *.csproj ./
    RUN dotnet restore
    # Copy local code to the container image.
    COPY . ./
    # Build a release artifact.
    RUN dotnet publish -c Release -o out
    # Run the web service on container startup in a lean production image.
    FROM mcr.microsoft.com/dotnet/aspnet:6.0
    WORKDIR /app
    COPY --from=build /app/out .
    # Start the .dll (will have the same name as your .csproj file)
    ENTRYPOINT ["dotnet", "helloworld-gke.dll"]
    

    再添加一个 .dockerignore 文件,以确保本地文件不会影响容器的构建过程:

    Dockerfile
    README.md
    **/obj/
    **/bin/
    

    PHP
    # Use the official PHP 7.4 image.
    # https://hub.docker.com/_/php
    FROM php:8.2-apache
    # Copy local code to the container image.
    COPY index.php /var/www/html/
    # Use port 8080 in Apache configuration files.
    RUN sed -i 's/80/${PORT}/g'
    /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
    # Configure PHP for development.
    # Switch to the production php.ini for production operations.
    # RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
    # https://hub.docker.com/_/php#configuration
    RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
    

    再添加一个 .dockerignore 文件,以确保本地文件不会影响容器的构建过程:

    Dockerfile
    README.md
    vendor
    
  2. 获取 Google Cloud 项目 ID:
    gcloud config get-value project
                        
  3. 在本快速入门中,您需要将容器存储在 Artifact Registry 中,并从注册表中将其部署到 集群。运行以下命令,在集群所在的位置创建名为 hello-repo 的仓库:
    gcloud artifacts repositories create hello-repo \
    --project=PROJECT_ID \
    --repository-format=docker \
    --location=us-central1 \
    --description="Docker repository"
    

    替换以下值: 是您的 Google Cloud 项目 ID

  4. 使用 Cloud Build 构建容器映像,此行为类似于运行 docker build 和 docker push,但构建是在 Google Cloud 上进行的:
    gcloud builds submit \
    --tag us-central1-docker.pkg.dev/PROJECT_ID/hello-repo/helloworld-gke .

创建 GKE 集群

GKE 集群是作为单个 GKE 集群运行的一组托管式 Compute Engine 虚拟机。

  1. 创建集群。
    gcloud container clusters create-auto helloworld-gke \
        --location us-central1
  2. 验证您有权访问该集群。以下命令会列出您的容器集群中已启动并运行的节点, 并表明您有权访问该集群。
    kubectl get nodes

部署到 GKE

如需将该应用部署到您创建好的 GKE 集群,您需要用到两个 Kubernetes 对象。

  1. 一个 Deployment 对象,用来定义您的应用。
  2. 一个 Service 对象,用来定义如何访问您的应用。

部署应用

该应用具有一个前端服务器,用于处理 Web 请求。您可以在名为 deployment.yaml 的新文 件中定义运行该前端所需的集群资源。这些资源通过一个 Deployment 对象来描述。您可以使 用 Deployment 来创建和更新 ReplicaSet 以及与其关联的 Pod。

  1. 在与其他文件相同的目录中创建 deployment.yaml 文件,然后复制以下内容。在文 件中替换以下值:
    • $GCLOUD_PROJECT 是您的 Google Cloud 项目 ID
    • $LOCATION 是代码库位置,例如 us-central1。
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: helloworld-gke
    spec:
    replicas: 1
    selector:
    matchLabels:
    app: hello
    template:
    metadata:
    labels:
    app: hello
    spec:
    containers:
    - name: hello-app
    # Replace $LOCATION with your Artifact Registry location (e.g.,
    us-west1).
    # Replace $GCLOUD_PROJECT with your project ID.
    image:
    $LOCATION-docker.pkg.dev/$GCLOUD_PROJECT/hello-repo/helloworld-gke:lates
    t
    # This app listens on port 8080 for web traffic by default.
    ports:
    - containerPort: 8080
    env:
    - name: PORT
    value: "8080"
    resources:
    requests:
    memory: "1Gi"
    cpu: "500m"
    ephemeral-storage: "1Gi"
    limits:
    memory: "1Gi"
    cpu: "500m"
    ephemeral-storage: "1Gi"
    
  2. 将资源部署到集群:
    kubectl apply -f deployment.yaml
  3. 跟踪 Deployment 的状态:
    kubectl get deployments

    如果所有 AVAILABLE 部署都为 READY,则表示 Deployment 已完成。

    NAME READY UP-TO-DATE AVAILABLE AGE
    helloworld-gke 1/1 1 1 20s

    如果 Deployment 有误,请再次运行 kubectl apply -f deployment.yaml,更新 Deployment 以纳入任何更改。

  4. Deployment 完成后,您可以查看 Deployment 创建的 Pod:
    kubectl get pods

部署Service

Service 提供对一组 Pod 的单一访问点。尽管您可以访问单个 Pod,但 Pod 是临时性 的,只有使用一个 Service 地址才能进行可靠的访问。在您的 Hello World 应用中,名 为“hello”的 Service 定义了一个负载均衡器,用于通过一个 IP 地址访问多个 hello-app Pod。此 Service 在 service.yaml 文件中定义。

  1. 请在与其他源文件相同的目录中创建一个名为 service.yaml 的文件,并在此 文件中添加以下内容:
    # The hello service provides a load-balancing proxy over the hello-app
     # pods. By specifying the type as a 'LoadBalancer', Kubernetes Engine
     will
     # create an external HTTP load balancer.
     apiVersion: v1
     kind: Service
     metadata:
     name: hello
     spec:
     type: LoadBalancer
     selector:
     app: hello
     ports:
     - port: 80
     targetPort: 8080

    这些 Pod 与使用 Pod 的 Service 是分别定义的。Kubernetes 使用标签来选择 服务指向的 Pod。利用标签,您既可以让一个 Service 指向来自不同副本集的多 个 Pod,也可以让多个 Service 指向同一个 Pod。

  2. 创建 Hello World Service:
    kubectl apply -f service.yaml
  3. 获取服务的外部 IP 地址:
    kubectl get services

    分配 IP 地址最多可能需要 60 秒的时间。外部 IP 地址列在 hello Serivce 的 EXTERNAL-IP 列下。

    NAME        TYPE            CLUSTER-IP      EXTERNAL-IP     PORT(S)         AGE
    hello       LoadBalancer    10.22.222.222   35.111.111.11   80:32341/TCP    1m
    kubernetes  ClusterIP       10.22.222.1     none            443/TCP         20m

查看已部署的应用

现在,您已经部署好了在 GKE 上运行 Hello World 应用所需的全部资源。

使用在上一步中获取的外部 IP 地址在网络浏览器中加载应用,并查看正在运行的应用:

http://EXTERNAL-IP

或者,您可以对 Service 的外部 IP 地址进行 curl 调用:

curl EXTERNAL_IP

输出显示以下内容:

Hello World!


清理

为避免因本页中使用的资源导致您的 Google Cloud 账号产生费用,请按照以下步骤操作。

您需要为集群中运行的 Compute Engine 实例和 Container Registry 中的容器映像付费。


删除项目

删除 Google Cloud 项目后,系统会停止对该项目中使用的所有资源计费。

  1. 在 Google Cloud 控制台中,进入管理资源页面。
  2. 在项目列表中,选择要删除的项目,然后点击删除。
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除集群

如果您想保留项目,只删除本教程中使用的资源,请删除您的集群和映像。

如需使用 Google Cloud CLI 删除集群,请为您使用的模式运行以下命令:

gcloud container clusters delete helloworld-gke \
    --location us-central1

如需删除 Artifact Registry 代码库中的映像,请运行以下命令:

gcloud artifacts docker images delete \
    us-central1-docker.pkg.dev/PROJECT_ID/hello-repo/helloworld-gke