【K8s】api-server 源码分析 01-02

2022-06-19 15:41:39 浏览数 (1)

【注】源码分析均以 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():创建任务
代码语言:go复制
CreateTask(machineIn string, task Task) error {}

传入节点信息和 task 信息;

-- 判断任务是否在存在,存在直接报错返回;

代码语言:go复制
registry.findTask(task.ID)

-- 运行任务

代码语言:go复制
registry.runTask(task, machineIn)

0 人点赞