炼数成金 门户 大数据 虚拟化 查看内容

实用至极,我从Kubernetes中学习到的5个架构经验

2018-9-7 14:20| 发布者: 炼数成金_小数| 查看: 29501| 评论: 0|原作者: jolestar|来自: 聊聊架构

摘要: 「架构」这个词不同的人有不同的理解,有人觉得「架构」就好像一种工程师努力追寻的武学秘籍,也有人觉得「架构」就是画 PPT 或者技术大会上吹牛。确实,学架构不像学编程,有许多教程可用,没有教程类的书教我们如 ...

存储 安全 Hadoop 架构 Kubernetes

「架构」这个词不同的人有不同的理解,有人觉得「架构」就好像一种工程师努力追寻的武学秘籍,也有人觉得「架构」就是画 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 的 REST API 设计的非常优雅,SDK 这种完全可以自动生成。Kubernetes 中的代码生成工具都已经单独抽取成独立的项目了,了解一下它的运作方式,对自己设计和架构系统也很有帮助。

思考:如何设计出便于代码生成的系统?
综合系统如何确定自己的边界?
Kubernetes 是一个综合系统,这样的系统在演化过程中会很容易膨胀成一个无所不能的系统。Kubernetes 又是如何控制自己的膨胀的「欲望」,探索和界定自己的边界的?这个问题是一个值得深入探讨和思考的问题。

声明:文章收集于网络,如有侵权,请联系小编及时处理,谢谢!

欢迎加入本站公开兴趣群
软件开发技术群
兴趣范围包括:Java,C/C++,Python,PHP,Ruby,shell等各种语言开发经验交流,各种框架使用,外包项目机会,学习、培训、跳槽等交流
QQ群:26931708

Hadoop源代码研究群
兴趣范围包括:Hadoop源代码解读,改进,优化,分布式系统场景定制,与Hadoop有关的各种开源项目,总之就是玩转Hadoop
QQ群:288410967 

鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

热门频道

  • 大数据
  • 商业智能
  • 量化投资
  • 科学探索
  • 创业

即将开课

 

GMT+8, 2018-11-14 06:18 , Processed in 0.151735 second(s), 25 queries .