从 Kubernetes 迁移到 Cloud Run

Cloud Run 和 Kubernetes 都使用标准容器映像作为部署工件,它们都使用声明性 API 模型,其中的资源可以在具有相同标准结构的 YAML 文件中表示。

简介

Cloud Run Admin API v1 旨在最大限度地提高 Kubernetes 的可移植性,例如,Cloud Run Admin API 资源与 Kubernetes 资源具有相同的结构惯例和特性名称。请参阅 Cloud Run 服务 YAML 参考文档

Cloud Run Admin API v1 实现了 Knative Serving API 规范,但您无需在现有 Kubernetes 集群中使用 Knative 即可将一些 Kubernetes 工作负载迁移到 Cloud Run。

Cloud Run 的主要资源是服务。您可以将 Cloud Run 服务视为一个高级抽象层,它类似于一个具有内置 pod 自动扩缩器和唯一端点的 Kubernetes Deployment。Kubernetes 中的“Pod”对应于 Cloud Run 中的一个“实例”。我们建议逐一将 Kubernetes Deployment 转换为 Cloud Run 服务。您还可以将 Kubernetes Pod 横向自动扩缩器和 Kubernetes 服务的一些配置合并到 Cloud Run 服务中。

Cloud Run 没有命名空间的概念,而是使用 Google Cloud 项目作为资源之间的隔离边界。从 Kubernetes 迁移到 Cloud Run 时,我们建议为每个命名空间创建一个 Google Cloud 项目。在 Cloud Run 服务的 YAML 中,命名空间值是 Google Cloud 项目编号。

Cloud Run 具有内置可用区冗余,这意味着您无需预配副本,即可确保您的服务在所选 Google Cloud 区域发生可用区级服务中断时具有弹性。

快速入门

本快速入门是一个简单的迁移示例。

简单的资源对比

将以下名为 my-app 的简单 Kubernetes Deployment 与等效的 Cloud Run 服务进行比较。请注意,YAML 文件几乎完全相同。

blue 颜色显示的部分有些许差异,迁移时需要予以更改。由于 Cloud Run 具有内置的自动扩缩器,因此应删除 red 中的部分内容。

Kubernetes DeploymentCloud Run 服务
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
  labels:
    app: my-app
spec:
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - image: gcr.io/cloudrun/hello
        env:
        - name: HELLO
          value: world
  replicas: 3
  selector:
    matchLabels:
      app: my-app
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: my-app
  namespace: 'PROJECT_NUMBER'
  labels:
    app: my-app
spec:
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - image: gcr.io/cloudrun/hello
        env:
        - name: HELLO
          value: world

将简单的 Kubernetes Deployment 迁移到 Cloud Run

  1. 使用以下命令下载当前目录中 Deployment 的 YAML 文件:

    kubectl get deployment  my-app -o yaml > my-app.yaml
  2. 修改 YAML 以与 Cloud Run 服务匹配。更新 my-app.yaml 文件。

    • 对于“kind”属性,请将值“Deployment”替换为“Service
    • 对于“apiVersion”属性,请将值“apps/v1”替换为“serving.knative.dev/v1
    • 删除 metadata.namespace 属性或更改其值以与您的 Google Cloud 项目编号匹配。
    • 删除 spec.replicasspec.selector
  3. 使用以下命令将 my-app.yaml 文件部署到 Cloud Run,注意将 REGION 替换为所需的 Google Cloud 区域,例如 us-central1

    gcloud run services replace my-app.yaml --region REGION

调用 Cloud Run 服务受 IAM 权限保护。如果要将新的 Cloud Run 服务公开给互联网并允许未经身份验证的调用,请运行以下命令:

gcloud run services add-iam-policy-binding my-app --member="allUsers" --role="roles/run.invoker" --region REGION

Cloud Run 不支持的功能

只能迁移适合 Cloud Run 的工作负载。

