kube-apiserver 核心实现 (一)
一、概述
kube-apiserver 组件负责将 kubernetes 的 “资源组,资源版本,资源” 以RESTful 风格的形式对外暴露服务。也是 kubernetes集群中各组件之间沟通的桥梁。
以在 kubernetes 集群中一个 pod 资源对象创建流程为例,如图:
Kubernetes Pod 资源对象创建流程如下:
- 使用 kubectl 工具向 API server 发起创建 Pod 资源对象的请求,在这个过程中会经过一系列的权限认证,包括客户端的认证,rbac 权限检查和 Pod 配置中字段的验证与默认值设置。
- API server 验证请求并将其持久保存到 ETCD 集群中。
- API server 基于 Watch 机制通知 kube-scheduler 调度器。
- kube-scheduler 调度器根据预选,优选调度算法为 Pod 资源对象选择最优的节点并通知 API server。
- API server 将最优节点的配置持久化保存到 Etcd 集群中。
- kubelet 组件在所在节点上通过与容器运行时交互创建容器。
- kubelet 将容器状态上报至 api server。
- API server 将容器状态持久化到 Etcd 集群中。
二、go-restful 核心原理
go-restful (https://github.com/emicklei/go-restful)
2. 1 go-restful 介绍
在 kubernetes 源码中使用了 go-restful 框架,主要原因在于 go-restful 框架可定制程度高,go-restful 设计逻辑如图:
go-restful 框架支持多个 container,对应着一个 Http server, 每个 container 可以包含多个 web service, web service 就是多个不同类别服务的集合。一个 web service 包含多个 route, 当请求的 url 匹配到相应 route 就会执行该 route 对应的处理函数(handler func)
Note: go-restful 框架中的 Container, 并非指 Docker 容器,仅是 go-resful 框架中的定义。
2.2 go-restful 数据结构与原理
go-restful 核心数据结构如下:
核心原理即将 Container 接收的请求分发匹配的 WebService,再由 WebService 分发给 Router 中的 Handle 函数。
代码示例:
// Dispatch the incoming Http Request to a matching WebService.
func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) {
...
// Find best match Route ; err is non nil if no match was found
var webService *WebService
var route *Route
var err error
func() {
c.webServicesLock.RLock()
defer c.webServicesLock.RUnlock()
webService, route, err = c.router.SelectRoute(
c.webServices,
httpRequest)
}()
...
// no filters, handle request by route
route.Function(wrappedRequest, wrappedResponse)
}
...
}
dispatch 函数进行分发的过程分为两步:
- 使用
c.router.SelectRoute
方法,根据请求匹配到最优的WebService
和route
组合(?WebService->?route
,其中包含两种 RouterSelector, 分别是 RouterJSR311 和 CurlyRouter, CurlyRouter 是基于 RouterJSR311 实现的,在其基础上支持正则表达式和动态参数。go-restful 框架默认使用 CurlyRouter - 根据请求路径调用对应的 Handler 函数,执行 route.Function 函数。
2.3 示例代码
package main
import (
"io"
"log"
"net/http"
restful "github.com/emicklei/go-restful/v3"
)
func main() {
// 实例化 WebService
ws := new(restful.WebService)
// 为 WebService 定义一条 route, 在 route 中指定请求方法
// 路径、请求路径,和 Handler 函数
ws.Route(ws.GET("/hello").To(hello1))
restful.Add(ws)
go func() {
log.Fatal(http.ListenAndServe(":8080", nil))
}()
// 实例化 Container
container2 := restful.NewContainer()
ws2 := new(restful.WebService)
ws2.Route(ws2.GET("/hello").To(hello2))
// 添加 WebService 到 Container 中
container2.Add(ws2)
server := &http.Server{
Addr: ":8081",
Handler: container2,
}
log.Fatal(server.ListenAndServe())
}
// Handler 函数方法接收 request 和 response,并与用户进行数据交互
func hello1(req *restful.Request, resp *restful.Response) {
io.WriteString(resp, "default world\n")
}
func hello2(req *restful.Request, resp *restful.Response) {
io.WriteString(resp, "second world\n")
}
在 main 函数中如果未实例化 Container, 那么默认会使用 restful.DefaultContainer
和 DefaultServeMux
,可以通过 restful.NewContainer()
函数来创建一个 container, 如上代码所示。
运行上述程序,将会监控 8080
和 8081
两个端口,当我们发送 GET 请求到 http://localhost:8080/hello
时,会返回 default world
, 而 http://localhost:8081/hello
会返回 second world
。
三 访问 API server 一次 HTTP 请求的完整周期
如图:
一次 Http 请求的完整周期:
- 用户向 API server 发出 Http 请求
- API server 接收到用户发出的请求
- API server 启用 goroutine 处理接收到的请求
- API server 验证请求内容中的认证信息
- API server 解析请求内容
- API server 调用路由条目对应的处理函数
- API server 获取经Handler处理过的的数据信息
- API server 设置请求状态码
- API server 响应用户的请求
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!