【注】源码分析均以 k8s 的第一个 commit 代码分析;
接上一篇 01-01 接着说;
上一篇主要是讲 pkg/registry 中的代码,这一节将主要讲 pkg/apiserver 中的代码实现;
通过上一篇的讲解,整个 api-server 的整体架构有一个简单的认识;
api-server 下的 RESTStorage 接口,有六个方法;
代码语言:go复制// RESTStorage is a generic interface for RESTful storage services
type RESTStorage interface {
List(*url.URL) (interface{}, error)
Get(id string) (interface{}, error)
Delete(id string) error
Extract(body string) (interface{}, error)
Create(interface{}) error
Update(interface{}) error
}
还有个
代码语言:go复制// TODO: consider migrating this to go-restful which is a more full-featured version of the same thing.
type ApiServer struct {
prefix string
storage map[string]RESTStorage
}
ApiServer 的结构体,主要是用于 resetful 的请求:
- prefix 是请求的 URL 路径;
- storage 是实现的 RESTStorage 接口;
pkg/registry
reistry 目录中的注册表:
先来分析下目录下提供的接口信息:
代码语言:go复制type TaskRegistry interface {}
type ControllerRegistry interface {}
type ServiceRegistry interface {}
主要是这三个接口:
- task
- controller
- service
再来看下,这些接口都有哪些实现:
1)TaskRegistry
代码语言:go复制// TaskRegistryStorage implements the RESTStorage interface in terms of a TaskRegistry
type TaskRegistryStorage struct {
registry TaskRegistry
containerInfo client.ContainerInfo
scheduler Scheduler
}
2)ControllerRegistry
代码语言:go复制// Implementation of RESTStorage for the api server.
type ControllerRegistryStorage struct {
registry ControllerRegistry
}
3)ServiceRegistry
代码语言:go复制type ServiceRegistryStorage struct {
registry ServiceRegistry
}
再重新分析 main() 函数中的这些接口的实例化:
代码语言:go复制if len(etcdServerList) > 0 {
log.Printf("Creating etcd client pointing to %v", etcdServerList)
etcdClient := etcd.NewClient(etcdServerList)
taskRegistry = registry.MakeEtcdRegistry(etcdClient, machineList)
controllerRegistry = registry.MakeEtcdRegistry(etcdClient, machineList)
serviceRegistry = registry.MakeEtcdRegistry(etcdClient, machineList)
} else {
taskRegistry = registry.MakeMemoryRegistry()
controllerRegistry = registry.MakeMemoryRegistry()
serviceRegistry = registry.MakeMemoryRegistry()
}
1)传入了 etcd 节点的初始化:
这里可以看出,三个接口都是通过 MakeEtcdRegistry() 函数进行实例化,这个返回的实例实现了这个三个接口;
代码语言:go复制pkg/registry/etcd_registry.go
func MakeEtcdRegistry(client EtcdClient, machines []string) *EtcdRegistry {}
这里最重要的就是 EtcdRegistry{} 结构体:
代码语言:go复制// EtcdRegistry is an implementation of both ControllerRegistry and TaskRegistry which is backed with etcd.
type EtcdRegistry struct {
etcdClient EtcdClient
machines []string
manifestFactory ManifestFactory
}
通过上面的注释也可以看出,这个结构体实现了这几个接口;(包括 ServiceRegistry{} 接口)
- ListTasks():列出所有节点上符合标签的任务信息;
代码语言:go复制ListTasks(query *map[string]string) ([]Task, error)
(每个任务都有 label 标签)
这个方式是通过
代码语言:go复制key := "/registry/hosts/" machine "/tasks"
从 etcd 中查询每个 machine 下的任务信息;每个节点的任务信息都是会同步到 etcd 中;
- GetTask():根据任务 ID 获取单个任务信息;
代码语言:go复制GetTask(taskID string) (*Task, error)
任务都是存在 etcd 中,根据 key 获取:
代码语言:go复制"/registry/hosts/" machine "/tasks/" taskID
这里简单介绍下这里的实现逻辑:
-- 首先遍历每个节点下的所有任务信息;
-- 根据任务 ID 拼接的 key 查询 etcd 中的写任务信息;
-- 将当前查询到的节点 IP 信息填入 Task 中并返回;
- ListControllers():获取 controller 列表信息;
代码语言:go复制ListControllers() ([]ReplicationController, error)
首先根据 key, 列出所有 Node(etcd 中存储的节点) 信息:
代码语言:go复制key := "/registry/controllers"
- CreateTask():创建任务
CreateTask(machineIn string, task Task) error {}
传入节点信息和 task 信息;
-- 判断任务是否在存在,存在直接报错返回;
代码语言:go复制registry.findTask(task.ID)
-- 运行任务
代码语言:go复制registry.runTask(task, machineIn)