值得注意的是,Cloud Run 不支持以下 Kubernetes 功能:

  • 固定数量的 replicas(一种解决方法是使用相同数量的最小最大实例)
  • ConfigMap(可用解决方法
  • 自定义 Pod 横向自动扩缩器策略
  • Service Discovery

将 YAML 文件从 Kubernetes Deployment 迁移到 Cloud Run 服务时,gcloud run services replace 命令会为 Cloud Run 不支持的任何特性返回明确错误消息。删除或更新这些特性,然后重复运行该命令,直到成功为止。

如需查看 Cloud Run 支持的特性的详尽列表,请参阅 YAML 参考文档

迁移 Kubernetes 资源

迁移 Kubernetes Secret

与 Kubernetes 一样,Cloud Run 支持将 Secret 作为环境变量或卷装载,但 Secret 应存储在 Secret Manager 中。

Secret Manager 中的 Secret 与 Kubernetes Secret 之间存在一些重大差异:

  • 名称中允许使用的字符
  • 版本控制:Secret Manager 中的 Secret 可以有版本控制,而 Kubernetes Secret 则没有版本控制。
  • 载荷:Secret Manager 中的 Secret 包含一个 []byte,而 Kubernetes Secret 则包含 map<string, string>

按照 Secret Manager 文档创建 Secret,并为您的 Kubernetes 应用所依赖的每个 Secret 添加新的 Secret 版本

迁移 Kubernetes ConfigMap

Cloud Run 没有等效的 Kubernetes ConfigMaps,但是,由于 ConfigMap 可以被视为未加密的 Secret,因此您可以将 ConfigMap 转换为 Secret Manager 中的 Secret。请参阅迁移 Kubernetes Secret 下的说明。

迁移 Kubernetes Deployment

Kubernetes Deployment 是映射到 Cloud Run 服务的资源。我们建议从 Kubernetes Deployment 的 YAML 开始,并对其进行修改以将其转换为 Cloud Run 服务。

所需的主要更改如下:

  • namespace 必须替换为 Google Cloud 项目编号。
  • 标签(metadata.labelsspec.template.metadata.labels)必须是有效的 Google Cloud 标签
  • 容器必须存储在受支持的容器注册表中。
  • 可能需要调整 CPU内存限制。
  • 引用 Secret 时,“key”特性用于捕获 Secret Manager 中的版本,其中“latest”引用 Secret 的最新版本。
  • serviceAccountName 应引用当前 Google Cloud 项目中的服务账号
  • 应将对 ConfigMap (configMapKeyRef) 的引用替换为对 Secret (secretKeyRef) 的引用

如果您的 Kubernetes Deployment 正在访问 Kubernetes 集群中的其他资源或 VPC 上的资源,则必须将 Cloud Run 服务连接到相应的 VPC

迁移 Kubernetes Service

Cloud Run 服务会自动公开一个唯一的端点,该端点会将流量路由到具有 containerPort 的容器。将 Kubernetes Deployment 迁移到 Cloud Run 服务后,您无需迁移将流量路由到此 Deployment 的 Kubernetes Service

迁移 Kubernetes HorizontalPodAutoscaler

Cloud Run 服务具有内置的横向自动扩缩器:Cloud Run 会在其定义的实例数下限和上限的边界内使用因素组合来自动扩缩 pod(称为“实例”)。

HorizontalPodAutoscalerminReplicasmaxReplicas 属性迁移到 Cloud Run 服务的 autoscaling.knative.dev/minScaleautoscaling.knative.dev/maxScale 注解。请参阅有关配置实例数下限实例数上限的文档。

迁移 Kubernetes 作业

由于 Kubernetes 作业类似于 Cloud Run 作业执行,因此您可以迁移到 Cloud Run 作业以及执行作业

以下示例展示了 Kubernetes 作业和 Cloud Run 作业之间的结构差异:

Kubernetes 作业Cloud Run 作业
apiVersion: batch/v1
kind: Job
metadata:
  name: my-job
spec:
  template:
    spec:
      containers:
      - image: us-docker.pkg.dev/cloudrun/container/job
apiVersion: run.googleapis.com/v1
kind: Job
metadata:
  name: my-job
spec:
  template:
    spec:
      template:
        spec:
          containers:
          - image: us-docker.pkg.dev/cloudrun/container/job

迁移策略

创建等效资源后,您需要公开全球外部应用负载均衡器后面的外部端点,这样您便可以在 Cloud Run 和 Google Kubernetes Engine (GKE) 之间逐步迁移流量。