工程师分享 | Pinterest 如何构建 Kubernetes 平台
技术
作者:才云 Caicloud
译者:bot(才云)
2019-10-11 18:30

近日,Pinterest 工程师团队透露了公司采用 Kubernetes 构建 PaaS 的实践。

为什么选择 Kubernetes?

Pinterest 是一个图片社交平台,拥有庞大的用户群。在过去的几年里,有 3 亿多 Pinner 在 Pinterest 上保存了超过 2000 亿次 Pin,覆盖了超过 40 亿个 Board。

为了服务庞大的用户群和内容池,Pinterest 团队已经开发了数千种服务,包括只占用少量 CPU 的小型服务和占据整个 VM 机群的庞大整体式服务,其中也涉及各种不同框架的批处理作业,对 CPU、内存等造成了巨大压力。

为了支持这些多样化的工作负载,Pinterest 的基础架构团队面临多个挑战:

  • 工程师在启动工作负载时缺乏统一经验。Pinterest 的无状态服务、有状态服务和批处理作业由完全不同的技术堆栈进行部署和管理。这给工程师们创造了陡峭的学习曲线,并给基础设施团队带来了巨大的维护负担;
  • VM 管理为基础设施团队带去巨大维护压力。诸如 OS、AMI 升级之类的简单操作可能需要数周至数月的时间,这个过程会对工作的工作负载造成或多或少的影响;
  • 工程师难以在割裂的管理系统之上构建基础设施治理工具。事实上在 Pinterest,确定机器的归属和目标机器能否安全回收都是件困难的事。

基础架构优先级(服务可靠性、开发人员生产力和基础设施效率)

出于长远性考虑,早在 2017 年,Pinterest 的云管理平台团队就开始尝试使用 Kubernetes。2017 年上半年,他们将大部分生产工作负载(包括核心 API 和 Web)进行了容器化,并通过构建产品集群在其上运行实际工作负载,对当时已有的不同容器编排系统进行了广泛评估。

到 2017 年底,Kubernetes 凭借其灵活性和广泛的社区支持被 Pinterest 选中

截至目前,Pinterest 已经基于 Kops 构建了自己的集群引导工具,并将现有的基础架构组件集成到 Kubernetes 集群中,如网络、安全性、指标、日志记录、身份管理和流量。

Pinterest 团队引入了量身定制的 CRD 对工作负载进行建模,同时向开发人员隐藏运行时的复杂性。接下来,Pinterest 将专注于优化 Kubernetes 集群的稳定性、可伸缩性和易用性。

st 将专注于优化 Kubernetes 集群的稳定性、可伸缩性和易用性。

Pinterest 的 K8s 之旅

对 Pinterest 团队来说,采用 Kubernetes 意味着诸多风险,它不仅需要支持 Pinterest 如此大规模的工作负载,还要打造工程师们喜欢的平台。

作为一个大型组织,Pinterest 在基础架构工具上进行了大量投资,如处理证书和密钥分发的安全性工具、启用服务注册和发现的流量组件以及传输日志和指标的可见性组件。这些组件大多依赖经验构建,Pinterest 团队希望将其集成到 Kubernetes 中,而不是重新造轮子。

另一方面,Kubernetes 的本机工作负载模型涵盖了 Deployment、Job 和 Daemonset,但是团队需要更多的工作负载模型。可用性问题成了采用 Kubernetes 过程中的巨大障碍。例如,团队中曾有服务开发人员抱怨缺少或错误配置的入口弄乱了他们的端点,负责批量处理的工程师也有过利用模板工具生成数百份副本,结果调试时宛如噩梦的经历。

考虑到对工作负载的运行时支持也在不断发展,在同一 Kubernetes 集群上支持不同版本是非常困难的。试想一下,如果你需要面对不同版本的运行时,还要为它们升级、修 Bug,这之中的繁琐程度难以想象。

CRD为了给工程师以更轻松的方式采用 Kubernetes,并使基础设施开发更快、更流畅,Pinterest 团队设计了自己的自定义资源定义(CRD)。

  • 将各种本地 Kubernetes 资源捆绑在一起,以便它们作为单个工作负载工作。例如,PinterestService 资源将 Deployment、Service、Ingress 和 Configmap 放在一起,因此工程师将无需担心为其服务设置 DNS;
  • 为应用程序注入必要的运行时支持。工程师只需要关注业务逻辑的 PodSpec,而 CRD 控制器就会将必要的 Sidecar、初始化容器、环境变量和 Volume 注入其 PodSpec 中。这为工程师提供了开箱即用的体验;
  • CRD 控制器还对本机资源进行生命周期管理,并处理可见性和可调试性。这包括但不限于协调所需规范和实际规范、CRD 状态更新和事件记录。如果没有 CRD,工程师必须管理更大的资源集,易导致出错。

