kube-apiserver

时间:July 26, 2020 分类:

目录:

kube-apiserver

kube-apiserver是Kubernetes与etcd交互的组件,主要有几个功能

  • 提供Kubernetes API,包括认证授权,数据校验,集群状态变更等,提供Client和其他组件调用
  • 代理集群中的一些附加组件组件,如Kubernetes UI、metrics-server、npd等
  • 创建kubernetes服务,即提供apiserver的Service,kubernetes Service
  • 资源在不同版本的转换

kube-apiversion的处理流程

kube-apiserver的接口有三种

  • core group:主要在/api/v1下,例如/api/v1/nodes, /api/v1/pods, /api/v1/service
  • named group:path为/apis/$NAME/$VERSION,例如/apis/bratch/v1/jobs
  • 暴露的系统状态API:/metrics/healthz

一个POST请求举例,到达apiserver

  1. 执行http filter chain中注册的过滤器链,进行过滤,包括认证和鉴权等
  2. 进入route对应的handler,handler的主要操作是与etcd交互
  3. 解码(decoder)传入的参数,转为internal version
  4. 检查是否使用全局约束条件(Admission)来检查是否可以创建或更新对象
  5. 检查字段合法性
  6. 转换写入etcd

http filter chain

在代码的server/config.go主要方法有

  • WithRequestInfo
  • MaxInfightLimit
  • TimeoutForNonLongRunningRequests
  • PanicRecovery
  • CORS
  • Authentication
  • Audit
  • Impersonation
  • Authorization

decoder

kubernetes的resource会有一个internal version

因为在开发过程中,一个resource会对应多个version,为了避免kube-apiserver必须知道如何在每个版本转换,使用internal version作为通用的version,会包含所有version的字段。在decoder过程中将object转化为internal version,最后转为一个storage version,存储在etcd中

解码的过程是获取path中期待的version,使用scheme以正确的version创建对象,再使用json或protobuf解码转化,并补全省略的字段

Admission

在解码完成后,需要通过验证集群的全局约束来检查是否可以创建或更新对象,并根据集群配置设置默认值。在k8s.io/kubernetes/plugin/pkg/admission 目录下可以看到kube-apiserver可以使用的所有全局约束插件,kube-apiserver在启动时通过设置--enable-admission-plugins参数来开启需要使用的插件,通过ValidatingAdmissionWebhook或MutatingAdmissionWebhook添加的插件也都会在此处进行工作。

kube-apiserver的组件

包括三个组件

  • Aggregator
  • KubeAPIServer,用于通用认证,授权和处理内建资源的Rest请求
  • APIExtensionServer,用于CRD和CR的Rest请求

Aggregator

Aggregator包括一个GenericAPIServer和维护自身状态的Controller

GenericAPIServer主要是处理apiregistration.k8s.io下的资源请求

  • apiserviceRegistrationController 负责APIServer中的资源注册与删除
  • availableConditionController 维护APIServer的可用状态
  • autoRegistrationController 保持API中一组特定的APIServices
  • crdRegistrationController CRD字段的注册
  • openAPIAggregationController 资源变化同步到Openapi文档

metrics-server也是通过Aggregator进行扩展的,官方工具apiserver-builder

KubeApiServer

提供对API的操作请求的接收,注册API的路由,暴露Restful接口

APIExtensionServer

负责处理使用CRD定义的资源

  • openapiController 负责crd资源的变化同步至提供的OpenAPI文档,path为/openapi/v2
  • crdController 将CRD注册到apiVersions和apiResources中,可以通过kubectl api-versionskubectl api-resources查看
  • namingController 检查CRD是否存在命名冲突
  • establishingController 检查CRD是否正常
  • nonStructuralSchemaController 检查CRD结构是否正常
  • apiApprovalController 检查CRD是否遵循Kubernetes API声明
  • finalizingController 删除CRD相关

kube-apiserver启动流程

Run方法的逻辑

k8s.io/kubernetes/cmd/kube-apiserver/app/server.go的Run方法

  1. 调用CreateServerChain构建服务调用链,判断是否使用https,并为server注册路由
  2. 调用server.PrepareRun进行服务启动前的准备,包括健康检测,存活检测和openapi的注册
  3. 调用prepared.Run启动http服务

CreateServerChain完成初始化的方法,分别初始化APIExtensionsServer,KubeAPIServer和AggregatorServer

  1. 调用CreateKubeAPIServerConfig创建KubeAPIServer的配置
  2. 如果启动了扩展APIServer调用createAPIExtensionsConfig创建APIExtensionsServer的配置
  3. 调用createAPIExtensionsServer初始化apiExtensionsServer
  4. 调用CreateKubeAPIServer初始化kubeAPIServer
  5. 调用createAggregatorConfig创建aggregatorServer的配置
  6. 调用createAggregatorServer初始化aggregatorServer
  7. 判断是否使用https

