k8s源码分析 pdf_kubeapiserver源码阅读分享

作者 |baron TKE专项技术组导读:本文主要对kube-apiserver的功能在源码层面进行解读,分析了kube-apiserver三个基本功能的代码结构以及逻辑实现。分别解读了kube-apiserver服务路由的配置方式,kube-apiserver服务请求访问控制模式,bootstrapToken鉴权模式等内容。版本环境• kubernetes版本:kubernet...
摘要由CSDN通过智能技术生成

作者 | baron  TKE专项技术组

导读:本文主要对kube-apiserver的功能在源码层面进行解读,分析了kube-apiserver三个基本功能的代码结构以及逻辑实现。分别解读了kube-apiserver服务路由的配置方式,kube-apiserver服务请求访问控制模式,bootstrapToken鉴权模式等内容。

版本环境

•   kubernetes版本:kubernetes:v1.17.0

•   go环境:go version go1.13.4 windows/amd64

代码总体解析 1. ApiServer的功能设计 kube-apiserver的设计目的在于成为一台相对优雅简单的server,对外提供规范的Kubernetes API。它不仅提 供了外部访问集群api的渠道,同时也达到了解耦各组件的目的。 kube-apiserver的主要功能是处理其他业务的REST请求,对其进行验证及鉴权,请求成功后将结果更新 到后端存储 etcd (也可以是其他存储)中。 从kube-apiserver的功能可以看出,其源码主要围绕三个关键点展开。我们将依次从三个方面:配置 服务路由、访问权限以及同数据库(etcd)的交互对kube-apiserver源码进行解读。 2. 数据结构 数据结构体现了代码的组织和存储形式,为了便于后续代码阅读,这里先简单介绍下kube-apiserver主要逻辑涉及的几个重要的结构体,主要为ServerRunOptions、Config、APIGroupInfo。

ServerRunOptions

ServerRunOptions位于k8s.io/kubernetes/cmd/kube-apiserver/app/options/options.go,是kube-apiserver的启动参数结构体,涵括了kube-apiserver启动需要所有参数,后续各个逻辑需要的相关配置参数均来源于此。其中每项参数的含义请参考官网文档:

type ServerRunOptions struct {
        // kube-apiserver系列服务基础配置项  GenericServerRunOptions *genericoptions.ServerRunOptions    // 后端存储etcd的配置项  Etcd                    *genericoptions.EtcdOptions  SecureServing           *genericoptions.SecureServingOptionsWithLoopback  InsecureServing         *genericoptions.DeprecatedInsecureServingOptionsWithLoopback  Audit                   *genericoptions.AuditOptions  Features                *genericoptions.FeatureOptions  Admission               *kubeoptions.AdmissionOptions    // 集群验证配置项  Authentication          *kubeoptions.BuiltInAuthenticationOptions    // 集群操作鉴权配置项  Authorization           *kubeoptions.BuiltInAuthorizationOptions  CloudProvider           *kubeoptions.CloudProviderOptions  APIEnablement           *genericoptions.APIEnablementOptions  EgressSelector          *genericoptions.EgressSelectorOptions  ...}

Config

Config位于k8s.io/apiserver/pkg/server/config.go,是kube-apiserver系列服务的通用配置项,用于与各服务对应的额外配置组合来构成对应服务的配置结构体。

type Config struct {
      // https服务配置项SecureServing *SecureServingInfo  // 服务验证配置Authentication AuthenticationInfo  // 服务鉴权配置Authorization AuthorizationInfoLoopbackClientConfig *restclient.ConfigEgressSelector *egressselector.EgressSelectorRuleResolver authorizer.RuleResolverAdmissionControl    admission.InterfaceAuditBackend audit.Backend  // 配置服务路由BuildHandlerChainFunc func(apiHandler http.Handler, c *Config) (securehttp.Handler)RESTOptionsGetter genericregistry.RESTOptionsGetter  ...}

APIGroupInfo

APIGroupInfo位于k8s.io/apiserver/pkg/server/generaticapiserver.go,定义了一个 API 组的相关信息。(以customresourcedefinitions资源为例,对应的API组name为apiextensions.k8s.io,API组支持的版本信息PrioritizedVersions为v1和v1beta1两个版本,版本 、资源 、 后端CRUD结构体的映射关系为map[v1beta1]

[customresourcedefinitions]customresourcedefinitionsStorage)type APIGroupInfo struct {
      PrioritizedVersions []schema.GroupVersion    // map[version][resource]storage  VersionedResourcesStorageMap map[string]map[string]rest.Storage  OptionsExternalVersion *schema.GroupVersion  MetaGroupVersion *schema.GroupVersion  Scheme *runtime.Scheme  NegotiatedSerializer runtime.NegotiatedSerializer  ParameterCodec runtime.ParameterCodec  StaticOpenAPISpec *spec.Swagger}

kube-apiserver功能介绍

功能一:配置服务路由

kube-apiserver中配置路由的代码完全遵循的设计模式,先将处理方法注册到对应Route,再Route中注册到WebService,最后将所有的WebService注册到Container中,由Container负责分发流量。访问的过程为Container-->WebService-->Route。 kube-apiserver整个的api如下:                                                 53ff051cf5a657235d9bb483cfd8dfa0.png

main

入口函数,这里使用构建apiserver的cli命令工具,代码逻辑放在app.NewAPIServerCommand():

func main() {
      rand.Seed(time.Now().UnixNano())  command := app.NewAPIServerCommand()  logs.InitLogs()  defer logs.FlushLogs()  if err := command.Execute(); err != nil {
        os.Exit(1)  }}
NewAPIServerCommand

在这里,代码组织形式是cobra构建cli命令行工具的模式。这里主要是对启动参数进行解析、完善及验证其合法性。各项启动参数及其意义可参考。apiserver的具体逻辑放在Run(completedOptions, genericapiserver.SetupSignalHandler())。

func NewAPIServerCommand() *cobra.Command  s := options.NewServerRunOptions()  cmd := &cobra.Command{
        Use: "kube-apiserver",    Long: `xxxxx`,    RunE: func(cmd *cobra.Command, args []string) error {
          verflag.PrintAndExitIfRequested()      utilflag.PrintFlags(cmd.Flags())      completedOptions, err := Complete(s)      if errs := completedOptions.Validate(); len(errs) != 0 {
            return utilerrors.NewAggregate(errs)      }      return Run(completedOptions, genericapiserver.SetupSignalHandler())    ,  }

在笔者的测试环境里,kube-apiserver对应的启动参数如下:      f6d58ec4ab6a01d2ad1a8824706166fd.png

Run

run函数逻辑很明了,分为三部分:

  • 创建kube-apiserver服务链,配置各api路由的逻辑。

  • kube-apiserver服务运行前的准备,如设置健康检查和存活检查等操作。

  • 正式运行kube-apiserver服务。

func Run(completeOptions completedServerRunOptions, stopCh  {
      server, err := CreateServerChain(completeOptions, stopCh)  prepared, err := server.PrepareRun()  return prepared.Run(stopCh)}
CreateServerChain

kube-apiserver包含一系列服务:

createAPIExtensionsServer:创建CustomResourceDefinitions对应的服务,配置对应api的路由(/apis/apiextensions.k8s.io/)。

CreateKubeAPIServer:创建kube-apiserver的api服务,配置/api和/apis根路径下的路由。

createAggregatorServer:创建聚合服务,聚合在kube-apiserver之外的拓展apiserver。

func CreateServerChain(completedOptions completedServerRunOptions, stopCh chan struct{}) (*aggregatorapiserver.APIAggregator, error) {
      ...  // 启动CustomResourceDefinitions对应的服务  apiExtensionsServer, err := createAPIExtensionsServer(apiExtensionsConfig, genericapiserver.NewEmptyDelegate())  // 启动kube-apiserver的api服务  kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer)  // 启动聚合服务  aggregatorServer, err := createAggregatorServer(aggregatorConfig, kubeAPIServer.GenericAPIServer, apiExtensionsServer.Informers)  ...}
createAPIExtensionsServer

这里就以createAPIExtensionsServer为例详细梳理下kube-apiserver配置api路由的代码逻辑。

Complete()完善apiextensionsConfig的配置信息,然后到new的逻辑里面组装customresourcedefinitions对应的api组信息apiGroupInfo。

func createAPIExtensionsServer(apiextensionsConfig *apiextensionsapiserver.Config, delegateAPIServer genericapiserver.DelegationTarget) (*apiextensionsapiserver.CustomResourceDefinitions, error) {
      return apiextensionsConfig.Complete().New(delegateAPIServer)}func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*CustomResourceDefinitions, error) {
      ...    // 将这组api的GroupName设置为apiextensions.k8s.io  apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiextensions.GroupName, Scheme, metav1.ParameterCodec, Codecs)    // 根据配置情况,装填对应资源的CRUD后端交互结构体  if apiResourceConfig.VersionEnabled(v1beta1.SchemeGroupVersion) {
        storage := map[string]rest.Storage{}    customResourceDefintionStorage := customresourcedefinition.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)    storage["customresourcedefinitions"] = customResourceDefintionStorage    storage["customresourcedefinitions/status"] = customresourcedefinition.NewStatusREST(Scheme, customResourceDefintionStorage)    apiGroupInfo.VersionedResourcesStorageMap[v1beta1.SchemeGroupVersion.Version] = storage  }  if apiResourceConfig.VersionEnabled(v1.SchemeGroupVersion) {
        storage := map[string]rest.Storage{}    customResourceDefintionStorage := customresourcedefinition.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)    storage["customresourcedefinitions"] = customResourceDefintionStorage    storage["customresourcedefinitions/status"] = customresourcedefinition.NewStatusREST(Scheme, customResourceDefintionStorage)    apiGroupInfo.VersionedResourcesStorageMap[v1.SchemeGroupVersion.Version] = storage  }  // 转入下一步逻辑  if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
        return nil, err  }  ...}
ApiGroupInfo在测试环 境的体现为:          97604ba299165cb2cc7865c7187b15e0.png
InstallAPIGroupfunc (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
      return s.InstallAPIGroups(apiGroupInfo)}func (s *GenericAPIServer) InstallAPIGroups(apiGroupInfos ...*APIGroupInfo) error {
      ...  for _, apiGroupInfo := range apiGroupInfos {
            // 设置APIGroupPrefix即api根路径为/apis,随后转入下一步逻辑    if err := s.installAPIResources(APIGroupPrefix, apiGroupInfo, openAPIModels); err != nil {
          return fmt.Errorf("unable to install api resources: %v", err)    }    ...  }  return nil}

apiGroupInfo在测试环境对应于:           b0216f312dbb36a76ef539d38e10d8f0.png

installAPIResourcesfunc (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *APIGroupInfo, openAPIModels openapiproto.Models) error {
        // 分别对对应的api组的不同版本进行处理  for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
        if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 {
          klog.Warningf("Skipping API %v because it has no resources.", groupVersion)      continue    }    apiGroupVersion := s.getAPIGroupVersion(apiGroupInfo, groupVersion, apiPrefix)    if apiGroupInfo.O
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值