实用至极,我从Kubernetes中学习到的5个架构经验
「架构」这个词不同的人有不同的理解,有人觉得「架构」就好像一种工程师努力追寻的武学秘籍,也有人觉得「架构」就是画 PPT 或者技术大会上吹牛。
确实,学架构不像学编程,有许多教程可用,没有教程类的书教我们如何做架构。脱离具体的业务场景和系统,谈架构总是让人感觉很虚,所以一直想找个系统作为依托,写写自己对架构的思考。
在基础研发领域,Kubernetes 的架构有非常多的借鉴之处。一方面它的许多设计是 Google 内部多年积累的最佳实践的沉淀,是 Borg,Omega 演进的结果。另外一方面,它是一个综合的系统工程,不是一个单纯的技术工程。
系统工程的特点是任何一部分单独抽取出来,貌似都没有太高的技术含量,但它的复杂度在于如何让各个子系统优雅的结合在一起,对外表现出统一的设计思想,而不是堆砌和拼凑,如何设计对用户更友好,如何设计才更利于扩展。这也意味着,它的许多设计和选择没有最优解,是一种优劣权衡的结果。而我们设计的大多数系统,都是这类型的系统,所以更值得借鉴。
Kubernetes 本身的架构在这里不细说,网上的资料非常多,如果不熟悉大家检索一下。这里抽几个值得思考和借鉴的点简单分析下。
设计思想之声明式 VS 命令式
我们大多数系统的设计都是命令式的,或者叫过程式。系统的组件以及层级之间,通过一层一层调用和封装,组成一个大的系统。组件和层级之间都是基本都是强依赖关系,即便是要设计成弱依赖,也是代码显示完成的,比如调用超时后设置个默认值,也只是一种权宜之计。这种方式带来如下问题:
组件和层级间耦合严重,重构代价高昂,只能依赖工程师的代码抽象能力实现一定程度的解耦。
系统调用边界不可控,A 调用 B,但不知 B 又依赖什么组件和服务,可能很小一个错误,导致整个大的任务失败,并且很难重试和回滚。
以一个部署系统为例,这个系统需要下载安装包,推送到各服务器上(或者从各服务器上拉取,道理一样),从集群中摘掉该节点,关闭旧的进程,部署,启动新的进程,再加入到集群中对外服务。这个还是一个简化了的流程。这个流程中,任何一步都可能出现失败,超时等问题。如果是通过调用的方式完成,就需要有一个总的超时时间,然后各步骤也需要超时,重试机制,很难有一个优雅的方式处理。如果其中一步出错,重试几次后也失败,只能让整个任务失败,进行人工排查错误,如果贸然重试任务可能导致状态不一致。
而 Kubernetes 通过声明式方式实现的 Controller,则比较优雅的解决了这个问题。每个组件都只需要和 Etcd 这样的状态中心交互,完成自己的任务后把状态更新到 ETCD 中即可。如果失败则反复重试,直到失败条件解除。虽然任务的完成时间不可控,但可达到最终一致。
如果想进一步了解可以深入学习 Kubernetes 的 Pod,Service,ReplicaSet,Deployment,Autoscaling 不同组件之间的关系以及 Controller 的实现。
当然,申明式设计并不适合所有的系统,可以思考下哪些场景下比较适合这种设计。
思考:为什么 Kubernetes 一直没提供重启 Pod 的接口?大家普遍的概念里,一个部署系统,重启应用程序是一个必备功能。
参看这个从 2015 年开始讨论的 Issue:
https://github.com/kubernetes/kubernetes/issues/13488
如何设计出通用的 IAM 机制?
IAM(Identity and Access Management) 是所有企业级应用服务平台必须要考虑的功能之一。本想通过和各公有云的 IAM 机制的比较,来解析 Kubernetes 对安全认证机制的抽象和实现,学习和思考如何在自己的系统中设计出通用的 IAM 机制,但这里受限于篇幅,就简单分析下。
IAM 要解决的关键问题是:
身份认证:通过什么凭证来证明自己的身份,比如 用户名密码,Token,证书等。
访问权限控制:有哪些资源,不同的资源有什么操作(对应权限),如何定义权限集合,又如何和用户关联。
为了方便定义权限集合,一般需要引入 Role 的概念,一个 Role 对应一个权限集合,另外为了方便批量操作,会引入 Group 的概念把用户做一个集合。这个大体就是 Kubernetes RBAC(Role-based access control)的设计思路。
IAM 需要解决的另外一个问题是服务器端调用的身份认证问题。终端用户使用时,可以通过通用的身份凭证来校验用户,但如果两个系统之间需要互相调用呢?一种办法是创建一些系统账号,给比较高的权限,系统之前调用也是使用和终端用户一样的认证机制。带来的问题是这些账号的维护以及凭证的管理,密码等凭证泄露可能带来安全隐患。参考最近的某酒店拖库事件,最直接的原因是数据库地址以及账号密码被误提交到 GitHub,但根本原因是服务之间互相认证的凭证管理问题。
所以 Kubernetes 引入了一个 ServiceAccount 的机制。部署应用的时候,在配置文件中声明该应用拥有某 ServiceAccount 权限,这样 Kubernetes 会自动在容器中生成并挂载 ServiceAccount 的凭证,该应用通过标准 SDK 调用 Kubernetes 的接口的时候会自动使用该凭证,应用中无需配置身份凭证信息。
这个和 AWS 的 AWS Role(AWS IAM 中的 Role 和通常的理解不太一样),GCE ServiceAccount 机制类似,有兴趣的朋友可以深入调研一下。
思考:
为什么 Kubernetes 从最初的 ABAC(Attribute-based access control)演进到了 RBAC?
很多云服务将资源和用户账号关联,主要是为了方便权限控制以及计费。但企业场景下,由于员工离职等原因,可能需要在账号间迁移资源。如何设计 IAM,可以使这种迁移更便捷?
如何通过设计让资源提供方和使用方解耦?
我们的系统中总有许多依赖外部资源的地方,不同的环境,外部资源的供给方式不同,如何通过抽象,让资源供给放对使用方透明?Kubernetes 存储的 Provision 机制是一个典型案例。
Kubernetes 存储的 Provision 机制,将不同云,不同分布式存储系统,提供的存储能力抽象成统一的接口,使用方只需要在配置文件中申明需要多少存储,无需知道具体的资源提供方的信息,由 Kubernetes 系统将需求和供给进行撮合,如果当前供给不足就通过调度系统自动创建新的资源。
这种方式可以最大程度的弥合环境的异构,让应用可以在不同的环境中无缝迁移。
同时 Kubernetes 上的 service-catalog,也通过 Service Broker 的方式给其他服务提供了 Provision 机制。比如应用需要依赖另外一个服务,按照原来的方式,要么应用将依赖服务也一起打包进来,要么让用户手动操作,解决依赖问题。而 Service Broker 的方式是应用只需要声明,如果系统中尚未有类似服务,则会自动创建。
思考:自己开发的应用系统是否有和资源环境的耦合?当前是如何解决的?
复杂系统如何提供自定义机制?
任何一个软件系统本身都是对一种通用模式的沉淀,但任何通用的模式都会遇到特例,环境和场景的变化,新的技术的出现等都会给原有系统带来挑战。这时候设计一种扩展机制,以应对变化成为了必选项。
Kubernetes 提供了以下扩展能力:
Admission Kubernetes 的 Admission 属于其安全系统的一部分,通过插件机制提供了一系列拦截器,以实现自定义的安全策略以及默认属性的注入。可以利用它来设计自己的安全策略以及运维规范。
CloudProvider 给不同的云厂商的扩展
Volume 存储的扩展,和前面说的 Provision 机制相关。
CNI(Container Network Interface)网络扩展,实现不同的网络方案。
CRD(CustomResourceDefinition) Kubernetes 的 CRD 是它的声明式设计的优势集中体现,有了这种扩展能力后,几乎可以把整个 DevOps 平台中涉及的工具统一纳入 Kubernetes 中,通过 Kubernetes 提供统一的控制平面,屏蔽后端工具的差异。
每一种扩展,都有不同的演进历程,当前的成熟度也不同。并且扩展的具体实现方式和编程语言也有关系。Kubernetes 是 Go 实现的,它的动态加载机制还不成熟,所以 Kubernetes 中的扩展大多数都是通过标准化的命令行调用或者 RPC 接口实现的。
思考:列举下自己知道的插件式系统,分析下它们的插件是如何抽象的,如何实现的,不同的编程语言有什么差异。
如何用代码生成机制减少重复代码,提高开发效率?
Kubernetes 中大量使用了代码生成机制,一方面是因为 Kubernetes 是用 go 语言开发的,go 当前不支持泛型,也无法支持像 java 那样的动态字节码生成技术,所以很多情况需要依赖静态代码生成机制。
另外一方面 Kubernetes 的 RESE API 设计的非常优雅,SDK 这种完全可以自动生成。Kubernetes 中的代码生成工具都已经单独抽取成独立的项目了,了解一下它的运作方式,对自己设计和架构系统也很有帮助。
思考:如何设计出便于代码生成的系统?
综合系统如何确定自己的边界?
Kubernetes 是一个综合系统,这样的系统在演化过程中会很容易膨胀成一个无所不能的系统。Kubernetes 又是如何控制自己的膨胀的「欲望」,探索和界定自己的边界的?这个问题是一个值得深入探讨和思考的问题。
后记
Kubernetes 中可以琢磨研究的点实际上很多,上面只是列举了几点,也只是抛出了问题,但并没有给出详细分析。
这里推荐一个 Kubernetes 项目维护者张磊的专栏《深入剖析 Kubernetes》,看了他的课程,非常完备,可以兼顾初学者以及想进一步深入了解 Kubernetes 的朋友。
我已经听了几期,张磊兄从最初的 Docker 诞生以及演进开始分析,有技术,有故事,普通话也很好听,娓娓道来,兼顾趣味性与知识性,即便是老手也能有新的收获。
希望大家在听的过程中,一遍学习 Kubernetes 的特性,一遍思考它的架构。学习的第一境界是学会使用,第二境界是知道它的实现方式,第三境界是可以做到居高临下,把学习到的点用到自己的创造过程中去。
订阅立享双重福利:
福利 1:限时优惠¥68,原价¥99,9 月 8 日恢复原价。
福利 2:每邀请一位好友订阅,可获得 24 元现金返现,随时可取。(流程:极客时间 - 我的 - 分享有赏)
扫描下方二维码,即可订阅
点击 阅读原文,可免费试读专栏。
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
随时掌握互联网精彩
- 1 准确把握守正创新的辩证关系 7949449
- 2 中国黄金原董事长家搜出大量黄金 7994767
- 3 空调英文不会男生盯着考场空调看 7898708
- 4 消费品以旧换新“加速度” 7795223
- 5 被铁路售票员的手速惊到了 7686905
- 6 网红赤木刚宪爆改赵露思 7529952
- 7 县委原书记大搞“刷白墙”被通报 7468682
- 8 山姆代购在厕所分装蛋糕 7394086
- 9 马龙刘诗雯穿正装打混双 7270185
- 10 刘强东提前发年终奖 7141482