Kubernetes 控制面由多个独立进程组成:
kube-apiserver
kube-scheduler
kube-controller-manager
etcd
它们(包括 Kubelet)之间的关系:
Scheduler ───────────────┐
Controller Manager ──────┤
Kubelet ─────────────────┤
▼
API Server
│
▼
etcd
一、各组件的职责
API Server:
提供 API、认证、授权、校验、Watch 和对象存储
etcd:
保存 Kubernetes 集群状态
Scheduler:
为未绑定节点的 Pod 选择 Node
Controller Manager:
根据当前状态和期望状态执行控制循环
Kubelet:
在节点上启动和管理容器
API Server 不负责调度 Pod,也不负责启动容器。
二、各组件是独立进程
每个核心组件都是独立的 Go 程序。
cmd/kube-apiserver/apiserver.go
cmd/kube-scheduler/scheduler.go
cmd/kube-controller-manager/controller-manager.go
cmd/kubelet/kubelet.go
但 main() 通常只负责启动命令,不包含主要业务逻辑。
拿 API Server 的启动结构举例(几乎所有组件的启动代码类似):
// cmd/kube-apiserver/apiserver.go
package main
func main() {
command := app.NewAPIServerCommand()
code := cli.Run(command)
os.Exit(code)
}
实际调用链:
main()
↓
NewAPIServerCommand()
↓
RunE()
↓
加载配置
↓
创建 API Server
↓
创建 Storage 和 etcd client
↓
启动 HTTP Server
三、API Server 处理请求
以创建 Pod 为例:
HTTP 请求
↓
认证 / 授权 / Admission
↓
对象解析和校验
↓
资源 Storage
↓
通用 Store
↓
etcd
简化代码:
func Create(obj Object) {
validate(obj)
key := makeKey(obj)
data := encode(obj)
etcd.Put(key, data)
notifyWatchers(obj)
}
实际 API Server 会处理:
默认值
API 版本转换
字段校验
ResourceVersion
并发冲突
Admission
序列化
Watch 事件
四、API Server 如何连接 etcd
API Server 启动时读取 etcd 配置:--etcd-servers=https://127.0.0.1:2379
启动流程:
--etcd-servers
↓
EtcdOptions
↓
StorageBackendConfig
↓
创建 etcd client
↓
创建 Storage
↓
各资源复用 Storage
API Server 不会为每个请求重新创建 etcd 连接,而是在启动时创建并复用客户端。(其实就是平时写后端时候连接数据库那样)
在 kubeadm 集群中,这个参数通常出现在:/etc/kubernetes/manifests/kube-apiserver.yaml
示例:
command:
- kube-apiserver
- --etcd-servers=https://127.0.0.1:2379
五、其他组件如何找到 API Server
Scheduler、Controller Manager 和 Kubelet 通常使用 kubeconfig。
Scheduler:--kubeconfig=/etc/kubernetes/scheduler.conf
Controller Manager:--kubeconfig=/etc/kubernetes/controller-manager.conf
各个组件的 kubeconfig 中保存 API Server 地址:
clusters:
- cluster:
server: https://127.0.0.1:6443
因此:
scheduler.conf
↓
kube-scheduler
↓
https://127.0.0.1:6443
↓
kube-apiserver
Controller Manager 也是同样的方式。
六、创建 Pod 的完整流程
- 客户端请求 API Server
- API Server 校验 Pod
- API Server 将 Pod 写入 etcd
- API Server 产生 Pod 事件
- Scheduler Watch 到 Pod
- Scheduler 选择 Node
- Scheduler 通过 API Server 绑定 Pod
- API Server 更新 etcd
- Kubelet Watch 到分配给自己的 Pod
- Kubelet 启动容器
- Kubelet 更新 Pod Status
- API Server 将 Status 写入 etcd
七、Watch 是什么
Watch 是一个长期保持的 HTTP 请求:GET /api/v1/pods?watch=true
它不是多次 HTTP 响应,而是:
一次请求
↓
一次响应
↓
响应 Body 不关闭
↓
持续写入事件
事件类似:
{"type":"ADDED","object":{}}
{"type":"MODIFIED","object":{}}
{"type":"DELETED","object":{}}
简化代码:
func Watch(w http.ResponseWriter, events <-chan Event) {
flush := w.(http.Flusher)
for event := range events {
writeJSON(w, event)
flush.Flush()
}
}
Kubernetes Watch 不是标准 SSE,而是 HTTP Streaming。
八、Watch 的事件链路
etcd
↓
API Server Watch Cache
↓
API Server 内部 Go channel
↓
HTTP Watch 长连接
↓
Scheduler / Controller Manager / Kubelet
不同层使用的通信方式:
API Server 内部:
Go channel
API Server 与其他组件之间:
HTTP 长连接
API Server 与 etcd 之间:
etcd client / gRPC
Scheduler 和 Controller Manager 不直接监听 etcd,而是监听 API Server。
九、Scheduler 的逻辑
for event := range watchPods() {
pod := event.Object
if pod.NodeName == "" {
node := chooseNode(pod)
bindPod(pod, node)
}
}
实际链路:
Scheduler Watch Pod
↓
发现 Pod 没有 Node
↓
选择 Node
↓
通过 API Server 更新 Pod
↓
API Server 写入 etcd
十、Controller Manager 的逻辑
Controller Manager 内部运行多个 Controller:
Deployment Controller
ReplicaSet Controller
Node Controller
Job Controller
控制循环:
for event := range watchResources() {
desired := calculateDesiredState(event)
updateThroughAPIServer(desired)
}
例如副本不足:
Controller Watch Deployment
↓
发现副本数不足
↓
创建或调整 ReplicaSet
↓
ReplicaSet 创建 Pod
↓
API Server 写入 etcd
十一、最终模型
etcd:
保存集群状态
API Server:
提供统一 API
读写 etcd
维护 Watch
分发资源变化
Scheduler:
监听未调度 Pod
选择 Node
Controller Manager:
Watch 各类资源
执行控制循环
通过 API Server 创建、修改、删除对象
Kubelet:
执行 Pod
更新运行状态
完整链路:
etcd
↓
API Server
↓ HTTP Watch
Scheduler / Controller Manager / Kubelet
↓
控制逻辑
↓ HTTP REST
API Server
↓
etcd
一句话:
API Server 是控制面的中枢,etcd 保存状态,Scheduler 和 Controller Manager 是独立的 Go 进程。它们通过 kubeconfig 找到 API Server,通过 HTTP Watch 获取事件,再通过 API Server 修改集群状态。