下图是 PinterestService 和控制器转换的本机资源的示例:

如图所示,为了支持用户的容器,这里需要插入一个初始化容器和几个 Sidecar 来提高安全性、可见性和网络流量。此外,Pinterest 团队还在批处理作业中引入了对配置映射模板和 PVC 模板的支持,以及许多用于跟踪标识、资源利用率和垃圾回收的环境变量。

应用程序部署工作流程

上图显示了如何将 Pinterest 自定义资源部署到 Kubernetes 集群:

  • 开发人员通过 CLI 和 UI 与 Kubernetes 集群进行交互;
  • CLI/UI 工具从 Artifactory 检索工作流配置 YAML 文件和其他构建属性(例如版本 ID),并将它们发送到 Job Submission Service;
  • Job Submission Service 是通往各种计算平台(包括 Kubernetes)的网关。用户身份验证、配额执行和部分 Pinterest CRD 配置验证都在此处进行;
  • CRD 通过 Job Submission Service 验证后,将其发送到 Kubernetes API;
  • CRD 控制器监视所有自定义资源上的事件。它将 CR 转换为 Kubernetes 本地资源,将必要的辅助工具添加到用户定义的 Pod 中,设置适当的环境变量,并执行其他必要的处理工作,以确保用户的应用程序容器具有足够支持;
  • 然后 CRD 控制器将生成的本机资源写回到 Kubernetes API,以便调度程序可以选择它们并开始运行。

注:这是一个预发布的部署工作流,可用于基于 Kubernetes 的新计算平台的早期采用者。该团队正在将此工作流集成到他们的 CI/CD 平台中,以便为他们的工程师创建一个更干净的服务。

自定义资源类型

根据 Pinterest 的特定需求,技术团队设计了以下 CRD,以适合不同的工作流程:

  • PinterestService 是长期运行的无状态服务,许多核心系统基于一组此类服务;
  • PinterestJobSet 为运行完成的批处理作业建模。Pinterest 中一个非常常见的模式是多个作业并行运行相同的容器,每个作业占用了一部分工作负载,而又彼此不依赖;
  • PinterestCronJob 是本机 cron 作业的封装,支持 Pinterest 特有的安全、流量、日志和指标;
  • PinterestDaemon 目前仅限于与基础设施相关的守护进程;
  • PinterestTrainingJob 封装了 TensorFlow 和 Pytorch 作业,提供与所有其他 CRD 相同的运行时支持。由于 Pinterest 大量使用 TensorFlow 和其他机器学习框架,因此围绕它们构建专用的 CRD 是有意义的。

此外,Pinterest 技术团队还正在构建 PinterestStatefulSet,它将很快用于存储和其他有状态系统。

运行时支持

当一个应用程序 Pod 在 Kubernetes 上启动时,它会自动获得一个证书来标识自己。此证书用于通过 mTLS 访问秘密存储或与其他服务对话。

同时,配置管理初始化容器和守护程序将确保在应用程序容器启动之前下载所有必需的依赖项。当应用程序容器准备就绪时,流量 Sidecar 和 Daemon 会将 Pod IP 注册到 Zookeeper,使客户端可以发现它。在 Pod 启动之前,它就已经为 Pod 建立了联网。

以上是 Pinterest 内部对服务工作负载的典型运行时支持的示例。对于其他工作负载类型,细节可能存在差异,但它们均以 Pod 级 Sidecar、节点级 Daemonset 或 VM 级 Daemon 的形式出现。

未来的工作

当前,Pinterest 正在所有 Kubernetes 集群上运行混合工作负载。为了支持不同大小和类型的工作负载,技术团队正在下列方向做积极探索:

  • 将大型应用程序分散到不同的集群上,提高可伸缩性和稳定性;
  • 集群稳定性、可伸缩性和可视性,确保应用程序达到其 SLA;
  • 资源和配额管理,以确保应用程序不会相互干扰,集群规模得到控制;
  • 新的 CI/CD 平台,支持 Kubernetes 上的应用程序部署。

原文地址:https://medium.com/pinterest-engineering/building-a-kubernetes-platform-at-pinterest-fb3d9571c948

1536 comCount 0