欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > Kubernetes控制平面组件:API Server代码基础概念

Kubernetes控制平面组件:API Server代码基础概念

2025/4/24 10:59:08 来源:https://blog.csdn.net/a1369760658/article/details/147353196  浏览:    关键词:Kubernetes控制平面组件:API Server代码基础概念

云原生学习路线导航页(持续更新中)

  • kubernetes学习系列快捷链接
    • Kubernetes架构原则和对象设计(一)
    • Kubernetes架构原则和对象设计(二)
    • Kubernetes架构原则和对象设计(三)
    • Kubernetes控制平面组件:etcd(一)
    • Kubernetes控制平面组件:etcd(二)
    • Kubernetes控制平面组件:API Server详解(一)
    • Kubernetes控制平面组件:API Server详解(二)

本文主要对kubernetes的控制面组件API Server的代码阅读做一些前置准备,包括apimachinery项目的定位和核心包的介绍,API Server代码的一些基础操作,subresource概念、apiserver代码走读的关键点等

  • 希望大家多多 点赞 关注 评论 收藏,作者会更有动力继续编写技术文章

1.apimachinery项目定位

  • girhub:
    • https://github.com/kubernetes/apimachinery
    • https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/apimachinery
  • apimachinery 是 Kubernetes 生态中的底层基础设施库,为 Kubernetes API 的构建、操作和扩展提供基础能力。其核心定位体现在以下方面:
    • 统一 API 基础设施:定义 Kubernetes API 的核心数据结构(如 TypeMetaObjectMeta)、类型系统(GVK/GVR 模型)和序列化机制(JSON/Protobuf),是客户端和服务端共享的依赖库
    • 解耦核心组件:通过抽象 API 操作的通用逻辑(如版本转换、资源发现),使 Kubernetes 主仓库(k8s.io/kubernetes)、客户端库(client-go)和扩展组件(如 CRD 控制器)无需直接依赖核心代码
    • 支撑扩展生态:提供自定义资源(CRD)和聚合层(Aggregated APIServer)的基础能力,是构建 Operator、Service Mesh 等云原生组件的基石

2.apimachinery的核心能力与基本原理

2.1.核心能力

  • 类型系统管理
    • 定义 Kubernetes 资源的元数据(TypeMetaObjectMeta)和通用接口(如 runtime.Object),支持资源的版本化描述。
  • 序列化与反序列化
    • 提供 JSON/Protobuf 编码解码能力,通过 runtime.Scheme 实现类型与数据格式的动态映射。
  • 版本转换与兼容性
    • 支持多版本 API 共存(如 v1v1beta1),通过 Convert 接口实现不同版本资源的自动转换。
  • 资源发现与操作
    • 提供 RESTMapper 实现 GVK 到 GVR 的映射,支持动态客户端(dynamic.Client)操作未预定义类型的资源。
  • 通用工具链
    • 包含深拷贝(DeepCopy)、标签选择器(labels.Selector)、字段选择器(fields.Selector)等高频工具

2.2.基本原理

  • Scheme 机制

    • runtime.Scheme 是核心组件,负责注册 Golang 类型与 GVK 的映射关系,并管理版本转换函数。例如:
      scheme := runtime.NewScheme()
      corev1.AddToScheme(scheme)  // 注册核心类型
      
    • 通过 Scheme,客户端可自动反序列化 API Server 返回的 JSON 数据为对应结构体。
  • GVK/GVR 模型

    • GVK (Group/Version/Kind):标识资源的逻辑类型(如 apps/v1.Deployment)。
    • GVR (Group/Version/Resource):对应 API 路径(如 /apis/apps/v1/deployments)。
    • apimachinery 提供 meta.RESTMapper 实现两者的动态映射,支撑 kubectl get deployments 等操作。
  • 类型注册与转换

    • 资源类型需实现 runtime.Object 接口,并通过 AddKnownTypes 注册到 Scheme。
    • 版本转换通过 Convert 函数链实现,例如将 v1beta1.Deployment 转换为 v1.Deployment

