【译】Google Cloud Run 和 Knative 真的一样吗
本文翻译自 Ahmet Alp Balkan 在 2020 年 3 月发布的博文《Is Google Cloud Run really Knative?》。用以阐述谷歌开源的无服务器引擎 Knative 与其商业版无服务器平台 Google Cloud Run 的关系。本文仅供学习交流,如有侵权将立即删除。
Cloud Run 是谷歌的无服务器平台。它声称实现了 Knative API 及其运行时规约。即可以使用相同的 YAML 清单文件,在 Google Cloud Platform 的基础设施或任何 Kubernetes 集群上运行相同的应用程序。
Knative 在 Kubernetes API 的基础上直接实现了自动扩缩容和网络功能。然而,谷歌 Cloud Run 没有使用Kubernetes,它实际上是在谷歌基础架构上对 Knative API 的“重新实现”。
本文将介绍 Knative API 的部分功能,以及在 Cloud Run 上尚不支持的功能。
同样的格式、运行时和API
Cloud Run 遵循与 Knative 和 Kubernetes 相同的部署格式:可以通过 OCI 镜像(即所谓的 Docker 镜像)进行部署。
当容器被执行时,它遵循与 Knative Serving 运行时规约 相同的 Cloud Run 容器运行时规约。例如,容器将获得相同的一组环境变量、请求将获得相同的一组 HTTP header。
此外,为了扩展对控制平面的兼容性,Cloud Run REST API 也实现了 Knative Serving 的 API 规范。
在 Cloud Run 上使用 Knative API
这是一个简单的 Knative Service 部署文件。可以使用它直接将服务部署到 Cloud Run:
1 | apiVersion: serving.knative.dev/v1 |
使用下面的命令将 Knative 服务部署到 Cloud Run(像执行 kubectl apply
一样):
1 | gcloud alpha run services replace app.yaml --platform=managed |
这个示例有意省略了在 Cloud Run 上不起作用的部分。现在谈一谈被隐藏的部分。
尚不生效的部分(暂未支持)
Knative Serving API 的某些部分尚未在 Cloud Run 上实现,或者永远不会实现。这些情况通常源于以下原因之一:
- Knative API 依赖于 Kubernetes 某些原语的底层实现(但这些实现在 Cloud Run 上不可用)
- 一些容器参数尚不能被 gVisor 支持
- 正在等待实现
如果查看 Cloud Run REST API 参考中的 Knative RevisionSpec 类型,并搜索“not supported”,将会发现许多 API 字段尚未支持。
不支持的字段
- 卷和卷挂载: Knative 目前甚至不允许在 Kubernetes上挂载任意类型的卷,因此以下选项会受限:
- configMap 卷: Cloud Run 目前没有 ConfigMap 的概念(可以使用环境变量env代替它)
- secret 卷: Cloud Run 没有 Secret 对象(但 Cloud Run 发布了 Secret Manager,用户可以考虑通过这种方式进行集成 Secret)
- envFrom: 实际上,这在 Knative 规范中是建议的支持的,但由于缺乏 ConfigMap/Secrets,因此没有实现。需要在清单中指定环境变量作为文字量进行传递。
- liveness/readiness 探针: 实际上可以做到,但似乎尚未实现。在 Knative 中还有关于删除探针支持的讨论。
- imagePullPolicy: Cloud Run 有一种高效的处理镜像的方式,实际上在新容器启动时并不会从镜像库中拉取镜像。
- securityContext: 指定entrypoint的 UID。这可能可以实现。
不支持的 API 规范
Knative 在配置服务的许多方面(自动缩放、可见性)上大量使用Kubernetes 注释 和标签。但这些注释在 Knative API 规范中没有定义,因此,Cloud Run 可能会将未实现的注释视为自由格式的键值对并悄悄忽略它们。
autoscaling.knative.dev/minScale
:目前还不支持,因为 Cloud Run 在一段时间内处于不活跃状态时总是将应用程序缩减到 0。2021年4月更新:Cloud Run 现在通过此注释支持实例预热。为了避免冷启动,这些实例保持活跃状态,并以较低的价格计费。
autoscaling.knative.dev/maxScale
:支持设置 Cloud Run 上的容器实例的最大数量。serving.knative.dev/visibility
:设置服务是否可以外部访问,目前不支持,因为所有的 Cloud Run 服务都拥有一个公共路由(域名格式:*.run.app
)。但可以使用 Cloud IAM 权限绑定进行授权。
相同 API 的不同效果
- 标签: Cloud Run API 与 Kubernetes 标签不完全兼容。例如,
example.com/foo
在 Kubernetes 中是一个有效的,但在 Cloud Run API 中不允许。相反,它支持 GCP 资源的标签格式。 - serviceAccountName: 在 Knative 中,这指的是 Kubernetes 服务帐户。但在 Cloud Run 中,它是 GCP 服务帐户电子邮件地址。所以使用语法不同。
- 资源的 requests 和 limits: 虽然 requests/limits 有助于在 Kubernetes 集群中进行 burst 操作,但 Cloud Run 将使用 gVisor 沙箱中指定的 CPU 和内存规格来提供服务,因此
requests
实际上不会起作用。 - CPU限制: Cloud Run 目前仅支持 1 或 2 个 CPU(可能会更改),并且不支持小数的核数规格(例如
500m
)。
结论
来自译者:Cloud Run 与 Knative 的实现机制并不完全相同,甚至会有 API 层面的不兼容,但在声明文件上又有很大的相似性。
对于一些用户来说,这些差别可能影响程度不高,那就可以使用 gcloud run services replace
或 Terraform 在 Google Cloud Run 上进行自动化部署。
但考虑到对一些特性上的依赖,某些用户仍期望使用 Knative,Google Cloud 仍然提供了 Knative 托管版 Cloud Run for Anthos,用户可以在 GKE 上运行自己的 Knative。
【译】Google Cloud Run 和 Knative 真的一样吗