一、从 Borg 到 Kubernetes:声明式基础设施的诞生
2014 年 6 月,Google 将其内部容器编排系统 Borg 的设计思想提炼并开源,发布了 Kubernetes(简称 K8s)项目。Borg 在 Google 内部运行了超过十年,管理着数百万个容器实例,支撑了搜索、Gmail、YouTube 等核心服务。根据 Google 2015 年发表的论文《Large-scale cluster management at Google with Borg》,Borg 集群的典型规模为单集群 10000 台以上机器,每周调度超过 200 亿个任务实例。Kubernetes 继承了 Borg 的声明式 API、控制器模式、标签选择器等核心设计理念,同时在可扩展性和开放性方面做了根本性改进。
Kubernetes 解决的核心问题是:如何在大规模分布式环境中,以声明式(Declarative)的方式管理应用的部署、扩缩容、服务发现和自愈。与传统的命令式运维方式不同,用户只需声明期望的终态(Desired State),系统负责持续将实际状态(Actual State)收敛到期望状态。这一设计哲学贯穿了 Kubernetes 架构的每一个组件。
本文将从架构全景出发,深入分析 kube-apiserver 为什么是整个集群的”单点”、etcd 的 watch 机制如何驱动声明式 API、控制器模式的工作原理、调度器的决策流程、以及如何通过 CRD 和 Operator 模式扩展 Kubernetes 的能力边界。
二、Kubernetes 整体架构:控制面与数据面
2.1 架构全景
Kubernetes 集群由控制面(Control Plane)和数据面(Data Plane)两部分组成。控制面负责集群的全局决策与状态管理,数据面负责实际运行工作负载。
graph TB
subgraph 控制面["控制面(Control Plane)"]
APIServer["kube-apiserver<br/>API 网关 / 认证鉴权 / 准入控制"]
etcd["etcd<br/>分布式键值存储"]
Scheduler["kube-scheduler<br/>调度决策"]
CM["kube-controller-manager<br/>控制器集合"]
CCM["cloud-controller-manager<br/>云平台适配"]
end
subgraph 数据面Node1["数据面 - Node 1"]
kubelet1["kubelet<br/>Pod 生命周期管理"]
kproxy1["kube-proxy<br/>网络规则管理"]
CRI1["容器运行时<br/>containerd / CRI-O"]
Pod1A["Pod A"]
Pod1B["Pod B"]
end
subgraph 数据面Node2["数据面 - Node 2"]
kubelet2["kubelet"]
kproxy2["kube-proxy"]
CRI2["容器运行时"]
Pod2A["Pod C"]
Pod2B["Pod D"]
end
APIServer -->|"读写状态"| etcd
Scheduler -->|"watch 未调度 Pod"| APIServer
CM -->|"watch 资源变化"| APIServer
CCM -->|"watch Node/Service"| APIServer
kubelet1 -->|"上报状态 / watch Pod"| APIServer
kubelet2 -->|"上报状态 / watch Pod"| APIServer
kproxy1 -->|"watch Service/Endpoints"| APIServer
kproxy2 -->|"watch Service/Endpoints"| APIServer
kubelet1 --> CRI1
CRI1 --> Pod1A
CRI1 --> Pod1B
kubelet2 --> CRI2
CRI2 --> Pod2A
CRI2 --> Pod2B
2.2 控制面组件职责
| 组件 | 职责 | 无状态/有状态 | 高可用方式 |
|---|---|---|---|
| kube-apiserver | 集群唯一入口,提供 RESTful API,负责认证、鉴权、准入控制、API 聚合 | 无状态 | 多副本 + 负载均衡 |
| etcd | 存储所有集群状态,提供 watch 通知机制 | 有状态 | Raft 共识,奇数节点(3/5/7) |
| kube-scheduler | 为未调度的 Pod 选择最优 Node | 无状态 | Leader Election |
| kube-controller-manager | 运行所有内置控制器(Deployment、ReplicaSet、Job 等) | 无状态 | Leader Election |
| cloud-controller-manager | 对接云厂商 API(负载均衡、存储卷、节点生命周期) | 无状态 | Leader Election |
2.3 数据面组件职责
每个工作节点(Worker Node)上运行以下组件:
- kubelet:节点代理,负责 Pod 的创建、启动、监控和销毁。通过 CRI(Container Runtime Interface)调用容器运行时,通过 CNI(Container Network Interface)配置 Pod 网络,通过 CSI(Container Storage Interface)挂载存储卷。
- kube-proxy:维护节点上的网络规则,实现 Service 的负载均衡。支持 iptables、IPVS 和 nftables 三种代理模式。
- 容器运行时(Container Runtime):负责实际的容器创建和管理。主流选择包括 containerd 和 CRI-O,Docker 自 Kubernetes 1.24 起已被移除。
2.4 核心设计原则
Kubernetes 架构遵循以下设计原则:
- 声明式优于命令式:用户声明期望状态,系统自动收敛。
- 控制面与数据面分离:控制逻辑与工作负载运行互不干扰。
- 面向终态的设计:所有控制器只关心”当前状态与期望状态的差异”。
- 松耦合通信:所有组件通过 API Server 间接通信,不直接互联。
- 可扩展性优先:CRD、Admission Webhook、调度框架等扩展点贯穿全栈。
三、kube-apiserver 深度解析
3.1 为什么 apiserver 是”单点”
kube-apiserver 是整个集群的唯一通信枢纽。所有组件——kubelet、kube-scheduler、kube-controller-manager、kubectl、自定义控制器——都只与 apiserver 通信,不直接互联。这一设计有以下深层原因:
- 单一数据源(Single Source of Truth):所有状态变更必须经过 apiserver 写入 etcd,确保数据一致性。
- 统一认证鉴权:所有请求在同一处完成身份认证和权限校验。
- 审计与可观测性:所有 API 调用在同一处记录审计日志。
- 乐观并发控制:通过 resourceVersion 实现基于 etcd 的乐观锁。
虽然 apiserver 可以水平扩展为多副本,但从逻辑架构角度看,它仍然是所有组件的”单点依赖”——任何组件失去与 apiserver 的连接,都会停止正常工作。
3.2 请求处理链路
一个典型的 API 请求(如
kubectl apply -f deployment.yaml)经历以下处理阶段:
客户端请求
│
▼
┌─────────────────────────────────┐
│ 1. 认证(Authentication) │ → 确认请求者身份
│ - X.509 客户端证书 │
│ - Bearer Token │
│ - OIDC / Webhook Token Review │
├─────────────────────────────────┤
│ 2. 鉴权(Authorization) │ → 确认请求者权限
│ - RBAC │
│ - ABAC │
│ - Webhook │
│ - Node Authorization │
├─────────────────────────────────┤
│ 3. 准入控制(Admission Control) │ → 变更/验证请求内容
│ - MutatingAdmissionWebhook │ → 可修改请求
│ - ValidatingAdmissionWebhook │ → 只能拒绝请求
├─────────────────────────────────┤
│ 4. 持久化 │ → 写入 etcd
├─────────────────────────────────┤
│ 5. 通知 │ → 通过 watch 推送变更事件
└─────────────────────────────────┘
3.3 认证机制
Kubernetes 支持多种认证方式,可以同时启用:
# kube-apiserver 认证相关启动参数
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
- --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
- --service-account-issuer=https://kubernetes.default.svc
- --oidc-issuer-url=https://accounts.google.com
- --oidc-client-id=my-k8s-cluster
- --oidc-username-claim=email
- --authorization-mode=Node,RBAC
image: registry.k8s.io/kube-apiserver:v1.30.0认证模块采用链式处理:任一认证器成功即通过,全部失败则拒绝(返回 401)。
3.4 RBAC 鉴权模型
RBAC(Role-Based Access Control)是生产环境中最常用的鉴权模式。其核心模型包含四种资源:
# Role:定义命名空间内的权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
---
# RoleBinding:将 Role 绑定到用户/组/ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: production
subjects:
- kind: ServiceAccount
name: monitoring-agent
namespace: monitoring
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioClusterRole 和 ClusterRoleBinding
提供集群级别的权限控制,适用于跨命名空间资源(如
Node、PersistentVolume)和非资源端点(如
/healthz)。
3.5 准入控制
准入控制器(Admission Controller)在认证鉴权之后、持久化之前执行,分为两类:
- 变更准入(Mutating Admission):可以修改请求对象。例如,自动注入 sidecar 容器(Istio 使用此机制注入 Envoy)、设置默认资源限制。
- 验证准入(Validating Admission):只能接受或拒绝请求。例如,检查镜像是否来自受信仓库、验证 Pod 安全策略。
执行顺序为:先执行所有 Mutating Webhook,再执行所有 Validating Webhook。这保证了验证逻辑看到的是最终修改后的对象。
3.6 API 聚合层
API 聚合(API Aggregation)允许在不修改核心代码的情况下扩展 Kubernetes API。通过注册 APIService 资源,将自定义 API 组的请求代理到用户部署的扩展 API 服务器。metrics-server 就是一个典型的聚合 API 实现:
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1beta1.metrics.k8s.io
spec:
service:
name: metrics-server
namespace: kube-system
group: metrics.k8s.io
version: v1beta1
groupPriorityMinimum: 100
versionPriority: 100
insecureSkipTLSVerify: true四、etcd 在 Kubernetes 中的角色
4.1 etcd 概述
etcd 是一个基于 Raft 共识算法的分布式键值存储系统,为 Kubernetes 提供所有集群状态的持久化存储。Kubernetes 中的每一个资源对象——Pod、Service、Deployment、ConfigMap——最终都以键值对的形式存储在 etcd 中。
etcd 在 Kubernetes 中的数据模型:
/registry/pods/default/nginx-7d8b49557c-abc12
/registry/deployments/default/nginx
/registry/services/specs/default/kubernetes
/registry/configmaps/kube-system/coredns
/registry/secrets/default/my-secret
4.2 Watch 机制
etcd 的 watch 机制是 Kubernetes 声明式 API 的核心驱动力。所有控制器、kubelet、kube-proxy 都通过 watch API Server 的资源变更来触发自身的处理逻辑,而不是定期轮询。
sequenceDiagram
participant User as 用户(kubectl)
participant API as kube-apiserver
participant etcd as etcd
participant Informer as Controller Informer
participant Controller as Controller Reconcile
User->>API: kubectl apply -f deployment.yaml
API->>API: 认证 → 鉴权 → 准入控制
API->>etcd: Put /registry/deployments/default/nginx
etcd-->>API: OK(revision=1025)
Note over etcd,Informer: Watch 连接(长连接 gRPC Stream)
etcd-->>API: WatchEvent(ADDED, revision=1025)
API-->>Informer: WatchEvent(ADDED)
Informer->>Informer: 更新本地缓存(Store)
Informer->>Controller: 入队 workqueue(key="default/nginx")
Controller->>Controller: Reconcile(读缓存,计算差异)
Controller->>API: 创建 ReplicaSet
API->>etcd: Put /registry/replicasets/default/nginx-7d8b49557c
Watch 机制的关键特性:
- 事件驱动:基于 gRPC 长连接的服务端推送,延迟通常在毫秒级。
- 有序性保证:事件按 etcd revision 严格有序。
- 断线重连:客户端通过 resourceVersion 实现断点续传,不会丢失事件。
- 压缩与回收:etcd 定期压缩历史版本,过旧的 resourceVersion 会触发 “410 Gone” 错误,客户端需回退到全量 List 重建缓存。
4.3 MVCC 与一致性保障
etcd 使用 MVCC(Multi-Version Concurrency Control)实现并发控制。每次写操作都会生成一个新的 revision,旧版本被保留直到压缩。
Kubernetes 利用 etcd 的 MVCC 实现乐观并发控制:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
namespace: default
resourceVersion: "12345" # 对应 etcd 的 mod_revision
data:
key: value当两个客户端同时修改同一个对象时: 1. 客户端 A
读取对象,resourceVersion=12345。 2. 客户端 B
读取对象,resourceVersion=12345。 3. 客户端 A
提交更新,携带 resourceVersion=12345,成功,新
resourceVersion=12346。 4. 客户端 B
提交更新,携带 resourceVersion=12345,etcd
发现已被修改,返回冲突错误(HTTP 409 Conflict)。
4.4 为什么 etcd 是瓶颈
在大规模集群中,etcd 常常成为整个系统的性能瓶颈:
- 写放大:Raft 协议要求每次写操作在多数节点上持久化 WAL 日志,再应用到 BoltDB。一次逻辑写入会转化为多次磁盘 I/O。
- Watch 连接数:大集群中可能有数千个 watch 连接,每次写操作需要通知所有相关 watcher。
- 数据库大小限制:etcd 默认数据库大小上限为 2 GB(可调至 8 GB),超过后拒绝写入。
- 序列化开销:所有对象在 apiserver 和 etcd 之间以 Protobuf 序列化传输,大对象(如大型 ConfigMap)带来显著开销。
- 磁盘延迟敏感:etcd 对磁盘延迟极度敏感,官方建议使用 SSD 且 P99 写延迟不超过 10ms。
生产环境中的优化措施:
| 优化方向 | 具体措施 | 效果 |
|---|---|---|
| 磁盘 | 使用 NVMe SSD,分离 WAL 与数据目录 | 降低 P99 写延迟 50% 以上 |
| 网络 | etcd 节点间延迟控制在 1ms 以内 | 降低 Raft 共识延迟 |
| 数据规模 | 定期压缩与碎片整理(etcdctl defrag) |
控制数据库大小 |
| 事件分离 | 使用独立的 etcd 集群存储 Event 资源 | 减少主 etcd 写入压力 |
| Watch 优化 | apiserver 开启 WatchCache(默认开启) | 减少 etcd watch 连接数 |
| 限流 | 配置 apiserver 的 --max-requests-inflight
和 --max-mutating-requests-inflight |
保护 etcd 不被打满 |
五、控制器模式:Reconciliation Loop
5.1 控制器的核心思想
控制器模式是 Kubernetes 最重要的设计模式。每个控制器持续执行以下循环:
for {
desired := 获取期望状态(从 API Server 的资源对象中读取)
actual := 获取实际状态(从集群实际情况中观察)
diff := 计算差异(desired - actual)
执行动作使 actual 趋向 desired
}
这个循环被称为 Reconciliation Loop(调谐循环)。控制器不关心事件的类型(创建、更新、删除),只关心”当前状态与期望状态是否一致”。这种面向终态的设计使系统天然具备自愈能力。
5.2 Informer 机制
Informer 是 client-go 库提供的核心组件,解决了控制器与 API Server 之间高效通信的问题。
graph LR
subgraph Informer["SharedInformer"]
Reflector["Reflector<br/>List + Watch"]
DeltaFIFO["DeltaFIFO<br/>增量事件队列"]
Indexer["Indexer / Store<br/>本地缓存"]
end
APIServer["kube-apiserver"]
EventHandler["ResourceEventHandler<br/>OnAdd / OnUpdate / OnDelete"]
WorkQueue["WorkQueue<br/>限速队列"]
Worker["Worker Goroutine<br/>Reconcile 逻辑"]
APIServer -->|"List(首次全量)"| Reflector
APIServer -->|"Watch(增量事件流)"| Reflector
Reflector -->|"事件入队"| DeltaFIFO
DeltaFIFO -->|"Pop 事件"| Indexer
DeltaFIFO -->|"通知"| EventHandler
EventHandler -->|"提取 key 入队"| WorkQueue
WorkQueue -->|"取出 key"| Worker
Worker -->|"读取缓存"| Indexer
Worker -->|"写操作"| APIServer
Informer 的关键设计决策:
- SharedInformerFactory:同一进程内对同一资源类型的多个控制器共享一个 Informer 实例,避免对 API Server 发起重复的 List/Watch 请求。
- DeltaFIFO:增量事件队列,保存对象的变更增量(Added、Updated、Deleted),而非完整对象。
- Indexer:本地内存缓存,支持按 namespace、标签等维度索引查询,控制器的读操作直接命中本地缓存,极大降低 API Server 负载。
- WorkQueue:限速工作队列,支持去重、延迟重入、指数退避重试。
5.3 控制器代码示例
以下是一个简化的 Deployment 控制器 Reconcile 逻辑伪代码:
func (c *DeploymentController) syncDeployment(key string) error {
namespace, name, err := cache.SplitMetaNamespaceKey(key)
if err != nil {
return err
}
// 从 Informer 本地缓存读取 Deployment 对象
deployment, err := c.deploymentLister.Deployments(namespace).Get(name)
if errors.IsNotFound(err) {
// 对象已删除,无需处理
return nil
}
if err != nil {
return err
}
// 获取该 Deployment 管理的所有 ReplicaSet
rsList, err := c.getReplicaSetsForDeployment(deployment)
if err != nil {
return err
}
// 计算期望状态与实际状态的差异
scalingEvent := false
if deployment.Spec.Replicas != nil {
desiredReplicas := *deployment.Spec.Replicas
currentReplicas := countAvailableReplicas(rsList)
if currentReplicas < desiredReplicas {
// 需要扩容
err = c.scaleUp(deployment, rsList, desiredReplicas)
scalingEvent = true
} else if currentReplicas > desiredReplicas {
// 需要缩容
err = c.scaleDown(deployment, rsList, desiredReplicas)
scalingEvent = true
}
}
// 检查是否需要滚动更新
if !scalingEvent && needsRollout(deployment, rsList) {
return c.rolloutUpdate(deployment, rsList)
}
// 更新 Deployment 状态
return c.updateDeploymentStatus(deployment, rsList)
}5.4 内置控制器一览
kube-controller-manager 内嵌了数十个控制器,以下是核心控制器:
| 控制器 | 职责 | 监听资源 | 管理资源 |
|---|---|---|---|
| DeploymentController | 管理无状态应用部署与滚动更新 | Deployment, ReplicaSet | ReplicaSet |
| ReplicaSetController | 维持 Pod 副本数 | ReplicaSet, Pod | Pod |
| StatefulSetController | 管理有状态应用,保证有序部署与持久化身份 | StatefulSet, Pod | Pod, PVC |
| DaemonSetController | 确保每个节点运行一个 Pod 副本 | DaemonSet, Node, Pod | Pod |
| JobController | 管理一次性批处理任务 | Job, Pod | Pod |
| CronJobController | 按 cron 表达式创建 Job | CronJob | Job |
| EndpointSliceController | 维护 Service 的后端端点列表 | Service, Pod, Node | EndpointSlice |
| NodeLifecycleController | 监控 Node 健康状态,驱逐不健康节点上的 Pod | Node, Pod | Pod(Taint/Eviction) |
| GarbageCollector | 级联删除拥有者被删除的资源 | 所有资源 | 所有资源 |
| NamespaceController | 清理被删除命名空间中的所有资源 | Namespace | 命名空间内所有资源 |
六、kube-scheduler 调度流程
6.1 调度流程概览
kube-scheduler 负责为每个新创建且未绑定节点的 Pod 选择最优的运行节点。调度流程分为三个主要阶段:
新 Pod(spec.nodeName 为空)
│
▼
┌──────────────────────────┐
│ 阶段一:预选(Filtering) │ → 过滤不满足条件的节点
│ - NodeResourcesFit │ → 节点资源是否充足
│ - NodeAffinity │ → 节点亲和性是否匹配
│ - PodTopologySpread │ → 拓扑分布约束
│ - TaintToleration │ → 污点是否被容忍
│ - NodePorts │ → 端口是否冲突
│ 可行节点集合 → N 个候选 │
├──────────────────────────┤
│ 阶段二:优选(Scoring) │ → 对候选节点打分
│ - NodeResourcesFit │ → 资源利用率均衡
│ - InterPodAffinity │ → Pod 间亲和/反亲和
│ - ImageLocality │ → 镜像是否已缓存
│ - PodTopologySpread │ → 拓扑均匀分布
│ 每个节点得分 0-100 │
├──────────────────────────┤
│ 阶段三:绑定(Binding) │ → 将 Pod 绑定到最高分节点
│ - 设置 spec.nodeName │
│ - 通知 kubelet 启动 Pod │
└──────────────────────────┘
6.2 调度框架扩展点
Kubernetes 1.19 引入的调度框架(Scheduling Framework)定义了完整的扩展点链路:
| 扩展点 | 阶段 | 功能 | 调用时机 |
|---|---|---|---|
| PreEnqueue | 入队前 | 决定 Pod 是否可以进入调度队列 | Pod 创建时 |
| QueueSort | 排序 | 决定调度队列中 Pod 的优先级 | 队列排序时 |
| PreFilter | 预过滤 | 计算过滤阶段需要的前置信息 | 过滤前 |
| Filter | 过滤 | 判断节点是否满足 Pod 的约束 | 对每个节点 |
| PostFilter | 后过滤 | 没有可行节点时的处理(如抢占) | 过滤后无结果 |
| PreScore | 预打分 | 计算打分阶段需要的前置信息 | 打分前 |
| Score | 打分 | 对候选节点打分 | 对每个候选节点 |
| NormalizeScore | 归一化 | 将分数归一化到 0-100 | 打分后 |
| Reserve | 预留 | 在绑定前预留资源 | 选定节点后 |
| Permit | 许可 | 允许/拒绝/等待 Pod 绑定 | 预留后 |
| PreBind | 预绑定 | 绑定前的准备(如挂载 PV) | 许可后 |
| Bind | 绑定 | 执行实际绑定 | 预绑定后 |
| PostBind | 后绑定 | 绑定成功后的清理/通知 | 绑定后 |
6.3 调度约束示例
apiVersion: v1
kind: Pod
metadata:
name: web-server
labels:
app: web
spec:
# 节点亲和性:优先调度到有 SSD 的节点
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node.kubernetes.io/instance-type
operator: In
values:
- m5.xlarge
- m5.2xlarge
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: disk-type
operator: In
values:
- ssd
# Pod 反亲和性:同一应用的 Pod 分散到不同节点
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
# 拓扑分布约束:跨可用区均匀分布
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
# 容忍 GPU 节点的污点
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
containers:
- name: web
image: nginx:1.25
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"七、kubelet 的职责
7.1 Pod 生命周期管理
kubelet 是每个节点上最核心的组件,负责 Pod 从创建到销毁的全部生命周期管理:
- Pod 同步:通过 watch API Server 接收分配到本节点的 Pod 定义,与本地容器运行时的实际状态进行对比。
- 容器创建:调用 CRI 接口创建容器,包括拉取镜像、创建 Sandbox、启动容器。
- 健康检查:执行 livenessProbe(存活探针)、readinessProbe(就绪探针)和 startupProbe(启动探针)。
- 资源管理:通过 cgroups 实施 CPU、内存等资源限制,执行驱逐策略(Eviction)。
- 状态上报:定期向 API Server 上报节点状态(NodeStatus)和 Pod 状态(PodStatus)。
7.2 CRI、CNI、CSI 接口
kubelet 通过三个标准接口实现与底层基础设施的解耦:
kubelet
├── CRI(Container Runtime Interface)
│ ├── containerd
│ ├── CRI-O
│ └── 其他符合 CRI 规范的运行时
├── CNI(Container Network Interface)
│ ├── Calico(BGP/eBPF 模式)
│ ├── Cilium(eBPF 原生)
│ ├── Flannel(VXLAN/host-gw)
│ └── 其他 CNI 插件
└── CSI(Container Storage Interface)
├── EBS CSI Driver
├── Ceph RBD CSI
├── NFS CSI
└── 其他 CSI 驱动
CRI 接口的核心 gRPC 方法:
// RuntimeService 定义了容器运行时的核心操作
type RuntimeService interface {
// Pod Sandbox 管理
RunPodSandbox(config *PodSandboxConfig) (string, error)
StopPodSandbox(podSandboxId string) error
RemovePodSandbox(podSandboxId string) error
// 容器管理
CreateContainer(podSandboxId string, config *ContainerConfig,
sandboxConfig *PodSandboxConfig) (string, error)
StartContainer(containerId string) error
StopContainer(containerId string, timeout int64) error
RemoveContainer(containerId string) error
// 容器状态
ContainerStatus(containerId string) (*ContainerStatus, error)
ListContainers(filter *ContainerFilter) ([]*Container, error)
// 命令执行
ExecSync(containerId string, cmd []string, timeout int64) (
stdout []byte, stderr []byte, err error)
}7.3 节点资源管理与驱逐
kubelet 通过驱逐管理器(Eviction Manager)监控节点资源使用情况,当资源低于阈值时触发 Pod 驱逐:
| 资源信号 | 默认驱逐阈值 | 驱逐优先级 |
|---|---|---|
| memory.available | 100Mi | BestEffort → Burstable → Guaranteed |
| nodefs.available | 10% | 按磁盘使用量排序 |
| nodefs.inodesFree | 5% | 按 inode 使用量排序 |
| imagefs.available | 15% | 先回收未使用镜像 |
| pid.available | 按内核限制 | 按 PID 使用量排序 |
八、CRD 与 Operator 模式
8.1 CRD 的本质
CRD(Custom Resource Definition)允许用户在不修改 Kubernetes 源码的情况下扩展 API,注册自定义资源类型。CRD 注册后,Kubernetes API Server 自动为其提供完整的 RESTful CRUD 端点、watch 机制和 kubectl 支持。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: databases.db.example.com
spec:
group: db.example.com
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required: ["engine", "version", "replicas"]
properties:
engine:
type: string
enum: ["postgresql", "mysql", "mongodb"]
version:
type: string
replicas:
type: integer
minimum: 1
maximum: 7
storageSize:
type: string
pattern: "^[0-9]+(Gi|Ti)$"
backup:
type: object
properties:
enabled:
type: boolean
schedule:
type: string
retentionDays:
type: integer
status:
type: object
properties:
phase:
type: string
readyReplicas:
type: integer
endpoint:
type: string
lastBackup:
type: string
format: date-time
subresources:
status: {}
additionalPrinterColumns:
- name: Engine
type: string
jsonPath: .spec.engine
- name: Version
type: string
jsonPath: .spec.version
- name: Replicas
type: integer
jsonPath: .spec.replicas
- name: Phase
type: string
jsonPath: .status.phase
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
scope: Namespaced
names:
plural: databases
singular: database
kind: Database
shortNames:
- db注册 CRD 后,用户即可像操作原生资源一样使用自定义资源:
apiVersion: db.example.com/v1alpha1
kind: Database
metadata:
name: order-db
namespace: production
spec:
engine: postgresql
version: "16.2"
replicas: 3
storageSize: "100Gi"
backup:
enabled: true
schedule: "0 2 * * *"
retentionDays: 308.2 Operator 模式
Operator 将领域运维知识编码为软件,使用 CRD 定义领域模型,使用自定义控制器实现自动化运维逻辑。一个 Operator 本质上就是”CRD + 自定义控制器”。
以下是一个数据库 Operator 的 Reconcile 循环实现:
package controllers
import (
"context"
"fmt"
"time"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
dbv1alpha1 "github.com/example/db-operator/api/v1alpha1"
)
type DatabaseReconciler struct {
client.Client
Scheme *runtime.Scheme
}
// Reconcile 是 Operator 的核心逻辑:确保实际状态与期望状态一致
func (r *DatabaseReconciler) Reconcile(
ctx context.Context, req ctrl.Request,
) (ctrl.Result, error) {
logger := log.FromContext(ctx)
// 第一步:获取 Database CR
var database dbv1alpha1.Database
if err := r.Get(ctx, req.NamespacedName, &database); err != nil {
if errors.IsNotFound(err) {
logger.Info("Database 资源已被删除")
return ctrl.Result{}, nil
}
return ctrl.Result{}, err
}
// 第二步:确保 StatefulSet 存在且规格正确
sts := r.buildStatefulSet(&database)
var existingSts appsv1.StatefulSet
err := r.Get(ctx, client.ObjectKeyFromObject(sts), &existingSts)
if errors.IsNotFound(err) {
logger.Info("创建 StatefulSet",
"name", sts.Name, "replicas", *sts.Spec.Replicas)
if err := r.Create(ctx, sts); err != nil {
return ctrl.Result{}, err
}
database.Status.Phase = "Creating"
r.Status().Update(ctx, &database)
return ctrl.Result{RequeueAfter: 10 * time.Second}, nil
} else if err != nil {
return ctrl.Result{}, err
}
// 第三步:检查是否需要扩缩容
if *existingSts.Spec.Replicas != int32(database.Spec.Replicas) {
logger.Info("更新副本数",
"from", *existingSts.Spec.Replicas,
"to", database.Spec.Replicas)
replicas := int32(database.Spec.Replicas)
existingSts.Spec.Replicas = &replicas
if err := r.Update(ctx, &existingSts); err != nil {
return ctrl.Result{}, err
}
database.Status.Phase = "Scaling"
r.Status().Update(ctx, &database)
return ctrl.Result{RequeueAfter: 15 * time.Second}, nil
}
// 第四步:确保 Service 存在
svc := r.buildService(&database)
var existingSvc corev1.Service
if err := r.Get(ctx, client.ObjectKeyFromObject(svc),
&existingSvc); errors.IsNotFound(err) {
if err := r.Create(ctx, svc); err != nil {
return ctrl.Result{}, err
}
}
// 第五步:更新状态
database.Status.ReadyReplicas = int(existingSts.Status.ReadyReplicas)
database.Status.Endpoint = fmt.Sprintf(
"%s.%s.svc.cluster.local:5432",
svc.Name, svc.Namespace)
if existingSts.Status.ReadyReplicas == *existingSts.Spec.Replicas {
database.Status.Phase = "Running"
} else {
database.Status.Phase = "Progressing"
}
r.Status().Update(ctx, &database)
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}
func (r *DatabaseReconciler) buildStatefulSet(
db *dbv1alpha1.Database,
) *appsv1.StatefulSet {
replicas := int32(db.Spec.Replicas)
labels := map[string]string{
"app": db.Name,
"db.example.com/engine": db.Spec.Engine,
}
return &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: db.Name,
Namespace: db.Namespace,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(db,
dbv1alpha1.GroupVersion.WithKind("Database")),
},
},
Spec: appsv1.StatefulSetSpec{
Replicas: &replicas,
ServiceName: db.Name,
Selector: &metav1.LabelSelector{
MatchLabels: labels,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{Labels: labels},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "database",
Image: fmt.Sprintf("%s:%s",
db.Spec.Engine, db.Spec.Version),
Ports: []corev1.ContainerPort{{
ContainerPort: 5432,
}},
}},
},
},
},
}
}
// SetupWithManager 注册控制器并声明监听资源
func (r *DatabaseReconciler) SetupWithManager(
mgr ctrl.Manager,
) error {
return ctrl.NewControllerManagedBy(mgr).
For(&dbv1alpha1.Database{}).
Owns(&appsv1.StatefulSet{}).
Owns(&corev1.Service{}).
Complete(r)
}8.3 Operator 成熟度模型
Operator 社区定义了五级成熟度模型:
| 级别 | 名称 | 能力描述 |
|---|---|---|
| Level 1 | 基本安装(Basic Install) | 自动部署应用,通过 CRD 配置参数 |
| Level 2 | 无缝升级(Seamless Upgrades) | 支持应用版本升级与配置变更 |
| Level 3 | 全生命周期管理(Full Lifecycle) | 备份、恢复、故障转移 |
| Level 4 | 深度监控(Deep Insights) | 指标暴露、日志聚合、告警集成 |
| Level 5 | 自动驾驶(Auto Pilot) | 自动扩缩容、自动调优、异常自愈 |
九、多集群联邦
9.1 为什么需要多集群
当集群规模超过一定阈值或业务具有跨地域要求时,单集群方案面临以下限制:
- etcd 性能天花板:单集群超过 5000 节点时,etcd 的读写延迟显著增加。
- 故障爆炸半径:单集群故障影响所有业务。
- 合规要求:数据主权法规(如 GDPR)要求数据存储在特定地域。
- 多云策略:避免供应商锁定,分散风险。
- 网络延迟:跨地域单集群的 etcd Raft 共识延迟不可接受。
9.2 多集群方案对比
| 方案 | 架构模式 | 核心能力 | 适用场景 | 局限性 |
|---|---|---|---|---|
| KubeFed v2 | 中心化联邦控制面 | 资源分发、跨集群调度策略 | 同质集群联邦 | 社区维护停滞,复杂度高 |
| Liqo | 去中心化 Peering | 虚拟节点映射,Pod 跨集群透明迁移 | 边缘-云协同 | 网络要求高,生态较新 |
| Admiralty | 虚拟调度器 | 多集群 Pod 调度代理 | 批处理跨集群调度 | 功能聚焦调度层 |
| Karmada | CNCF 沙箱项目,兼容原生 API | 资源模板 + 策略 + 覆写 | 大规模多集群管理 | 需要独立控制面 |
| Cluster API | 声明式集群生命周期管理 | 集群创建/升级/删除 | 集群即服务(Cluster as a Service) | 不处理工作负载分发 |
| ArgoCD + ApplicationSet | GitOps 驱动多集群 | Git 仓库为唯一事实源 | 多集群应用分发 | 不处理跨集群网络 |
9.3 多集群网络
跨集群网络互通是多集群架构的核心挑战。主流方案包括:
- Submariner:通过 IPsec/WireGuard 隧道连接多集群 Pod/Service 网络,支持跨集群 Service Discovery。
- Cilium ClusterMesh:基于 eBPF 的多集群网络方案,支持全局 Service、网络策略跨集群生效。
- Istio 多集群:在服务网格层面实现多集群服务互通,支持跨集群流量管理和可观测性。
十、工程案例:Spotify 的大规模 Kubernetes 实践
10.1 背景
Spotify 自 2019 年开始将其基础设施全面迁移到 Kubernetes。到 2023 年,Spotify 在全球范围内运行超过 200 个 Kubernetes 集群,服务于 6000 多个微服务。以下数据来自 Spotify 在 KubeCon 2023 的公开演讲和技术博客。
10.2 集群规模数据
| 指标 | 数值 |
|---|---|
| 集群总数 | 200+ |
| 总节点数 | 约 20000 |
| 总 Pod 数 | 约 500000 |
| 微服务数量 | 6000+ |
| 日均部署次数 | 10000+ |
| 最大单集群节点数 | 约 3000 |
| 平均 Pod 密度 | 约 25 Pods/Node |
| 工程师人数 | 约 4000 |
10.3 架构决策
集群拆分策略:Spotify 选择多集群而非单个大集群。每个”小队”(Squad,Spotify 的组织单元)可以拥有自己的命名空间,但集群按功能和地域划分:
- 生产集群按地域分布(us-east、us-west、eu-west 等)。
- 独立的预发布(Staging)集群。
- 专用的数据处理集群(运行 Apache Beam 等大数据工作负载)。
平台即产品:Spotify 构建了内部平台 Backstage(后来开源),为开发者提供统一的服务目录、部署流水线和基础设施自助服务。开发者无需直接操作 kubectl,而是通过 Backstage 的 UI 或声明式配置文件管理服务。
自定义 Operator:Spotify 开发了多个自定义 Operator 来管理特定领域的运维自动化:
- Flink Operator:管理 Apache Flink 流处理作业的生命周期。
- GCS Proxy Operator:管理 Google Cloud Storage 代理实例。
- Certificate Operator:自动化内部 TLS 证书的签发与轮换。
10.4 遇到的挑战与解决方案
挑战一:etcd 性能瓶颈
当单集群节点数超过 2000 时,etcd 的写入延迟从平均 5ms 上升到 30ms 以上,偶发超过 100ms。Spotify 采取的措施包括:
- 将 Event 资源分离到独立的 etcd 集群,减少主 etcd 约 30% 的写入量。
- 为 etcd 节点配备 NVMe SSD,P99 写入延迟降至 8ms 以下。
- 设置 apiserver
限流参数:
--max-requests-inflight=800、--max-mutating-requests-inflight=400。
挑战二:Pod 调度延迟
在高峰期,新 Pod 的调度延迟(从创建到绑定节点)可达 15 秒以上。优化措施:
- 启用调度器的 percentageOfNodesToScore 参数(设为 30%),在大集群中不需要遍历所有节点。
- 预热节点池:保持一定数量的空闲节点,避免等待节点自动扩缩容(Cluster Autoscaler)。
- 使用 Pod 优先级(PriorityClass)确保关键服务优先调度。
挑战三:大规模配置管理
6000 个微服务的配置管理极具挑战性。Spotify 采用 GitOps 方式,所有集群配置存储在 Git 仓库中,通过 ArgoCD 同步到集群。每次配置变更都会触发 CI/CD 流水线中的策略检查(OPA/Gatekeeper),拒绝不符合规范的配置。
10.5 关键指标
迁移到 Kubernetes 后,Spotify 报告了以下改进:
- 部署频率提升 5 倍:从日均 2000 次提升到 10000 次以上。
- 部署失败率降低 60%:得益于滚动更新和自动回滚。
- 资源利用率提升 40%:通过 bin-packing 和自动扩缩容。
- 新服务上线时间从数周缩短到数小时。
十一、K8s 架构决策 Trade-off 分析
11.1 部署方式对比
| 维度 | 自建 K8s(kubeadm/kubespray) | 托管 K8s(EKS/GKE/AKS) | 轻量 K8s(k3s/microK8s) |
|---|---|---|---|
| 控制面管理 | 完全自主,需维护 etcd、apiserver 等 | 云厂商托管,用户无需关注 | 内嵌 SQLite/DQLite 替代 etcd |
| 运维复杂度 | 高:证书轮换、版本升级、etcd 备份 | 低:一键升级,自动备份 | 极低:单二进制安装 |
| 成本 | 基础设施成本 + 人力运维成本 | 控制面费用(约 $70-150/月)+ 节点费用 | 极低,适合边缘场景 |
| 最大集群规模 | 视运维能力而定,通常 5000 节点以内 | EKS/GKE 支持 15000 节点 | 建议 500 节点以内 |
| 可定制性 | 完全可控:可修改任何组件参数 | 有限:部分参数由云厂商锁定 | 有限:精简了部分功能 |
| API 兼容性 | 完整的上游 Kubernetes API | 完整兼容 + 云厂商扩展 | 完整兼容(k3s 通过 CNCF 一致性认证) |
| etcd 可靠性 | 自行保障:备份、监控、恢复 | 云厂商保障 SLA(通常 99.95%) | 使用 SQLite,不适合多节点高可用 |
| 版本更新速度 | 最快:上游发布即可升级 | 延迟 1-3 个月 | 紧跟上游,通常延迟 1-2 周 |
| 适用场景 | 大型企业私有云、强合规要求 | 大多数生产工作负载 | 边缘计算、IoT、开发测试、CI/CD |
| 典型用户 | 金融机构、电信运营商 | 互联网公司、中小企业 | 边缘节点、树莓派、本地开发 |
11.2 关键架构决策分析
决策一:中心化 API Server 还是去中心化通信?
Kubernetes 选择了中心化 API Server 方案。所有组件间通信都经过 apiserver 中转,而非点对点通信。这一决策的 trade-off:
- 优势:统一的认证鉴权、审计日志、准入控制,简化了安全模型。
- 代价:apiserver 成为性能瓶颈和可用性单点,大规模集群需要精心调优。
决策二:etcd 还是其他存储后端?
Kubernetes 深度依赖 etcd 的 watch 机制和强一致性。社区曾讨论过支持其他后端(如 PostgreSQL、CockroachDB),k3s 项目使用 SQLite/DQLite 作为替代方案。
- etcd 优势:watch 机制原生支持、毫秒级变更通知、强一致性保证。
- etcd 代价:运维复杂、对磁盘延迟敏感、数据库大小限制。
- 替代方案的局限:关系型数据库的 watch 实现效率远低于 etcd 原生 watch。
决策三:声明式 API 还是命令式 API?
声明式 API 是 Kubernetes 最核心的设计决策:
- 优势:天然幂等、支持自愈、GitOps 友好、Reconciliation Loop 可以无限重试。
- 代价:即时反馈较弱(用户提交后不知道何时生效)、调试困难(需要理解控制器的状态机)、部分场景不直观(如一次性任务的声明式表达)。
决策四:控制器单进程还是多进程?
kube-controller-manager 将数十个控制器打包在一个进程中:
- 优势:降低部署复杂度、共享 Informer 缓存减少 API Server 压力。
- 代价:一个控制器的 bug 可能影响所有控制器、难以对单个控制器独立扩展。
11.3 网络方案对比
| 维度 | Calico | Cilium | Flannel |
|---|---|---|---|
| 数据面 | iptables 或 eBPF | eBPF 原生 | VXLAN 或 host-gw |
| 网络策略 | 支持(NetworkPolicy + 扩展策略) | 支持(L3/L4/L7 策略) | 不支持 |
| 性能 | 高(BGP 模式下无封装开销) | 最高(eBPF 绕过 iptables) | 中等 |
| 可观测性 | 中等 | 优秀(Hubble 提供 L7 可视化) | 基础 |
| 复杂度 | 中等 | 较高 | 低 |
| 多集群 | 支持(Calico Federation) | 支持(ClusterMesh) | 不支持 |
| 适用场景 | 通用生产环境 | 高性能/安全敏感环境 | 小规模/简单场景 |
十二、生产环境最佳实践
12.1 资源管理
每个容器都应设置资源请求(requests)和限制(limits):
resources:
requests:
cpu: "250m" # 调度依据:确保节点有足够资源
memory: "256Mi" # 调度依据:确保节点有足够内存
limits:
cpu: "1000m" # 硬限制:超过则被限流(throttle)
memory: "512Mi" # 硬限制:超过则被 OOM KillQoS(Quality of Service)等级由 requests 和 limits 的配置决定:
| QoS 等级 | 配置条件 | 驱逐优先级 |
|---|---|---|
| Guaranteed | 所有容器的所有资源都设置了 requests = limits | 最低(最后被驱逐) |
| Burstable | 至少一个容器设置了 requests,但不满足 Guaranteed 条件 | 中等 |
| BestEffort | 没有任何容器设置 requests 或 limits | 最高(最先被驱逐) |
12.2 健康检查配置
containers:
- name: app
livenessProbe: # 存活探针:失败则重启容器
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
readinessProbe: # 就绪探针:失败则从 Service 端点移除
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
startupProbe: # 启动探针:启动期间保护慢启动应用
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30 # 允许 150 秒启动时间12.3 Pod 中断预算
PodDisruptionBudget(PDB)保障在自愿中断(节点维护、滚动升级)期间的服务可用性:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2 # 至少保持 2 个 Pod 可用
# 或使用 maxUnavailable: 1 # 最多 1 个 Pod 不可用
selector:
matchLabels:
app: web12.4 安全加固
生产环境的安全加固清单:
- Pod 安全标准(Pod Security Standards):使用 Restricted 级别限制容器权限。
- 网络策略(NetworkPolicy):默认拒绝所有入站流量,按需开放。
- RBAC 最小权限:遵循最小权限原则,避免使用 cluster-admin。
- 镜像安全:只允许从受信仓库拉取镜像,启用镜像签名验证。
- Secret 加密:启用 etcd 静态加密(EncryptionConfiguration),使用外部密钥管理系统(如 Vault)。
- 审计日志:启用 API 审计日志,记录所有写操作。
# 网络策略:默认拒绝所有入站,只允许同 namespace 的流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}十三、总结与展望
Kubernetes 架构的核心设计理念可以归纳为三个关键词:声明式、控制器驱动、可扩展。
声明式 API 使得系统天然具备幂等性和自愈能力,用户只需描述期望状态,系统负责持续收敛。这一设计使得 GitOps、基础设施即代码等现代运维范式成为可能。
控制器模式 将所有状态管理逻辑抽象为”观察-比较-行动”的统一循环。kube-apiserver 作为中心枢纽,etcd 的 watch 机制作为事件驱动引擎,二者共同构成了整个系统的”神经中枢”。kube-apiserver 之所以是集群的”单点”,是因为它承载了认证、鉴权、准入控制、审计日志、watch 通知等所有横切关注点;etcd 的 watch 机制之所以能驱动声明式 API,是因为它提供了毫秒级的、有序的、可靠的变更通知机制,使控制器能够及时响应状态变化。
可扩展性 通过 CRD、Operator、Admission Webhook、调度框架等扩展点,使 Kubernetes 从容器编排平台演化为通用的分布式系统控制面。这种”平台的平台”定位是 Kubernetes 生态繁荣的根本原因。
未来的演进方向包括:Gateway API 逐步取代 Ingress 成为标准流量入口、Sidecar 容器的原生支持(KEP-753)、基于 eBPF 的网络和可观测性方案成为主流、以及多集群管理从工具碎片化走向标准化。
参考资料
- Abhishek Verma, Luis Pedrosa, Madhukar Korupolu, David Oppenheimer, Eric Tune, John Wilkes. “Large-scale cluster management at Google with Borg.” Proceedings of the European Conference on Computer Systems (EuroSys), ACM, 2015.
- Brendan Burns, Brian Grant, David Oppenheimer, Eric Brewer, John Wilkes. “Borg, Omega, and Kubernetes.” Communications of the ACM, Vol. 59, No. 5, May 2016.
- Kubernetes Official Documentation. “Kubernetes Components.” https://kubernetes.io/docs/concepts/overview/components/
- etcd Official Documentation. “etcd architecture.” https://etcd.io/docs/
- Kubernetes Official Documentation. “Controlling Access to the Kubernetes API.” https://kubernetes.io/docs/concepts/security/controlling-access/
- Kubernetes Official Documentation. “Scheduling Framework.” https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/
- Kubernetes Official Documentation. “Custom Resources.” https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
- Spotify Engineering. “How We Use Kubernetes at Spotify.” KubeCon North America 2023.
- Spotify Engineering Blog. “Backstage: An Open Platform for Building Developer Portals.” https://backstage.io/
- CNCF. “Operator Framework.” https://operatorframework.io/
- k3s Official Documentation. “Architecture.” https://docs.k3s.io/architecture
- Cilium Documentation. “ClusterMesh - Multi Cluster Networking.” https://docs.cilium.io/en/latest/network/clustermesh/
上一篇:容器架构
下一篇:Serverless 架构
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【系统架构设计百科】配置管理架构:从配置文件到配置中心
配置应该放在代码里、环境变量里、还是配置中心里?本文从 12-Factor App 的配置理念出发,拆解配置的分层模型,深入分析 Apollo、Nacos、etcd 三大配置中心的架构与取舍,讨论动态配置灰度发布、配置加密与审计、Feature Flags 等工程实践。
【系统架构设计百科】架构质量属性:不只是"高可用高性能"
需求评审时写下的'高可用、高性能、高并发',到了架构设计阶段几乎无法落地——因为它们不是可执行的需求。本文从 SEI/CMU 的质量属性理论出发,用 stimulus-response 场景模型把模糊需求变成可量化、可验证的架构约束,并拆解属性之间的冲突与联动关系。
【系统架构设计百科】告警策略:如何避免"狼来了"
大多数团队的告警系统都在制造噪声而不是传递信号。阈值告警看似直观,实则产生大量误报和漏报,值班工程师在凌晨三点被叫醒,却发现只是一次无害的毛刺。本文从告警疲劳的工业数据出发,拆解基于 SLO 的多窗口燃烧率告警算法,深入 Alertmanager 的路由、抑制与分组机制,结合 PagerDuty 的告警疲劳研究和真实工程案例,给出一套可落地的告警策略设计方法。
【系统架构设计百科】复杂性管理:架构的核心战场
系统复杂性是架构腐化的根源——本文从 Brooks 的本质复杂性与偶然复杂性划分出发,结合认知负荷理论与 Parnas 的信息隐藏原则,系统阐述复杂性的来源、度量与控制手段,并给出可操作的架构策略