k8s :kube-apiserver 启动流程 - 1
前言看 k8s 源代码有一段时间,总感觉在迷宫里乱窜,有时候觉得终于找到出口了,一下子又撞墙了,总结下来还是自己的内功不够深厚,本文是对 kube-apiserver Legacy(遗留,即将废弃)API 初始化流程(以及数据结构)的一个梳理,算是做个"路标",便于以后在"迷宫"中还能找到回来的路 kube-apiserver 主要功能是提供 api 接口给客户端访问 后端 etcd 存储,当然这中间不光是简单的 key/value 存储,为了方便扩展,kube-apiserver 设计了一套代码框架将 "资源对象" 映射到 RESTful API 本文梳理了一下 kube-apiserver 启动流程和相关数据结构 k8s 代码更新比较快,本文基于 k8s release-1.9.x 代码 数据结构kube-apiserver 启动流程相关的(主要)数据结构
Options,Config 和 Server 对象的(大致)关系: ServerRunOptionsServerRunOptions 类封装了 kube-apiserver 命令行参数,这些参数按照不同的类别进行分组 // kubernetes/cmd/kube-apiserver/app/options/options.go import ( ... genericoptions "k8s.io/apiserver/pkg/server/options" ... ) type ServerRunOptions struct { GenericServerRunOptions *genericoptions.ServerRunOptions Etcd *genericoptions.EtcdOptions SecureServing *genericoptions.SecureServingOptions InsecureServing *kubeoptions.InsecureServingOptions ... } 我们重点看看 EtcdOptions,etcd 存储相关的配置,它和 kube-apiserver 如何访问后端 etcd 存储密切相关 EtcdOptionsStorageConfig 定义了 etcd 详细配置,比如 etcd 版本,key 公共前缀等 // kubernetes/vendor/k8s.io/apiserver/pkg/server/options/etcd.go type EtcdOptions struct { StorageConfig storagebackend.Config EncryptionProviderConfigFilepath string ... } // kubernetes/vender/k8s.io/apiserver/storage/storagebackend/config.o type Config struct { // Type defines the type of storage backend,e.g. "etcd2","etcd3" Type string // Prefix is the prefix to all keys passed to storage.Interface methods. Prefix string // ServerList is the list of storage servers to connect with ... } 创建《工厂方法》NewEtcdOptions 用于创建 EtcdOptions // kubernetes/cmd/kube-apiserver/app/options/options.go func NewServerRunOptions() *ServerRunOptions { s := ServerRunOptions { ... Etcd: genericoptions.NewEtcdOptions( storagebackend.NewDefaultConfig(kubeoptions.DefaultEtcdPathPrefix,nil)) ... } } ApplyWithStorageFactoryToEtcdOptions 有一个非常重要的方法 ApplyWithStorageFactoryTo 用于初始化 server.Config(服务配置类,见下文)的 RESTOptionsGetter 属性,该属性用于创建 etcd 后端存储(见下文) // kubernetes/vendor/k8s.io/apiserver/pkg/server/options/etcd.go func (s *EtcdOptions) ApplyWithStorageFactoryTo( factory server storage.StorageFactory,c *server.Config) error { s.RESTOptionsGetter = &storageFactoryRestOptionsFactory{ Options: *s,StorageFactory: factory } } // kubernetes/pkg/kubeapiserver/options/storage_versions.go const ( DefaultEtcdPathPrefix = "/registry" ) server.ConfigConfig is a structure used to configure a GenericAPIServer // kubernetes/vender/k8s.io/apiserver/pkg/server/config.go type Config struct { ... // 这个字段很重要,标记一下 RESTOptionsGetter generic registry.RESTOptionsGetter ... } 创建《工厂方法》NewConfig 创建 server.Config 实例,该方法只是给 server.Config 的一些字段赋予一些默认值,《构建方法》BuildGenericConfig 对剩余的字段进行初始化 func BuildGenericConfig(s *options.ServerRunOptions,proxyTransport *http.Transport) (...) { //《工厂方法》 genericConfig := genericapiserver.NewConfig(legacy scheme.Codecs) ... // 将 ServerRunOptions.SecureServing "应用" 到 server.Config if err := s.SecureServing.ApplyTo(genericConfig); err 1= nil { ... } } 方法体中还有很多 ApplyTo 函数调用,基本都是将 ServerRunOptions 中的字段 "应用" 到 server.Config GenericAPIServerGenericAPIServer contains state for a Kubernetes cluster api server type GenericAPIServer struct { ... } MasterMaster contains state for a Kubernetes cluster master/api server type Master struct { GenericAPIServer *genericapiserver.GenericAPIServer ClientCARegistrationHook ClientCARegistrationHook } APIAggregatorAPIAggregator contains state for a Kubernetes cluster master/api server type APIAggregator struct { GenericAPIServer *genericapiserver.GenericAPIServer ... } kube-apiserver 启动流程kube-apiserver 入口在 kubernetes/cmd/kube-apiserver/apiserver.go PS:通过以下命令可以(单独)构建 kube-apiserver # export GOPATH=/opt/kubernetes-src/ # cd $GOPATH/src/k8s.io/kubernetes # make WHAT=cmd/kube-apiserver all // kubernetes/cmd/kube-apiserver/apiserver.go import( ... "k8s.io.kubernetes/cmd/kube-apiserver/app" ... ) func main() { rand.Seed(time.Now().UTC().UnixNano()) // 解析命令行参数 s := options.NewServerRunOptions() s.AddFlags(pflag.CommandLine) flag.InitFlags() // 初始化 log logs.InitLogs() defer logs.FlushLogs() ... stopCh := server.SetupSignalHandler() if err := app.Run(s,stopCh); err != nil { fmt.FPrintf(os.Stderr,"%vn",err) os.Exit(1) } } main 函数只是个壳子,解析完命令行参数后会调用 app 包中的 Run 函数 // kubernetes/cmd/kube-apiserver/app.server.go func Run(runOptions *options.ServerRunOptions,stopCh <-chan struct{}) error { ... server,err := CreateServerChain(runOptions,stopCh) if err != nil { return err } return server.PrepareRun().Run(stopCh) } CreateServerChain 函数使用了《责任链》模式,多个 server 组成一个链条,紧密相连,给客户端提供 RESTful API 服务 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |