kubernetes架构原则与对象设计

这篇文章解析了 Kubernetes 的对象设计。

1. 云计算的演变:从虚拟机到容器

云计算,简单来说,就是把计算资源(比如CPU、内存、存储、网络)放到“云”上,大家按需使用,不用自己买服务器、搭机房。

云计算平台大致经历了两个阶段:

  • 第一阶段:虚拟化平台 (以 OpenStack 为代表)

    • 想象一下,你有一台大电脑,通过虚拟化技术,把它“切”成很多小电脑(虚拟机),每个小电脑可以独立运行不同的应用。
    • 优点: 资源利用率提高了,不用每部署一个应用就买一台服务器。
    • 缺点: 虚拟机的创建和业务代码的部署是分开的,每次部署应用都要先创建虚拟机,再安装各种依赖,比较麻烦。而且,虚拟机的底层环境(操作系统、各种库)可能不一样,维护起来比较头疼。
  • 第二阶段:基于进程的作业调度平台 (以谷歌 Borg 为代表)

    • Borg 是谷歌内部使用的容器集群管理系统,它直接管理进程,而不是虚拟机。
    • 优点: 资源利用率更高,应用部署更快,故障恢复也更快。
    • 缺点: Borg 的设计比较复杂,有一些不太合理的地方,比如:
      • 对象之间的依赖关系太强,不够灵活。
      • 所有容器共享 IP,容易导致端口冲突。
      • 给超级用户添加了太多复杂逻辑,系统变得臃肿。

2. 谷歌 Borg:Kubernetes 的灵感之源

Borg 在谷歌内部发挥了巨大作用,支撑了 Gmail、Google Docs、Web Search 等众多核心业务。

2.1 Borg 的核心特性

  • 高资源利用率: 通过共享服务器,在进程级别进行隔离,充分利用硬件资源。
  • 高可用性: 应用故障时,可以快速恢复,保证服务不中断。
  • 灵活的调度: 可以根据不同的应用需求,灵活地分配资源。
  • 方便易用: 提供了完善的工具,方便用户部署、管理应用。

2.2 Borg 的基本概念

  • Workload(工作负载): 分为两种:
    • prod: 在线任务,比如网站、邮件服务等,对延迟敏感,需要长期运行。
    • non-prod: 离线任务,比如数据分析、批量计算等,可以容忍一定的延迟。
  • Cell(单元): 一个 Cell 包含一个 Borg 集群管理系统,用户不需要关心应用具体跑在哪台机器上,Borg 会自动分配资源、处理故障。
  • Job 和 Task:
    • Job: 用户提交的应用部署请求,包含一个或多个相同的 Task。
    • Task: 运行相同应用程序的副本,Task 的数量就是应用的副本数。
  • Naming(命名): Borg 通过 BNS(Borg Name Service)实现服务发现。例如:50.jfoo.ubar.cc.borg.google.com 表示在名为 cc 的 Cell 中,由用户 uBar 部署的名为 jFoo 的 Job 下的第 50 个 Task。

2.3 Borg 的架构

graph LR
    subgraph Borg
        A[客户端] --> B(Borgmaster)
        B --> C{Scheduler}
        B --> D[Borglet]
        D --> E[应用程序进程]
    end
  • Borgmaster:
    • 处理客户端请求(创建 Job、查询 Job 等)。
    • 维护系统组件和服务状态。
    • 与 Borglet 通信。
  • Scheduler:
    • 负责调度 Task 到合适的机器上。
    • 采用多种优化策略,提高调度效率。
  • Borglet:
    • 部署在每台服务器上的 Agent。
    • 接收 Borgmaster 的指令,管理 Task。

2.4 Borg 的高可用性

  • 应用高可用:
    • 多副本部署,跨故障域(不同机器、机架、电源等)。
    • 控制节点故障时的任务调度速率,避免网络分区误判。
    • 记录详细信息,方便故障排查。
    • 关键原则: 即使 Borgmaster 或 Borglet 挂掉,也不能杀掉正在运行的服务。
  • Borg 系统自身高可用:
    • Borgmaster 多副本设计。
    • 使用简单工具部署 Borg,避免过多外部依赖。
    • 每个 Cell 的 Borg 独立部署,避免相互影响。

2.5 Borg 的资源利用率

  • 混部: 在线任务(prod)和离线任务(non-prod)混合部署,充分利用资源。
    • 空闲时,离线任务可以使用更多资源。
    • 繁忙时,在线任务优先执行。
  • 效果:
    • 98% 的服务器实现了混部。
    • 90% 的服务器运行了超过 25 个 Task 和 4500 个线程。
    • 相比独立部署,混合部署可以节省 20%-30% 的服务器。

2.6 Borg 的调度原理

graph LR
    A[machine] --> B(task)
    B --> C[实际使用资源]
    B --> D[保留资源]
    B --> E[回收资源]
    B --> F[限制资源]
  • 资源回收: 在 task 启动一段时间后,进行资源回收,将保留资源设置为实际使用资源加上一定的安全余量,并定期重新计算。

2.7 Borg 的隔离性

  • 安全性隔离: 早期采用 Chroot jail,后期基于 Namespace。
  • 性能隔离: 采用基于 Cgroup 的容器技术。
    • 在线任务优先级高,离线任务优先级低。
    • 通过抢占式调度,优先保障在线任务性能。
    • 资源分为可压榨(如 CPU)和不可压榨(如内存)两种。

3. Kubernetes:Borg 的开源版本

Kubernetes(K8s)是谷歌开源的容器集群管理系统,是 Borg 的开源版本。

3.1 K8s 的主要功能

  • 基于容器的应用部署、维护和滚动升级。
  • 负载均衡和服务发现。
  • 跨机器和跨地区的集群调度。
  • 自动伸缩。
  • 无状态服务和有状态服务。
  • 插件机制保证扩展性。

3.2 命令式 vs 声明式

  • 命令式系统: 关注“如何做”,需要明确告诉系统每一步做什么。
  • 声明式系统: 关注“做什么”,只需要告诉系统你想要什么,系统会自动完成。

Kubernetes 是一个声明式系统,具有以下特点:

  • 声明式规范:
    • 直接声明:直接告诉系统你的需求。
    • 间接声明:把需求放在特定地方,系统会自动处理。
  • 幂等性: 状态固定,每次操作返回相同结果。
  • 面向对象: 把一切抽象成对象。

3.3 Kubernetes 的核心对象

  • Node: 计算节点的抽象。
  • Namespace: 资源隔离的基本单位。
  • Pod: 应用实例的抽象,包含镜像地址、资源需求等,是 K8s 最核心的对象。
  • Service: 将应用发布成服务,本质上是负载均衡和域名服务的声明。

3.4 Kubernetes 的架构

  • Master Node(主节点):
    • API Server: 暴露 Kubernetes API,是集群的入口。
    • Cluster Data Store (etcd): 存储集群所有数据。
    • Controller Manager: 运行各种控制器,确保集群状态与期望状态一致。
    • Scheduler: 负责将 Pod 调度到合适的节点。
  • Worker Node(工作节点):
    • Kubelet: 管理 Pod 的生命周期,向 Master 节点汇报状态。
    • Kube-proxy: 负责网络,维护网络规则,执行连接转发。
    • Container Runtime: 负责运行容器(如 Docker)。

3.5 Kubernetes 的其他组件

  • etcd: 分布式 key-value 存储,用于服务发现、共享配置和一致性保障。
  • APIServer: 提供集群管理的 REST API 接口,包括认证、授权、准入控制等。
  • Controller Manager: 确保集群的真实状态与用户定义的期望状态一致。
  • Scheduler: 监控未调度的 Pod,选择最佳节点进行调度。
  • Kubelet: 从不同源获取 Pod 清单,并按需求启停 Pod。
  • Kube-Proxy: 监控集群中用户发布的服务,并完成负载均衡配置。

3.6 Kubernetes 的常用 Add-ons

  • kube-dns: 提供 DNS 服务。
  • Ingress Controller: 提供外网入口。
  • Metrics Server: 提供资源监控。
  • Dashboard: 提供 GUI。
  • Fluentd-Elasticsearch: 提供日志采集、存储与查询。

3.7 kubectl:Kubernetes 的命令行工具

  • kubectl: 允许用户以命令行的方式与 Kubernetes 交互。
  • kubeconfig: 配置文件,包含 apiserver 地址、用户信息等。
  • 常用命令:
    • kubectl get po -oyaml -w:查看对象,输出 yaml 格式,并 watch 变化。
    • kubectl describe po <pod_name>:展示资源的详细信息和相关 Event。
    • kubectl exec -it <pod_name> bash:进入运行的容器。
    • kubectl logs <pod_name>:查看 pod 的标准输出。

4. 深入理解 Kubernetes

4.1 云计算的传统分类

  • IaaS (Infrastructure as a Service): 提供基础设施,如虚拟机、存储、网络。
  • PaaS (Platform as a Service): 提供平台,如操作系统、运行时环境、数据库。
  • SaaS (Software as a Service): 提供软件,如邮件服务、CRM 系统。

4.2 Kubernetes 生态系统

4.3 Kubernetes 设计理念

  • 可扩展性: 基于 CRD 的扩展,插件化的生态系统。
  • 高可用: 基于 replicaset、statefulset 的应用高可用,Kubernetes 组件本身高可用。
  • 可移植性: 多种 host OS 选择,多种基础架构的选择,多云和混合云。
  • 安全: 基于 TLS 提供服务,Serviceaccount 和 user,基于 Namespace 的隔离,secret,Taints,psp,networkpolicy。

