ApiServer之初识API
ApiServer作为 Kubernetes 的核心组件,让集群中所有资源可被描述和配置,即包括了pod、ingress、pvc这些基础资源,也包括deployment、rc、hpa等管理对象;ApiServer就像是一个包含一定逻辑的对象数据库代理;提供了RESTful API接口,其他组件或客户端可以通过该接口获取集群中资源对象的配置和状态,以实现各种逻辑处理;ApiServer本身是无状态的,集群所有的数据都会存储在ETCD中,各个组件对于资源对象的List-Watch机制都要通过 ApiServer 的验证授权和准入。
kube-apiserver 是 kubernetes 中与 etcd 直接交互的一个组件,其控制着 kubernetes 中核心资源的变化。它主要提供了以下几个功能:
- 提供 Kubernetes API,包括认证授权、数据校验以及集群状态变更等,供客户端及其他组件调用
- 代理集群中的一些附加组件组件,如 Kubernetes UI、metrics-server、npd 等;
- 允许对于对象状态的操作,比如Pod和Service的状态的改变,实现对象的持久化到Etcd
- 资源在不同版本之间的转换
API Overview
ApiServer 主要通过对外提供HTTP API 的方式与其他组件进行交互。API首选的序列化方案是JSON,但是也支持Protobuf协议。API主要有下面三种类型:
- core group:主要在
/api/v1下; - named groups:其 path 为
/apis/$NAME/$VERSION; - 暴露系统状态的一些 API:如
/metrics、/healthz等;
GVK/GVR
在Kubernetes中,要想定位一个对象,我们需要指定GVK或者GVR。比如这里声明了 apiVersion 是 apps/v1,其实就是隐含了 Group 是 apps,Version 是 v1,Kind 就是定义的 DaemonSet,而 kubectl 接收到这个声明之后,就可以根据这个声明去调用 API Server 对应的 URL 去获取信息,例如这个就是 /api/apps/v1/daemonset。
|
|
对应到实际的URI的请求组织形式,如下图所示:
通过结构体字段可以发现,它们其实就是Group、Version、Kind、Resource的不同组合
|
|
Kind
Kubernetes中的每个对象都有一个字段 Kind 表明其类型,以Pod为例:
|
|
Kubernetes 中 Kind 有三种类型:
- 系统中持久的实体对象,比如
Pod,Namespace - 一系列有某些共同特征的实体列表,比如
PodLists,NodeLists - 用于某些特定应用的一些非持久的实体,比如
APIGroup,APIResource,Status
Kind就是一个资源对象对应的种类 kind是通过 Kind=reflector.TypeOf(&Pod{}).Elem().Name()进行取值,取得的就是Pod这个结构体的名字。
|
|
Group
API Group 是一些有关系的Kinds的集合,比如所有的批处理对象,Job 或者 ScheduledJob 都在 batch这个API Group。
各个Group是相互独立的,发展速度也不同,所有每个Group都会有不同的Version,而kubernetes是通过插件的方式来使用各个Group的,可以根据需求决定使用哪个Group。
|
|
GroupMeta主要包括Group的元信息,里面的成员RESTMapper,与APIGroupVersion一样,其实APIGroupVersion的RESTMapper直接取值于GroupMeta的RESTMapper。一个Group可能包含多个版本,存储在 GroupVersions 中,而 GroupVersion 是默认存储在etcd中的版本。
|
|
Version
每个 API Group 下面都能存在有多个 version 版本。为了扩展性,Kubernetes支持多版本的API路径,比如 /api/v1 或者 /apis/extensions/v1beta1/, 不同版本的API意味着不同程度的稳定性和支持度。比如在一个 group 群组中最早有第一个 v1alpha1 版本,后来中间发展到了 v1beta1 版本,最终发展到 v1 的稳定版本。 如果在系统创建了一个 v1beta1 版本的对象,那么它能过被 Group 任一支持的版本( 比如v1 )检索到, 这是由于 API server 能够支持不同版本对象之间的无损耗转换。
type GroupVersion struct
|
|
GroupVersion中就是两个string类型,Group和 Version,分别对应了api所处的分组和版本,这也是kubernetes实现多版本的基础。
Resource
Resource 代表以 JSON 格式通过 HTTP 发送或检索的资源实体。 它既可以使一个单独的resource资源(比如…/namespaces/default,也可以是一组resource 资源(比如…/jobs)。 这里说明一下 Reource 和 Kind 的区别: 其实基本上都是一个概念,只是 Kind 表示一个种类,在实际中它是首字母大写的; Resource 表示资源,在实际中它是全部小写的,并且有单数和复数之分。我们可以把Kind和Resource的关系理解成面向对象编程中类与对象的关系,Kind 其实就是一个类,用于描述对象的;而 Resource 就是具体的 Kind,可以理解成类已经实例化成对象。
Resource就是指定了一个名字和kind的资源对象,不管它有没有namespace。 resource是通过 plural, singular := KindToResource(kind)取值,singular是将Kind转换为小写字母,而plural是变为复数
|
|
资源外部版本与内部版本
资源代码定义
将资源注册到资源注册表
资源首选版本
资源操作方法
资源与命名空间
自定义资源
资源对象描述文件定义
Kubernetes内置资源全图
runtime.Object 类型基石
Unstructured数据
Scheme资源注册表
Scheme资源注册表数据结构
资源注册表注册方法
资源注册表查询方法
Codec编解码器
Codec编解码实例化
jsonSerializer 与 yamlSerializer序列化器
protobufSerializer序列化器
Converter 资源版本转换器
Converter 转换器数据结构
Converter注册转换函数
Converter 资源版本转换原理
API Request Flow
了解了 kube-apiserver 的 API 后,下面会介绍 kube-apiserver 如何处理一个 API 请求,一个请求完整的流程如下图所示:
关于 API 的处理代码都在 k8s.io/pkg/api 包中,会处理来自集群内部和集群外部的API请求。
此处以一次 POST 请求示例说明,当请求到达 kube-apiserver 时,kube-apiserver 首先会执行在 http filter chain 中注册的过滤器链。该过滤器对其执行一系列过滤操作,主要有认证、鉴权等检查操作。当 filter chain 处理完成后,请求会通过 route 进入到对应的 handler 中,handler 中的操作主要是与 etcd 的交互。
Filter Chain
一个HTTP Request首先会被 DefaultBuildHandlerChain注册的 filter chain处理,每一个filter会传递各自的info到 ctx.RequestInfo上。
WithRequestInfo()as defined in requestinfo.go attaches aRequestInfoto the contextWithMaxInFlightLimit()as defined in maxinflight.go limits the number of in-flight requestsWithTimeoutForNonLongRunningRequests()as defined in timeout.go times out non-long-running requests like mostGET,PUT,POST,DELETErequests in contrast to long-running requests like watches and proxy requestsWithPanicRecovery()as defined in wrap.go wraps an handler to recover and log panicsWithCORS()as defined in cors.go provides a CORS implementation; CORS stands for Cross-Origin Resource Sharing and is a mechanism that allows JavaScript embedded in a HTML page to make XMLHttpRequests to a domain different from the one the JavaScript originated from.WithAuthentication()as defined in authentication.go tries to authenticate the given request as a user and stores the user info in the provided context. On success, theAuthorizationHTTP header is removed from the request.WithAudit()as defined in audit.go decorates the handler with audit logging information for all incoming requests The audit log entries contain infos such as source IP of the request, user invoking the operation, and namespace of the request.WithImpersonation()as defined in impersonation.go handles user impersonation, by checking requests that attempt to change the user (similar to sudo).WithAuthorization()as defined in authorization.go passes all authorized requests on to multiplexer which dispatched the request to the right handler, and returns a forbidden error otherwise.- WithRequestInfo:
- MaxInflightLimit
- TimeoutForNonLongRunningRequests
- Panic Recovery
- CORS
- Authentication
- Audit
- Impersonation
- Authorization
|
|
Handler Operation
当 filter chain 处理完成后,请求会通过 route 进入到对应的 handler 中,handler 中的操作主要是与 etcd 的交互,在 handler 中的主要的操作如下所示:
Decoder
在解码时,首先从 HTTP path 中获取期待的 version,然后使用 scheme 以正确的 version 创建一个与之匹配的空对象,并使用 JSON 或 protobuf 解码器进行转换,在转换的第一步中,如果用户省略了某些字段,Decoder 会把其设置为默认值。
Admission
在解码完成后,需要通过验证集群的全局约束来检查是否可以创建或更新对象,并根据集群配置设置默认值。在 k8s.io/kubernetes/plugin/pkg/admission 目录下可以看到 kube-apiserver 可以使用的所有全局约束插件,kube-apiserver 在启动时通过设置 --enable-admission-plugins 参数来开启需要使用的插件,通过 ValidatingAdmissionWebhook 或 MutatingAdmissionWebhook 添加的插件也都会在此处进行工作。
Validation
主要检查 object 中字段的合法性。
在 handler 中执行完以上操作后最后会执行与 etcd 相关的操作,POST 操作会将数据写入到 etcd 中,以上在 handler 中的主要处理流程如下所示:
v1beta1 ⇒ internal ⇒ | ⇒ | ⇒ v1 ⇒ json/yaml ⇒ etcd
admission validation
架构
- Scheme:定义了资源序列化和反序列化的方法,以及资源类型和版本的对应关系
- Storage:是对资源的完整封装,实现了资源创建、删除、watch等操作
- APIGroupInfo:是同一个group下所有资源的集合
每个资源对应着两个版本:
- External Object:这个版本是对外给用户访问创建的接口对象,比如使用yaml或json创建对象时,都要使用External Object
- Internal Object:这个版本是核心对象,实现了资源的创建和删除,对应了在ETCD中持久化的版本
这两个版本的资源是需要相互转换的,而转换的函数就需要事先初始化到Scheme中, 多个external version版本之间的资源进行相互转换,都是需要通过internal version进行中转。所以在ETCD中存储的资源是带版本的,这也是kubernetes能实现多版本转换的关键。
组件构成
ApiServer 共由 3 个组件构成(Aggregator、KubeAPIServer、APIExtensionServer),这些组件依次通过 Delegation 处理请求:
- Aggregator:暴露的功能类似于一个七层负载均衡,将来自用户的请求拦截转发给其他服务器,并且负责整个 APIServer 的 Discovery 功能;
- KubeAPIServer :负责对请求的一些通用处理,认证、鉴权等,以及处理各个内建资源的 REST 服务;
- APIExtensionServer:主要处理 CustomResourceDefinition(CRD)和 CustomResource(CR)的 REST 请求,也是 Delegation 的最后一环,如果对应 CR 不能被处理的话则会返回 404。
Aggregator 和 APIExtensionsServer 对应两种主要扩展 APIServer 资源的方式,即分别是 AA 和 CRD。
Aggregator
Aggregator 通过 APIServices 对象关联到某个 Service 来进行请求的转发,其关联的 Service 类型进一步决定了请求转发形式。Aggregator 包括一个 GenericAPIServer 和维护自身状态的 Controller。其中 GenericAPIServer 主要处理 apiregistration.k8s.io 组下的 APIService 资源请求。
Aggregator 除了处理资源请求外还包含几个 controller:
apiserviceRegistrationController:负责 APIServices 中资源的注册与删除;availableConditionController:维护 APIServices 的可用状态,包括其引用 Service 是否可用等;autoRegistrationController:用于保持 API 中存在的一组特定的 APIServices;crdRegistrationController:负责将 CRD GroupVersions 自动注册到 APIServices 中;openAPIAggregationController:将 APIServices 资源的变化同步至提供的 OpenAPI 文档;
kubernetes 中的一些附加组件,比如 metrics-server 就是通过 Aggregator 的方式进行扩展的,实际环境中可以通过使用 apiserver-builder 工具轻松以 Aggregator 的扩展方式创建自定义资源。
启用 API Aggregation
在 kube-apiserver 中需要增加以下配置来开启 API Aggregation:
|
|
KubeAPIServer
KubeAPIServer 主要是提供对 API Resource 的操作请求,为 kubernetes 中众多 API 注册路由信息,暴露 RESTful API 并且对外提供 kubernetes service,使集群中以及集群外的服务都可以通过 RESTful API 操作 kubernetes 中的资源。
APIExtensionServer
APIExtensionServer 作为 Delegation 链的最后一层,是处理所有用户通过 Custom Resource Definition 定义的资源服务器。
其中包含的 controller 以及功能如下所示:
openapiController:将 crd 资源的变化同步至提供的 OpenAPI 文档,可通过访问/openapi/v2进行查看;crdController:负责将 crd 信息注册到 apiVersions 和 apiResources 中,两者的信息可通过$ kubectl api-versions和$ kubectl api-resources查看;namingController:检查 crd obj 中是否有命名冲突,可在 crd.status.conditions中查看;establishingController:检查 crd 是否处于正常状态,可在 crd.status.conditions中查看;nonStructuralSchemaController:检查 crd obj 结构是否正常,可在 crd.status.conditions中查看;apiApprovalController:检查 crd 是否遵循 kubernetes API 声明策略,可在 crd.status.conditions中查看;finalizingController:类似于 finalizes 的功能,与 CRs 的删除有关;
-
No backlinks found.