惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
罗磊的独立博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Last Week in AI
Last Week in AI
云风的 BLOG
云风的 BLOG
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
A
About on SuperTechFans
WordPress大学
WordPress大学
B
Blog
Martin Fowler
Martin Fowler
Jina AI
Jina AI
I
InfoQ
P
Proofpoint News Feed
小众软件
小众软件
S
SegmentFault 最新的问题
V
V2EX
B
Blog RSS Feed
量子位
大猫的无限游戏
大猫的无限游戏
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
MongoDB | Blog
MongoDB | Blog
美团技术团队

Posts on WKLKEN THINKING

apisix 中的 lrucache apisix 中的服务发现机制 apisix 中的负载均衡 apisix etcd机制 聊聊框架 关于 k8s 的 zero downtime deployment 一些建议 apisix 遇到的一些问题 关于在除夕前一天换了一个洗衣机的故事 Django DRF 性能优化 DRF 的一些实践 Part1: Serializer DRF继承关系图 Better Code: 关于接口的灵活性 新的仓库: wklken/naming 缓存使用的一些经验 Better Code: 抽象: 可扩展性与可维护性的抉择 Better Code: 异常时, 该提示用户哪些信息? Better Code: 更好的异常日志打印 Go: some libs Go: go-redis/cache升级的坑 Go: logrus性能提升 Go: gin validation 远程办公的一点总结 Go: 开发过程中的一些bug 项目管理实践: 风险驱动开发 Go: 一种error wrap调用链处理方式 漫谈技术选型 Go: 基于 apitest 做handler层单元测试 Go: go-sql-driver interpolateparams参数优化 [分享]深度工作 你需要更多的思考时间
k8s APIServer源码: 服务启动
2017-09-23 · via Posts on WKLKEN THINKING

基于版本 1.6.7

启动流程

  • cmd/kube-apiserver/apiserver.go
func main() {
   app.Run(s)
}
  • cmd/kube-apiserver/app/server.go
func Run(s *options.ServerRunOptions) error {
	// 构建master配置信息
	config, sharedInformers, err := BuildMasterConfig(s)
	// 调用RunServer
	return RunServer(config, sharedInformers, wait.NeverStop)
}

func RunServer(config *master.Config, sharedInformers informers.SharedInformerFactory, stopCh <-chan struct{}) error {
	// 执行相关初始化
	m, err := config.Complete().New()     // => TO: Container初始化
	// 启动
	return m.GenericAPIServer.PrepareRun().Run(stopCh)  // => next
}
  • vendor/k8s.io/apiserver/pkg/server/genericapiserver.go

启动主体函数都在这个文件中, 绑定地址/端口号, 并最终启动

func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error {
	s.NonBlockingRun(stopCh)
}

func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
	s.serveSecurely(internalStopCh)
	// or
	s.serveInsecurely(internalStopCh) // => next
}
  • vendor/k8s.io/apiserver/pkg/server/serve.go
func (s *GenericAPIServer) serveInsecurely(stopCh <-chan struct{}) error {
	insecureServer := &http.Server{
		Addr:           s.InsecureServingInfo.BindAddress,
		Handler:        s.InsecureHandler,   // s.Hnalder for secure
		MaxHeaderBytes: 1 << 20,
	}
   runServer(insecureServer, s.InsecureServingInfo.BindNetwork, stopCh) // => next
}


func runServer(server *http.Server, network string, stopCh <-chan struct{}) (int, error) {
	go func() {
		for {
			var listener net.Listener
			listener = tcpKeepAliveListener{ln.(*net.TCPListener)}
			// *http.Server
			err := server.Serve(listener)
			}
	}()
}

Container初始化

  • cmd/kube-apiserver/app/server.go
func RunServer(config *master.Config, sharedInformers informers.SharedInformerFactory, stopCh <-chan struct{}) error {
	// 执行相关初始化
	m, err := config.Complete().New()     // => TO: Container初始化
	// 启动
	return m.GenericAPIServer.PrepareRun().Run(stopCh)  // => next
}
  • kubernetes/pkg/master/master.go
func (c completedConfig) New() (*Master, error) {
   // m.GenericAPIServer.HandlerContainer = APIContainer,   APIContainer.Container =  restful.NewContainer()
	s, err := c.Config.GenericConfig.SkipComplete().New() // completion is done in Complete, no need for a second time
   m := &Master{
		GenericAPIServer: s,
	}
}
  • vendor/k8s.io/apiserver/pkg/server/config.go

到这里, 完成了 s.Handler, s.InsecureHandler 的初始化

func (c completedConfig) New() (*GenericAPIServer, error) {
  s := &GenericAPIServer{
  }
  // s.HandlerContainer = APIContainer
  	s.HandlerContainer = mux.NewAPIContainer(http.NewServeMux(), c.Serializer)  // => next 1

  // 生成 Handler
  	s.Handler, s.InsecureHandler = c.BuildHandlerChainsFunc(s.HandlerContainer.ServeMux, c.Config)  // => next 2
}
  • 1: vendor/k8s.io/apiserver/pkg/server/mux/container.go

新建一个APIContainer, 包含

// NewAPIContainer constructs a new container for APIs
func NewAPIContainer(mux *http.ServeMux, s runtime.NegotiatedSerializer) *APIContainer {
	c := APIContainer{
		// 新建一个Container
		Container: restful.NewContainer(),
		NonSwaggerRoutes: PathRecorderMux{
			mux: mux,
		},
		UnlistedRoutes: mux,
	}
	// 配置 http.ServerMux
	c.Container.ServeMux = mux
	// 配置路由方式, 使用CurlyRouter
	c.Container.Router(restful.CurlyRouter{}) // e.g. for proxy/{kind}/{name}/{*}
	return &c
}
  • 2: vendor/k8s.io/apiserver/pkg/server/config.go
type Config struct {
	BuildHandlerChainsFunc func(apiHandler http.Handler, c *Config) (secure, insecure http.Handler)
}


func NewConfig() *Config {
	return &Config{
			BuildHandlerChainsFunc:      DefaultBuildHandlerChain,
	}
}


func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) (secure, insecure http.Handler) {
	return generic(protect(apiHandler)), generic(audit(apiHandler)) // add filters to handler
}

注意, 这里传递的参数是: s.HandlerContainer.ServeMux, DefaultBuildHandlerChain的参数是apiHandler http.Handler, 前者包含后者interface定义的方法.

  • net/http/server.go
type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
}

// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
	if r.RequestURI == "*" {
		if r.ProtoAtLeast(1, 1) {
			w.Header().Set("Connection", "close")
		}
		w.WriteHeader(StatusBadRequest)
		return
	}
	h, _ := mux.Handler(r)
	h.ServeHTTP(w, r)
}

初始化后, Hnalder 以及 InsecureHandler赋值Container, 然后在new Server前, 将handler放入

&http.Server{
		Addr:           s.InsecureServingInfo.BindAddress,
		Handler:        s.InsecureHandler,   // s.Hanlder for secure
		MaxHeaderBytes: 1 << 20,
}