Kubernetes设计和开发四大基本原则

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 作者介绍:Saad Ali 是来自Google的高级软件工程师,致力于开源Kubernetes项目。他于2014年12加入该项目并负责Kubernetes存储和volume子系统的开发。他还担任Kubernetes存储兴趣小组的负责人,同时也是CSI(容器存储接口)的协同开发者和maintainer。

作者介绍:Saad Ali 是来自Google的高级软件工程师,致力于开源Kubernetes项目。他于2014年12加入该项目并负责Kubernetes存储和volume子系统的开发。他还担任Kubernetes存储兴趣小组的负责人,同时也是CSI(容器存储接口)的协同开发者和maintainer。在加入Google之前,Saad Ali于微软负责IMAP原型开发项目。

Kubernetes正在迅速成为在分布式系统上部署工作负载的事实标准。在这篇文章中,笔者将通过揭示其设计的一些原则,帮助你更深入地了解Kubernetes。

1、要声明式而不要命令式

一旦你学会在Kubernetes开源编排引擎上部署第一个工作负载(pod),就会遇到Kubernetes的第一个原则:Kubernetes API是声明性的而不是命令式的。

在命令式API中,你可以直接发出服务器要执行的命令,例如: “运行容器”、“停止容器”等。在声明性API中,你声明系统要执行的操作,系统将不断向该状态驱动。   

可以想象成手动驾驶和自动驾驶系统。

因此,在Kubernetes中,你创建一个API对象(使用CLI或REST API)来表示你希望系统执行的操作。系统中的所有组件都会向该状态发展,直到删除该对象。

例如,如果要调度容器化工作负载,不是发出“运行容器”命令,而是创建描述所需状态的API对象、pod:

创建后,此对象在API服务器上保留:

如果容器由于某种原因崩溃,系统将重新启动容器。

要终止容器,请删除pod对象:

为什么要声明式而不要命令式?

声明式API使系统更加健壮。

在分布式系统中,任何组件都可能随时出现故障。当组件恢复时,需要弄清楚要做什么。

使用命令式API时,崩溃的组件可能在它关闭时错过了一个调用,并且需要一些外部组件在它恢复时“赶上”。但是使用声明式API,组件只需查看API服务器的当前状态,即可确定它需要执行的操作(“啊,我需要确保此容器正在运行”)。

这也被描述为“水平触发”而不是“边缘触发”。在边缘触发系统中,如果系统错过“事件”(“边缘”),则必须重放事件以便系统恢复。在水平触发系统中,即使系统错过了“事件”(可能是因为它已经关闭),当它恢复时,它可以查看信号的当前状态并相应地做出响应。

因此,声明式API使Kubernetes系统对组件故障更加健壮。

  • 2、
没有隐藏的内部API

如果你了解各种Kubernetes组件的工作原理,你会遇到Kubernetes的下一个原则:控制平面是透明的,因为没有隐藏的内部API。

这意味着Kubernetes组件用来交互的API和你用来与Kubernetes交互的API相同。结合第一个原则(Kubernetes API是声明式的),这意味着Kubernetes组件只能通过监控和修改Kubernetes API来交互。

让我们通过一个简单的例子来说明这一点。为了启动容器化工作负载,你可以在Kubernetes API服务器上创建一个pod对象,如上所示。

Kubernetes调度程序根据可用资源确定运行pod的最佳节点。调度程序通过为新pod对象监控Kubernetes API服务器来完成此操作。当新的未调度的pod被创建时,调度程序将运行其算法为这个pod查找最佳节点。在调度pod之后(已为pod选择了最佳节点),调度程序不会去告诉所选节点要启动pod。请记住,Kubernetes API是声明式的,内部组件使用相同的API。因此,调度程序更新pod对象中的NodeName字段以指示已经调度该pod。

kubelet(在节点上运行的Kubernetes代理)监控Kubernetes API(就像其他Kubernetes组件一样)。当kubelet看到具有与自身对应的NodeName字段的pod时,它知道改pod已经被调度且必须启动它。一旦kubelet启动了pod,它就会继续为pod监控容器状态,并且只要相应的pod对象继续存在于API服务器中,就会一直让容器保持运行。

删除pod对象后,Kubelet会明白不再需要容器,并终止它。

为什么没有隐藏的内部API?

让Kubernetes组件使用相同的外部API使得Kubernetes可组合和可扩展。

如果由于某种原因,Kubernetes的默认组件(例如,调度程序)不足以满足你的需求,你可以将其关闭并将其替换为自己的使用相同API的组件。

此外,如果你需要的功能尚不可用,则可以使用公共API轻松编写组件以扩展Kubernetes功能。

  • 3、
在用户所在的位置满足他们

Kubernetes API允许存储工作负载可能感兴趣的信息。例如,Kubernetes API可用于存储秘密或配置映射。秘密可以是你在容器镜像中不想要的任何敏感数据,包括密码、证书等。配置映射可以包含应独立于容器镜像的配置信息,例如应用程序启动和其他类似参数。

由于上面定义的没有隐藏的内部API的第二个原则,可以修改在Kubernetes上运行的应用程序以直接从Kubernetes API服务器获取秘密或配置映射信息。但这意味着你需要修改应用程序以意识到它是在Kubernetes中运行。

这就是Kubernetes的第三个原则:在用户所在的位置满足他们。也就是说,Kubernetes不应要求重写要在Kubernetes上运行的应用程序。

例如,许多应用程序接受秘密和配置信息作为文件或环境变量。因此,Kubernetes支持将秘密和配置映射作为文件或环境变量注入pod。