CreateKubeAPIServerConfig的配置初始化操作

  1. 主要使用buildGenericConfig构建
  2. 设置genericConfig默认值
  3. 初始化storageFactory
  4. 初始化RESTOptionsGetter(etcd的操作句柄)
  5. 设置使用protobufs用来内部交互,并且禁用压缩功能
  6. 创建clientset
  7. 创建认证实例BuildAuthenticator,包括Header,Auth文件,Ca证书,Token,ServiceAccount认证,BootstrapToken认证等
  8. 创建鉴权实例BuildAuthorizer,包括Node,RBAC,AlwaysAllow,AlwaysDeny,Webhook
  9. 审计插件的初始化Audit.ApplyTo()
  10. 准入插件的初始化Admission.ApplyTo()

createAPIExtensionsServer的初始化调用apiextensionsConfig.Complete().New完成初始化

  1. 调用c.GenericConfig.New按照restful模式初始化genericServer
  2. 初始化APIGroup,为APIGroup指定需要暴露的API
  3. 调用s.GenericAPIServer.InstallAPIGroup在路由中注册API Resources
  4. 初始化CRD的informer
  5. 初始化Controller例如openapiController、crdController、namingController、establishingController、nonStructuralSchemaController、apiApprovalController、finalizingController
  6. 将Controller和informer加入到PostStartHook

CreateKubeAPIServer的初始化调用的kubeAPIServerConfig.Complete().New

  1. 调用c.GenericConfig.New按照restful模式初始化genericServer
  2. 判断是否支持/log的路由
  3. m.InstallLegacyAPI将核心API Resource添加到路由,path为/api
  4. m.InstallAPIs将扩展API Resource添加到路由,path为/apis

m.InstallLegacyAPI的逻辑

  1. legacyRESTStorageProvider为资源创建RESTStorage,将访问路径和后端存储操作对应起来
  2. 初始化bootstrap-controller
  3. m.GenericAPIServer.InstallLegacyAPIGroup在路由中注册API Resources

createAggregatorServer的初始化

  1. 调用aggregatorConfig.Complete().NewWithDelegate初始化aggregatorServer
  2. 调用crdregistration.NewCRDRegistrationController初始化crdRegistrationController(用于注册CRD)
  3. 调用autoregister.NewAutoRegisterController初始化autoRegistrationController(将CRD对应的APIServices注册到apiserver)
  4. 调用aggregatorServer.GenericAPIServer.AddPostStartHook将crdRegistrationController和autoRegistrationController加入到PostStartHook

prepared.Run启动服务调用s.NonBlockingRun

  1. s.AuditBackend判断是否启动审计日志
  2. s.SecureServingInfo.Serve启动http服务
  3. s.RunPostStartHooks(stopCh)执行PostStartHooks
  4. 发送ready信号到systemd

Kube-api包含三个server,流程都是创建config,初始化http服务

初始化httpserver流程

  1. 初始化GoRestfulContainer
  2. 为每个Resource创建后端存储RESTStorage
  3. 为每个Resource支持的verbs添加handler,并将handler注册到route,最后注册到webservice

apiserver的handler都是以store结构保存,通过NewLegacyRESTStorage创建资源对应的RESTStorage

  1. LegacyAPI下RESTStorage初始化
  2. 初始化资源的RESTStorage,例如pod使用podstore.NewStorage
  3. podstore.NewStorage调用store.CompleteWithOptions创建后端存储,最后使用newETCD3Storage完成存储的写入
  4. restStorageMap保存url和RESTStorage的对应关系

kubernetes service

$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   4d22h
$ kubectl get endpoints kubernetes
NAME         ENDPOINTS             AGE
kubernetes   192.168.99.113:6443   4d22h

endpoint的配置地址由--advertise-address--secure-port配置

kubernetes service由kube-apiserver创建和维护,由bootstrap controller维护

bootstrap controller的功能

  • 创建kubernetes service
  • 创建默认的命名空间default、kube-system和kube-public
  • 基于Service ClusterIP的修复及检查功能
  • 基于Service NodePort的修复及检查功能

bootstrap controller的初始化是在InstallLegacyAPI中调用c.NewBootstrapController,启动和停止分别在PostStartHook和ShutdownHook

bootstrapController.Start启动

  1. createEndpointPortSpec创建endpoint
  2. epairClusterIPs(保证ClusterIP唯一不会超出范围)和repairNodePorts初始化
  3. async.NewRunner(c.RunKubernetesNamespaces, c.RunKubernetesService, repairClusterIPs.RunUntil, repairNodePorts.RunUntil).Start()
  • c.RunKubernetesNamespaces 创建kube-system和kube-public命名空间,之后每分钟检查一次
  • c.RunKubernetesService 通过/healthz接口获apiserver状态,并更新kubernetes service状态
  • c.UpdateKubernetesService 创建default命名空间,创建kubernetes service,更新endpoint
  • c.EndpointReconciler.ReconcileEndpoints 管理多个apiserver的endpoint