4.4 Kubernetes 分层架构

  • 核心层: 提供 API 构建高层应用,提供插件式应用执行环境。
  • 应用层: 部署和路由。
  • 管理层: 系统度量、自动化、策略管理。
  • 接口层: kubectl 命令行工具、客户端 SDK 以及集群联邦。
  • 生态系统:
    • Kubernetes 外部:日志、监控、配置管理、CI/CD 等。
    • Kubernetes 内部:CRI、CNI、CVI、镜像仓库、Cloud Provider 等。

4.5 API 设计原则

  • 所有 API 都应是声明式的。
  • API 对象是彼此互补而且可组合的。
  • 高层 API 以操作意图为基础设计。
  • 低层 API 根据高层 API 的控制需要设计。
  • 尽量避免简单封装。
  • API 操作复杂度与对象数量成正比。
  • API 对象状态不能依赖于网络连接状态。
  • 尽量避免让操作机制依赖于全局状态。

4.6 Kubernetes 对象的组合

graph LR
    A[Deployment] --> B(滚动升级策略)
    A --> C(副本数)
    A --> D[PodTemplate]
    D --> E[Replicaset]
    E --> F(版本信息)
    E --> G(副本数)
    E --> H[PodTemplate]
    H --> I[Node]
    H --> J[Pod]
    H --> K[Service]
    H --> L[Ingress]
    I --> M(计算资源)
    I --> N(健康状况)
    J --> O(镜像地址)
    J --> P(资源需求)
    K --> Q(服务协议)
    K --> R(服务端口)
    L --> S(域名)
    L --> T(访问 URL)
    L --> U(目标服务)

4.7 架构设计原则

  • 只有 APIServer 可以直接访问 etcd 存储。
  • 单节点故障不应该影响集群的状态。
  • 所有组件应该在内存中保持所需要的状态。
  • 优先使用事件监听而不是轮询。

4.8 引导(Bootstrapping)原则

  • Self-hosting 是目标。
  • 减少依赖。
  • 通过分层的原则管理依赖。
  • 循环依赖问题的原则:
    • 接受其他方式的数据输入。
    • 状态应该是可恢复或可重新发现的。
    • 支持简单的启动临时实例来创建稳态运行所需要的状态。
    • 自动重启异常退出的服务。

4.9 核心技术概念和 API 对象

  • API 对象: Kubernetes 集群中的管理操作单元。
  • 四大类属性:
    • TypeMeta: 对象的类型定义(GKV 模型)。
      • Group:对象的分组。
      • Kind:对象的基本类型。
      • Version:对象的版本。
    • MetaData: 对象的元数据。
      • Namespace:对象的命名空间。
      • Name:对象的名称。
      • Label:对象的标签,用于识别和选择对象。
      • Annotation:对象的注解,用于记录附加信息。
      • Finalizer:资源锁,用于控制对象的删除。
      • ResourceVersion:乐观锁,用于并发访问对象。
    • Spec: 用户的期望状态。
    • Status: 对象的实际状态。

4.10 常用 Kubernetes 对象及其分组

  • Node: Pod 运行的主机。
  • Namespace: 资源和对象的抽象集合。
  • Pod: 一组紧密关联的容器集合,共享 PID、IPC、Network 和 UTS namespace。
    • 环境变量: 设置容器的环境变量。
    • 存储卷: 将外挂存储挂载到 Pod 内部。
    • Pod 网络: 多个容器共享网络 Namespace。
    • 资源限制: 限制每个容器的 CPU 和内存使用。
    • 健康检查: 探测应用是否健康和就绪。
  • ConfigMap: 保存非机密性的数据到键值对中。
  • Secret: 保存和传递密码、密钥、认证凭证等敏感信息。
  • User Account & Service Account:
    • User Account:为人提供账户标识。
    • Service Account:为计算机进程和 Pod 提供账户标识。
  • Service: 应用服务的抽象,通过 labels 提供负载均衡和服务发现。
  • Replica Set: 定义 Pod 的副本数,保证指定数量的 Pod 正常运行。
  • Deployment: 表示用户对 Kubernetes 集群的一次更新操作。
  • StatefulSet: 用于管理有状态应用,每个 Pod 挂载自己独立的存储。
  • Job: 控制批处理型任务。
  • DaemonSet: 保证每个节点上都有一个 Pod 运行。
  • PersistentVolume (PV) & PersistentVolumeClaim (PVC):
    • PV:集群中的一块存储卷。
    • PVC:用户对存储的请求。
  • CustomResourceDefinition (CRD): 允许用户自定义对象。

kubernetes架构原则与对象设计
https://mfzzf.github.io/2025/03/16/kubernetes架构设计/
作者
Mzzf
发布于
2025年3月16日
许可协议