为什么要这么做?
通过进行设计选择,最大限度地减少在Kubernetes上部署工作负载的障碍,Kubernetes可以轻松地运行现有工作负载,而无需重写或大幅改变它们。

  • 4、
工作负载可移植性

一旦在Kubernetes上运行无状态工作负载,下一步自然就是尝试在Kubernetes上运行有状态工作负载。Kubernetes提供了一个功能强大的卷插件系统,可以将许多不同类型的持久存储系统与Kubernetes工作负载一起使用。

例如,用户可以轻松地请求将Google Cloud Persistent Disk安装到特定路径的pod中:

创建此pod时,Kubernetes将自动负责将指定的GCE PD挂载到pod被调度到的节点,并将其挂载到指定的容器中。然后,容器可以在容器或pod的生命周期之外写入GCE PD被挂载到持久数据的路径。

此方法的问题在于pod定义(pod YAML)直接引用Google Cloud Persistent Disk。如果此pod已部署在非Google Cloud Kubernetes集群上,则无法启动(因为GCE PD无法使用)。

这是另一个Kubernetes原则的用武之地:工作负载定义应该可以跨集群移植。用户应该能够使用相同的工作负载定义文件(例如相同的pod yaml)来跨不同的集群可以部署工作负载。

理想情况下,上面指定的pod甚至应该可以在没有GCE PD的集群上运行。为了实现这一目标,Kubernetes引入了PersistentVolumeClaim(PVC)和PersistentVolume(PV)API对象。这些对象将存储实现与存储使用分离。

PersistentVolumeClaim对象用作用户以与实现无关的方式请求存储的方法。例如,用户可以创建PVC对象来请求100 GB的ReadWrite存储,而不是请求特定的GCE PD:

Kubernetes系统将此请求与来自包含PersistentVolume对象的可用磁盘池中的卷匹配,或自动配置新卷以满足请求。无论哪种方式,用于Kubernetes集群部署工作负载的对象都可以跨集群实现移植。

为什么要有工作负载可移植性?

这种工作负载可移植性原则突出了Kubernetes的核心优势:与操作系统使应用程序开发人员不必担心底层硬件的细节一样,Kubernetes将分布式系统应用程序开发人员从底层集群的细节中解放出来。使用Kubernetes,分布式系统应用程序开发人员不必被锁定到特定的集群环境。针对Kubernetes部署的应用程序可以轻松地部署到本地和云环境中的各种集群,而无需对应用程序或部署脚本进行特定于环境的更改(Kubernetes端点除外)。

  • 5、
结论

由于这些原则,Kubernetes更强大,可扩展,可移植且易于迁移。这就是Kubernetes迅速成为在分布式系统上部署工作负载的行业标准的原因。

本文转移K8S技术社区-Kubernetes设计和开发四大基本原则

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
6月前
|
Kubernetes 开发工具 Docker
微服务实践k8s与dapr开发部署实验(2)状态管理
微服务实践k8s与dapr开发部署实验(2)状态管理
108 3
微服务实践k8s与dapr开发部署实验(2)状态管理
|
1月前
|
Kubernetes Docker 微服务
微服务实践k8s&dapr开发部署实验(1)服务调用(一)
微服务实践k8s&dapr开发部署实验(1)服务调用(一)
49 2
|
1月前
|
Kubernetes JavaScript 前端开发
k8s学习--chart包开发(创建chart包)
k8s学习--chart包开发(创建chart包)
|
1月前
|
Kubernetes Docker 微服务
微服务实践k8s&dapr开发部署实验(1)服务调用(二)
微服务实践k8s&dapr开发部署实验(1)服务调用(二)
51 0
|
3月前
|
Kubernetes Docker Perl
在K8S中,如果是因为开发写的镜像问题导致pod起不来该怎么排查?
在K8S中,如果是因为开发写的镜像问题导致pod起不来该怎么排查?
|
3月前
|
Kubernetes 网络协议 Python
运维开发.Kubernetes探针与应用
运维开发.Kubernetes探针与应用
132 2
|
3月前
|
Kubernetes Cloud Native 搜索推荐
探索云原生技术:Kubernetes在现代应用部署中的角色打造个性化移动体验:从开发到操作系统定制
【7月更文挑战第31天】本文深入探讨了云原生技术的核心组件之一——Kubernetes,并分析了其在现代云计算环境中的关键作用。通过实际代码示例和案例分析,文章揭示了Kubernetes如何优化资源管理、提高部署灵活性以及增强服务的可靠性。读者将获得对Kubernetes操作实践的直观理解,并认识到采用云原生架构对企业数字化转型的推动力。
61 0
|
6月前
|
Kubernetes Cloud Native Go
Golang深入浅出之-Go语言中的云原生开发:Kubernetes与Docker
【5月更文挑战第5天】本文探讨了Go语言在云原生开发中的应用,特别是在Kubernetes和Docker中的使用。Docker利用Go语言的性能和跨平台能力编写Dockerfile和构建镜像。Kubernetes,主要由Go语言编写,提供了方便的客户端库与集群交互。文章列举了Dockerfile编写、Kubernetes资源定义和服务发现的常见问题及解决方案,并给出了Go语言构建Docker镜像和与Kubernetes交互的代码示例。通过掌握这些技巧,开发者能更高效地进行云原生应用开发。
186 1
|
6月前
|
Kubernetes Docker 微服务
微服务实践k8s&dapr开发部署实验(3)订阅发布
微服务实践k8s&dapr开发部署实验(3)订阅发布
76 0
|
6月前
|
Kubernetes 监控 安全
「译文」在 K8S/OpenShift 上开发应用程序的 14 种最佳实践
「译文」在 K8S/OpenShift 上开发应用程序的 14 种最佳实践