2.3.apimachinery核心代码包

  • apimachinery 的代码结构围绕 类型系统API 操作 展开,核心包如下:

    包路径功能描述
    k8s.io/apimachinery/pkg/apis/meta定义元数据(TypeMetaObjectMeta)和公共接口(如 ListOptionsDeleteOptions
    k8s.io/apimachinery/pkg/runtime实现序列化(Serializer)、Scheme 管理、类型转换等核心逻辑
    k8s.io/apimachinery/pkg/api/resource处理资源配额(如 CPU/内存的单位转换)
    k8s.io/apimachinery/pkg/util提供通用工具(如 wait 重试机制、sets 集合操作)
    k8s.io/apimachinery/pkg/version定义 Kubernetes 版本信息结构
  • 关键数据结构示例:

    // TypeMeta 定义资源的 API 版本和类型
    type TypeMeta struct {APIVersion string `json:"apiVersion,omitempty"`Kind       string `json:"kind,omitempty"`
    }// ObjectMeta 定义资源的元数据(名称、标签等)
    type ObjectMeta struct {Name        string            `json:"name,omitempty"`Namespace   string            `json:"namespace,omitempty"`Labels      map[string]string `json:"labels,omitempty"`Annotations map[string]string `json:"annotations,omitempty"`
    }
    

3.API Server代码的一些基础操作

3.1.如何定义一个Group

在这里插入图片描述

  • 分为三步:
    • 定义一个GV:Group+Version
    • 定义一个SchemeBuilder
    • 将GV下具体的对象加入SchemeBuilder

3.2.如何定义一个对象

  • 对象一般都是在types.go文件中
    在这里插入图片描述

3.3.使用代码生成的Tags

3.3.1.code-generator项目

  • code-generator项目:https://github.com/kubernetes/code-generator

  • code-generator项目下包含很多代码生成的工具,包括生成 深拷贝代码、client代码、informer代码、lister代码、conversion代码等
    在这里插入图片描述

  • 代码生成器,是通过文件中的 特定tag 生效的,比如下面有一些常用的tag
    在这里插入图片描述

    标签解释
    // +k8s:deepcopy-gen=package全局标签,为包内所有类型生成深拷贝方法。
    // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object生成实现 runtime.Object 接口的深拷贝方法,用于序列化与版本转换。
    // +genclient生成客户端代码(CRUD 方法、Lister、Informer)。
    // +genclient:nonNamespaced标记资源为集群作用域(Cluster-scoped),生成不带命名空间参数的方法。
    // +genclient:noVerbs不生成默认客户端方法(需配合其他标签指定特定动词)。
    // +genclient:onlyVerbs=create,delete仅生成指定的客户端方法(如仅 CreateDelete)。
    // +genclient:skipVerbs=get,list,watch跳过生成指定的客户端方法(如 GetListWatch)。
    // +genclient:method=Create,verb=create,result=...自定义客户端方法名称、HTTP 动词及返回类型(如返回 metav1.Status)。
  • 说明:

    • 全局标签作用于整个包,局部标签作用于单个资源。
    • 标签需严格遵循格式(如空格不可省略),否则会被代码生成器忽略。

3.3.2.代码生成使用示例

  • 通过编写脚本文件,指定code-generator项目下各种工具的路径,然后使用命令生成具体的代码。如下图:
  • --input-dirs:源代码目录
  • -O:生成的文件名称
  • --bounding-dirs:输出目录
  • --go-header-file:加什么样的header描述
    在这里插入图片描述

3.4.如何操作etcd

在这里插入图片描述

  • 每一个etcd的对象都会有一个storage.go,定义如何与etcd交互。比如上面就是定义了configmap的etcd操作。
  • 其中strategy为具体的操作策略,比如创建、修改、删除,操作前可以进行一些校验,平时我们操作cm报的错误,就都是这个strategy报的错误了
  • 比如这里CreateStrategy里的validate方法,就是对cm的校验,看apiserver代码的时候,可以看这里的处理
    在这里插入图片描述
    在这里插入图片描述

3.5.将 API Group 注册到API Server

  • 通过install方法,将GVK的某个资源 Handler注册到apiserver中,在发生对应事件的时候才知道怎么处理
    在这里插入图片描述

4.subresource概念

4.1.subresource是什么

  • Kubernetes 中 Pod 的 ​​subresource(子资源)​​ 是 Pod 主资源的扩展操作接口,用于实现特定场景下的精细化操作或状态管理。

4.2.常见的subresource

Pod 的子资源主要通过 Kubernetes API 路径区分,常见的子资源如下:

4.2.1.pod的status

  • 功能:用于获取或更新 Pod 的运行时状态(如容器状态、Pod 阶段等)。状态信息由 kubelet 维护,用户可通过 kubectl get pod -o yaml 查看状态字段。
  • API 路径​​:/api/v1/namespaces/{namespace}/pods/{name}/status

4.2.2.pod容器执行的exec

  • ​​功能​​:在 Pod 的容器内​​执行命令​​(类似 docker exec)。常用于调试容器内进程或获取实时日志
  • 使用示例:
    kubectl exec -it <pod-name> -- /bin/sh
    
  • ​​API 路径​​:/api/v1/namespaces/{namespace}/pods/{name}/exec

4.2.3.pod容器的log

  • 功能:获取 Pod 中容器的日志输出。支持按时间范围、容器名称过滤日志。
  • 使用示例:
    kubectl logs <pod-name> -c <container-name> --since=5m
    
  • API 路径:/api/v1/namespaces/{namespace}/pods/{name}/log

4.2.4.pod的端口转发portforward

  • 功能:将本地端口转发到 Pod 的容器端口,便于本地访问容器内服务(如调试数据库)。
  • 使用示例:
    kubectl port-forward <pod-name> 8080:80
    
  • API 路径:/api/v1/namespaces/{namespace}/pods/{name}/portforward

4.3.子资源的核心原理

4.3.1.API 路径设计

  • Kubernetes 的 RESTful API 通过路径后缀标识子资源。例如,对 Pod 的 exec 操作对应路径 /pods/{name}/exec,而非直接操作 Pod 主资源。

4.3.2.独立的权限控制

  • 子资源的操作需通过 RBAC 独立授权。例如,execportforward 需要 pods/execpods/portforward 权限:
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    rules:
    - apiGroups: [""]resources: ["pods/exec", "pods/portforward"]verbs: ["create"]
    

4.3.3.status状态分离

  • status 子资源的设计遵循 声明式Declarative API 原则,将用户定义的期望状态(spec)与系统维护的实际状态(status)分离,避免并发写入冲突。
  • 因为status写入太频繁了,如果status直接操作pod主资源,容易与spec的update操作发生写入冲突,所以将status分离出来是非常有必要的
  • 如下图,status有独立的StatusStrategy,在更新status时,会把spec的内容恢复为和环境一致,防止status的修改影响到spec
    在这里插入图片描述

5.API Server代码走读

  • https://cncamp.notion.site/kube-apiserver-10d5695cbbb14387b60c6d622005583d
cmd/kube-apiserver/app/server.go:NewAPIServerCommand()-->
completedOptions, err := Complete(s)-->s.Etcd.WatchCacheSizes, err = serveroptions.WriteWatchCacheSizes(sizes)
Run(completedOptions, genericapiserver.SetupSignalHandler())-->CreateServerChain()-->CreateServerChain()-->CreateKubeAPIServerConfig-->buildGenericConfig(s.ServerRunOptions, proxyTransport)-->genericapiserver.NewConfig(legacyscheme.Codecs) // create codec factory for encoding/decodingcontrolplane.DefaultAPIResourceConfigSource() // group version: enabled/disabledstorageFactoryConfig.Complete(s.Etcd)completedStorageFactoryConfig.New()--> // register access path in etcd for all k8s objectsstorageFactory.AddCohabitatingResources(networking.Resource("networkpolicies"), extensions.Resource("networkpolicies"))s.Etcd.ApplyWithStorageFactoryTo(storageFactory, genericConfig)-->c.AddHealthChecks()c.RESTOptionsGetter = &StorageFactoryRestOptionsFactory{Options: *s, StorageFactory: factory}
// API Server启动过程中,认证、鉴权、准入逻辑都是如何加载的
// 认证s.Authentication.ApplyTo()--> // clientcert, serviceaccount, bootstrap token, authenticatorConfig.New()-->newWebhookTokenAuthenticator(config) // webhook
// 鉴权BuildAuthorizer(s, genericConfig.EgressSelector, versionedInformers)-->authorizationConfig.New()-->rbacAuthorizer := rbac.New()--> // if authorizer type is rbac
// 准入buildServiceResolver(s.EnableAggregatorRouting, genericConfig.LoopbackClientConfig.Host, versionedInformers)admissionConfig.New(proxyTransport, genericConfig.EgressSelector, serviceResolver)-->admission.PluginInitializer{webhookPluginInitializer, kubePluginInitializer}net.SplitHostPort(s.Etcd.StorageConfig.Transport.ServerList[0])utilwait.PollImmediate(etcdRetryInterval, etcdRetryLimit*etcdRetryInterval, preflight.EtcdConnection{ServerList: s.Etcd.StorageConfig.Transport.ServerList}.CheckEtcdServers)capabilities.Initialize() // allow privillage?config := &controlplane.Config{}createAPIExtensionsConfig()createAPIExtensionsServer()-->apiextensionsConfig.Complete().New(delegateAPIServer)-->s.AddHealthChecks(delegateCheck)
// 注册通用handlerinstallAPI(s, c.Config) // register generic api handler e.g. index, profiling, metrics, flow controlCreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer)kubeAPIServerConfig.Complete().New(delegateAPIServer)m.InstallLegacyAPI(&c, c.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider)-->m.GenericAPIServer.AddPostStartHookOrDie(controllerName, bootstrapController.PostStartHook)-->controlplane.controller.Start()-->async.NewRunner(c.RunKubernetesNamespaces, c.RunKubernetesService, repairClusterIPs.RunUntil, repairNodePorts.RunUntil)m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook)
// 所有的API Group都是如何Install的
// 注册core group API handler
// API Server的watch cache时如何构建的,newEtcdStorage-newCache的时候,newWatchCache建立了缓存,实现了watch etcdm.GenericAPIServer.InstallLegacyAPIGroup() // register handler for /apirestStorageProviders := []RESTStorageProvider{appsrest.StorageProvider{}}m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...)-->
// 初始化对应group中对象的watch cacherestStorageBuilder.NewRESTStorage(apiResourceConfigSource, restOptionsGetter)--> // trigger appsrest.StorageProviderp.v1Storage(apiResourceConfigSource, restOptionsGetter)-->daemonsetstore.NewREST(restOptionsGetter)-->store.CompleteWithOptions(options)-->opts, err := options.RESTOptions.GetRESTOptions(e.DefaultQualifiedResource)--> // etcd.goret.Decorator = genericregistry.StorageWithCacher()-->cacherstorage.NewCacherFromConfig(cacherConfig)-->watchCache := newWatchCache()-->
// 注册API handlerm.GenericAPIServer.InstallAPIGroups(apiGroupsInfo...)-->  // register handler for /apiss.installAPIResources(APIGroupPrefix, apiGroupInfo, openAPIModels)-->apiGroupVersion.InstallREST(s.Handler.GoRestfulContainer)-->discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, staticLister{apiResources})createAggregatorServer(aggregatorConfig, kubeAPIServer.GenericAPIServer, apiExtensionsServer.Informers)-->apiServices := apiServicesToRegister(delegateAPIServer, autoRegistrationController)server.PrepareRun()-->s.GenericAPIServer.PrepareRun()-->s.installHealthz()s.installLivez()s.installReadyz()prepared.Run(stopCh)-->s.runnable.Run(stopCh)--> // preparedGenericAPIServer.Run()s.NonBlockingRun(delayedStopCh)-->s.SecureServingInfo.Serve(s.Handler, s.ShutdownTimeout, internalStopCh)-->RunServer(secureServer, s.Listener, shutdownTimeout, stopCh)

6.注意事项

6.1.kubernetes集群版本升级 与对象兼容性

  • 需要注意,对于一个对象的版本,kubernetes只承诺向下兼容3个版本
    • 比如在1.0引入了一个v1alpha1的对象A版本,在kubernetes的后面3个版本发布时,都会做v1alpha1的对象A版本的兼容性处理,但是再后面的kubernetes版本就不保证了,
    • 所以在做kubernetes版本升级的时候不要跨太多版本,而且也要对你的Operator Controller等做好调查,不要升级kubernetes集群后发现Operator操作的对象不支持了
  • 社区建议升级kubernetes集群版本时不要跳过任何版本,要一个个升上去,但是实践下来很难能跟上kubernetes发布的版本,在一些集群比较多的厂商中,一般会2-3个版本升级一次。
    • 但即便这样,升级时也要非常仔细的读changeLog,不能忽略任何一句话
    • 之前就发生过版本升级后pod的hash计算方法变化的场景,可能会造成pod重建

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词