k8s first commit 源码分析之 API Server
阅读数:305穿越回 2014 年,分析下 k8s 第一个提交的源码。
获取 first commit 源码
1 | git clone https://github.com/kubernetes/kubernetes.git |
简介
api-server 是 k8s 的核心组件之一,用于接收 kubelet 的请求,并将请求信息保存到后端存储 etcd 中。核心功能是提供 k8s 各类资源对象的 CURD 等操作。
源码分析
从 api-server 的命令行入口开始分析,命令行代码位于 cmd/apiserver/apiserver.go
1 | var ( |
最开始定义了 api-server 启动所需要的相关参数,上古版本的 k8s 使用了标准库自带的 flag 库,其中 util.StringList
实现了flag.Value
接口。
1 | type StringList []string |
可以看到util.StringList
用于将以逗号分割的字符串转为[]string
类型。各个命令行参数含义如下:
- port: api-server 监听的 port
- address: api-server 监听的 ip
- apiPrefix: 访问 api-server 的 URL 前缀
- etcdServerList: 后端存储的 etcd 节点列表
- machineList: 工作节点的列表
从 main 函数开始分析 api-server 的具体实现
1 | var ( |
registry 是对具体资源对象的后端存储的抽象,这里定义了三个 registry,并根据命令行参数判断是使用 etcd 还是内存作为存储后端。
1 | // 代码路径:pkg/registry/interfaces.go |
其中taskRegistry
是对 task 的存储抽象,task 可以当作 pod 的前身看待,实现了对 task 的 list,get,create, update, delete 的操作。
1 | // 代码路径:pkg/registry/interfaces.go |
而ControllerRegistry
是对 RC(Replication Controller) 的存储抽象,而我们现在使用的较多的是 RS(RepicateSet), RS 正是 RC 的升级,同样是实现了对 RC 的 list,get,create,update,delete 操作。
1 | // 代码路径:pkg/registry/service_registry.go |
ServiceRegistry
是对 service 的存储抽象
1 | containerInfo := &kube_client.HTTPContainerInfo{ |
storge 是对所有资源的 registry 的统一抽象,被定义为 REST 风格的资源操作接口。
1 | // 代码路径: pkg/apiserver/api_server.go |
实例化所有资源的 storage 后放在 map 中维护,用于后面 handler 的处理。
1 | s := &http.Server{ |
使用前面的 REST Storage map 和 api prefix 创建 handler,启动 HTTP 服务器等待接收请求。接下来转到 handler 分析源码
1 | // 代码路径:pkg/apiserver/api_server.go |
Golang HTTP 的标准库是通过实现 Handler 接口的 ServeHTTP 函数来实现处理请求,通过代码可以看出先对请求的 URL 进行解析获取具体的资源对象,再通过 REST storage map 拿到对应资源对象的 REST storage,最后调用 server.handleREST
来处理具体的请求。
1 | // 代码路径:pkg/apiserver/api_server.go |
可以很清晰的看出,这段逻辑是根据请求方法和请求参数对实际的资源对象进行特定的 REST 的操作。
回到 main 函数,在启动 HTTP server 之前还启动了一个 goroutine 做定时任务
1 | endpoints := registry.MakeEndpointController(serviceRegistry, taskRegistry) |
其中 util.Forever
就是周期性任务的封装
1 | // 代码路径: pkg/util/util.go |
任务实体endpoints.SyncServiceEndpoints
逻辑如下
1 | // 代码路径: pkg/registry/endpoint.go |
可以看到主要逻辑就是定时获取所有 service 列表,再遍历 service 列表查询 service 下所有 task,最后根据 task 的 endpoint 来更新 service 的 endpoints。这一段逻辑其实就是为 kubeproxy 做负载均衡用的,让 kubeproxy 知道需要代理的 endpoint 有哪些。这一块逻辑在现在的 k8s 架构中已经从 api-server 中移除了。
笔者只分析了 api-server 主体的逻辑,后续会分析具体 registry 的逻辑。
本文链接: https://www.caiyifan.cn/p/c0ce3a49.html
版权声明: 本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!

v1.5.2