Kubernetes最初是怎么被设计的

130 阅读4分钟

概述

Kubernetes proposal 包含了几篇架构方面的文档,可以读了之后一起总结。

不同角度的设计

极简抽象版

architecture/architecture.md

  • 控制面:
    • RESTful API Server,所有的API必须是显式地表示为一个HTTP接口,client-go等的通信本质上也是基于HTTP API的
    • Scheduler
    • Controller Manager
  • 外部存储:etcd,有且仅有api-server能直接操纵etcd,从某种程度上说,api-server是etcd的一个proxy
  • 最核心管控面:kubelet,没有kubelet,api-server就仅仅只是一个CRUD Server,kubelet才是真正决定一个Pod能不能运行在Node上的最高组件,从这个角度看,kubelet的重要性要大于api-server
  • 附件(add-on):
    • DNS
    • Ingress
    • Monitor
    • GUI

Roadmap版

architecture/architectural-roadmap.md

Roadmap 不仅要考虑Kubernetes自身的设计,还要考虑到Kubernetes上层和周边的生态系统。

arch-roadmap-1.png

使用经典分层架构,从下往上依次是:

  1. Nucleus(核心层):Kubernetes 自身的特性
  2. Application Management Layer(应用管理层):包含部署和路由2个方面,对应于Kubernetes提供的Deployment/StatefulSet和kube-proxy
  3. Governance Layer(管理层):包含高级自动化和策略增强等方面,对应于多租户能力,VPA/HPA,Quota,网络和存储策略
  4. Interface Layer(接口层):提供了给用户的接口,例如kubectl、client-go、GUI等
  5. Ecosystem(生态):看CNCF的landscape,这可太多了

对于Kubernetes这种平台的平台,其实分出明显的层次是很难的,Kubernetes 希望自身称为OS内核一样的地位,但从多年后的视角看,Kubernetes 真正重要的是它给出了一种Cloudnative的实现,并且确定了声明式API,不可变基础设施,运维自动化等一系列云原生共识。

随着Kubernetes自身核心组件的成熟,它可以解决大部分中小企业的运维问题,但是对于更大规模的企业,Kubernetes本身正逐渐成为一种设计规约,也许有组件会替代掉它的某些部分,但是不可能违背它确立的精神。

Component和Interface

Component:

  • APIServer
  • etcd:Kubernetes唯一存储
  • Scheduler + scheduler framework
  • Kubelet
  • KubeDNS:将集群内部的域名解析为IP
  • Service:将一个或多个Deployment暴露
  • Ingress:将外部HTTP请求路由到Service上
  • Mutating/Validating Webhook:表现为mutatingwebhookconfigurations/validatingwebhookconfigurations对象,控制Pod对象的准入和修改

Interface:

  • CRI:grpc接口
  • CNI:1.0版本为二进制形式,2.0版本基于grpc接口
  • CSI:grpc接口
  • CRD:Kubernetes拓展性的核心

原则(宣言)

关于API:

  • 所有的API都是声明式的
  • 所有的Object都是互补的和可组合的,而不是黑盒封装
  • 控制面完全透明,没有内部API
  • API操作不会因为对象数量增加而爆炸,换句话说,就是要有常用索引
  • 对象状态可以根据历史操作进行100%复现
  • 低阶API要为高阶API设计,高阶API要面向需求设计,而不是面向实现设计

关于控制逻辑:

  • 功能应该是水平触发的(epoll),因为可以避免可能的miss,边缘触发可以作为优化手段
  • 假设世界是开放的,例如用户可以删除一个statefulset下的Pod,而不会让statefulset感到惊奇
  • 不要试图为Object定义一个全能的状态机(因为对象的status字段很多,状态数量是爆炸的)
  • 不要假设给其他组件的指令不会被覆盖或者拒绝,也就是说exception永远可能发生
  • 组件具有自愈性
  • 组件行为可以优雅地降级

关于架构

  • 只有api-server可以和存储交互,scheduler不行,kubelet也不行
  • 一个node不应该影响整个集群
  • 组件应该执行最新一次他被要求执行的(由于网络中断等异常)
  • 所有组件应该在内存中缓存数据,然后watch更新
  • watch要比polling(轮询)更好

附录

Eric Raymond 的 17个Unix哲学

  1. Rule of Modularity
  2. Rule of Clarity
  3. Rule of Composition
  4. Rule of Separation
  5. Rule of Simplicity
  6. Rule of Parsimony:写小程序而不是大程序,小程序不仅易修改,而且删除起来也损失小
  7. Rule of Transparency
  8. Rule of Robustness
  9. Rule of Representation
  10. Rule of Least Surprise
  11. Rule of Silence:程序正常的时候应该安静
  12. Rule of Repair:程序失败的时候应该吵闹
  13. Rule of Economy:程序员的时间远比机器时间重要
  14. Rule of Generation:不要手动重复写程序,而是生成代码
  15. Rule of Optimization:先原型后优化
  16. Rule of Diversity:程序可以被用在更广泛的场景,而不是局限
  17. Rule of Extensibility