【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析

这篇具有很好参考价值的文章主要介绍了【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考

  • Kubernetes 源码剖析(书籍)
  • kube-apiserver的设计与实现 - 自记小屋

kube-apiserver 核心思想

  • APIGroupInfo 记录 GVK 与 Storage 的对应关系

    • 将 GVK 转换成,Restful HTTP Path
    • 将 Storage 封装成 HTTP Handler
    • 将上面两个形成映射,实现相关的路由处理
  • 发起请求并处理的流程

    1. 发送请求:通过 GVK 对应的 Restful HTTP Path 发送请求(对 k8s 资源的操作)
    2. 认证:经过认证插件,判断是否为合法用户
    3. 鉴权(或叫授权):经过鉴权插件,判断该用户是否有权限操作此资源
    4. 准入控制:先执行已配置的 mutating 变更准入控制插件(修改用户提交的资源对象信息,如新增 label 等),再执行已配置 Validating 验证准入控制插件(验证用户提交的资源对象信息,如是否具有某个 label 等)
      • 在此过程中好像涉及 Schema Validation,不清楚此处作用(没有定位到,后续若找到,再补充)
    5. 执行(存储):经过以上流程,会到达 Handler 转换为对应的资源 Storage 结构,然后读取 Storage 中的存储配置信息,然后存储到 etcd 数据库中(若配置了加密,将在存入 etcd 之前,对资源对象信息进行加密)
      • 在存入之前,好像会转换为资源的某一特定版本或内部版本(没有定位到,后续若找到,再补充)
      • 【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

kube-apiserver 架构详解

  • APIExtensionsServer、KubeAPIServer、AggregatorServer 中的每个都是一个接口服务器(用于处理不同类型资源的请求),运行时可以理解为是 kube-apiserver 的 3 个进程

    • APIExtensionsServer:处理对 CRD 资源的请求,其 Scheme 记录关注的 CRD 资源相关信息
    • KubeAPIServer: 处理对 k8s 核心资源(如 core 组)的请求,其 Scheme 记录关注的 k8s 核心资源相关信息
    • AggregatorServer:处理对用户额外引入的资源(如通过 APIService 注册外部的 Server 或集群内的其他服务)的请求,其 Scheme 记录用户注册资源的相关信息
  • 但以上三种 Server 都依赖于 GenericAPIServer(通用服务器),该 Server 进行一些基础通用配置,并将负责各类 Server 的启动

Master 结构在 1.24.3 版本改为 Instance 结构

路径: pkg/controlplane/instance.go

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

kube-apiserver 启动流程

在kube-apiserver组件启动过程中,代码逻辑可分为9个步骤,分 别介绍如下。

(1)资源注册。 (2)Cobra命令行参数解析。 (3)创建APIServer通用配置。 (4)创建APIExtensionsServer。 (5)创建KubeAPIServer。(6)创建AggregatorServer。 (7)创建GenericAPIServer。 (8)启动HTTP服务。 (9)启动HTTPS服务。

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

资源注册

kube-apiserver组件启动后的第一件事情是将Kubernetes所支持 的资源注册到Scheme资源注册表中, 这样后面启动的逻辑才能够从 Scheme 资 源 注 册 表 中 拿 到 资 源 信 息 并 启 动 和 运 行 APIExtensionsServer 、 KubeAPIServer 、 AggregatorServer 这 3 种 服 务。

资源的注册过程并不是通过函数调用触发的, 而是通过Go语言的 导入(import)和初始化(init)机制触发的

  • import 某 package,会自动完成该 package 下 const、 var和init函数的初始化
    • import 按顺序执行
    • 若多层 import,先执行最下层的,再执行上层的
      • Pkg A import B --> pkg B import C --> pkg C import D
        • 先执行 pkg D 的 const、 var和init函数,再执行 pkg C 的 const、 var和init函数,然后 B 的 const、 var和init函数,最后 A 的 const、 var和init函数
kube-apiserver 的 import 信息 cmd/kube-apiserver/app/server.go
import “k8s.io/kubernetes/pkg/api/legacyscheme” 初始化 k8s 核心资源注册表 legacyscheme.Scheme
import “k8s.io/kubernetes/pkg/controlplane” 2. 注册 k8s 核心资源到 legacyscheme.Scheme 中
第1步细化 pkg/api/legacyscheme/scheme.go legacyscheme 包中全局变量 Scheme 初始化
第2步细化 pkg/controlplane/import_known_versions.go 注册所有

除将KubeAPIServer(API核心服务)注册至legacyscheme.Scheme资源注册表以外,还需要了解APIExtensionsServer和AggregatorServer资源注册过程。

●将APIExtensionsServer(API扩展服务)注册至extensionsapiserver.Scheme资源注册表,注册过程定义在vendor/k8s.io/apiextensionsapiserver/pkg/apiserver/apiserver.go中。

●将AggregatorServer(API聚合服务)注册至aggregatorscheme.Scheme资源注册表,注册过程定义在vendor/k8s.io/kubeaggregator/pkg/apiserver/scheme/scheme.go中。

  • 下面代码为 k8s 核心资源注册表(legacyscheme.Scheme)的详细初始化和注册流程
// 0. kube-apiserver 的 import 信息
// cmd/kube-apiserver/app/server.go

package app

import (
	"k8s.io/kubernetes/pkg/api/legacyscheme" // ymjx: 初始化 k8s 核心资源注册表 legacyscheme.Scheme
	"k8s.io/kubernetes/pkg/controlplane" // ymjx: 注册 k8s 核心资源到 legacyscheme.Scheme 中
)

// 1. 初始化 k8s 核心资源注册表全局变量 Scheme,之后别的包可通过 legacyscheme.Scheme 进行引用,从而获知到 k8s 核心资源信息
// pkg/api/legacyscheme/scheme.go

package legacyscheme

import (
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/serializer"
)

var (
	// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered.
	// NOTE: If you are copying this file to start a new api group, STOP! Copy the
	// extensions group instead. This Scheme is special and should appear ONLY in
	// the api group, unless you really know what you're doing.
	// TODO(lavalamp): make the above error impossible.
	Scheme = runtime.NewScheme()

	// Codecs provides access to encoding and decoding for the scheme
	Codecs = serializer.NewCodecFactory(Scheme)

	// ParameterCodec handles versioning of objects that are converted to query parameters.
	ParameterCodec = runtime.NewParameterCodec(Scheme)
)

// 2. 将 k8s 所有核心资源信息通过 各个资源的 install 包信息中 init 函数,注册到 legacyscheme.Scheme 中
// pkg/controlplane/import_known_versions.go
package controlplane

import (
	// These imports are the API groups the API server will support.
	_ "k8s.io/kubernetes/pkg/apis/admission/install"
	_ "k8s.io/kubernetes/pkg/apis/admissionregistration/install"
	_ "k8s.io/kubernetes/pkg/apis/apiserverinternal/install"
	_ "k8s.io/kubernetes/pkg/apis/apps/install"
	_ "k8s.io/kubernetes/pkg/apis/authentication/install"
	_ "k8s.io/kubernetes/pkg/apis/authorization/install"
	_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
	_ "k8s.io/kubernetes/pkg/apis/batch/install"
	_ "k8s.io/kubernetes/pkg/apis/certificates/install"
	_ "k8s.io/kubernetes/pkg/apis/coordination/install"
	_ "k8s.io/kubernetes/pkg/apis/core/install"
	_ "k8s.io/kubernetes/pkg/apis/discovery/install"
	_ "k8s.io/kubernetes/pkg/apis/events/install"
	_ "k8s.io/kubernetes/pkg/apis/extensions/install"
	_ "k8s.io/kubernetes/pkg/apis/flowcontrol/install"
	_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
	_ "k8s.io/kubernetes/pkg/apis/networking/install"
	_ "k8s.io/kubernetes/pkg/apis/node/install"
	_ "k8s.io/kubernetes/pkg/apis/policy/install"
	_ "k8s.io/kubernetes/pkg/apis/rbac/install"
	_ "k8s.io/kubernetes/pkg/apis/scheduling/install"
	_ "k8s.io/kubernetes/pkg/apis/storage/install"
)


// 3. 举例,core 组的资源注册到 legacyscheme.Scheme 中
// pkg/apis/core/install/install.go
package install

import (
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/kubernetes/pkg/api/legacyscheme"
	"k8s.io/kubernetes/pkg/apis/core"
	"k8s.io/kubernetes/pkg/apis/core/v1"
)

func init() {
	Install(legacyscheme.Scheme)
}

// Install registers the API group and adds types to a scheme
func Install(scheme *runtime.Scheme) {
	// ymjx: 如果有多 个资源版本,排在最前面的为资源首选版本
	utilruntime.Must(core.AddToScheme(scheme))                         // ymjx: core.AddToScheme函数注册了core资源组内部版本的资源
	utilruntime.Must(v1.AddToScheme(scheme))                           // ymjx: v1.AddToScheme函数注册了core资源组外部版本的资源
	utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion)) // ymjx: scheme.SetVersionPriority函数注册了资源组的版本顺序
}

Cobra命令行参数解析

cmd/kube-apiserver/app/server.go NewAPIServerCommand 该命令是 kube-apiserver 的启动命令,下面都是解析该函数内部的函数
s := options.NewServerRunOptions() 初始化各个模块的默认配置,
例如初始化Etcd、Audit、Admission等模块的默认配置
completedOptions, err := Complete(s) 通过Complete函数填充默认的配置参数
completedOptions.Validate() 通过Validate函数验证配置参数的合法性和可用性
Run(completedOptions, genericapiserver.SetupSignalHandler()) 最后将ServerRunOptions(kube-apiserver组件的运行配置)对象传入Run函数,Run函数定义了kube-apiserver组件启动的逻辑,它是一个运行不退出的常驻进程。

创建APIServer通用配置

APIServer通用配置是kube-apiserver不同模块实例化所需的配置,APIServer通用配置流程

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

生成通用配置
调用逻辑
cmd/kube-apiserver/app/server.go NewAPIServerCommand --> RunE --> Run --> CreateServerChain
–> CreateKubeAPIServerConfig --> buildGenericConfig
通用配置通过此函数读取,
其他APIServer 之后直接进行引用,不需要再次读取
kubeAPIServerConfig, … := CreateKubeAPIServerConfig(completedOptions)
APIExtensionsServer 配置信息,引用已创建的通用配置 createAPIExtensionsConfig(*kubeAPIServerConfig.GenericConfig, …)
AggregatorServer 配置信息,引用已创建的通用配置 createAggregatorConfig(*kubeAPIServerConfig.GenericConfig …)
  • 接着上面分析,此处详细分析通用配置都做了些什么
cmd/kube-apiserver/app/server.go buildGenericConfig 接下来详细分析如何构建通用配置
1. 实例化genericConfig对象,并注册 handler genericapiserver.NewConfig(legacyscheme.Codecs) 实例化genericConfig对象,
并为genericConfig对象设置默认值
该实例化过程包含个重要函数
DefaultBuildHandlerChain
该函数注册了多个handler,用于认证、授权等
2. 设置启用和禁用 Group/Version genericConfig.MergedResourceConfig = controlplane.DefaultAPIResourceConfigSource() genericConfig.MergedResourceConfig用于设置启用/禁用GV(资源组、资源版本)及其Resource(资源)

如果未在命令行参数中指定启用/禁用的GV,则通过master.DefaultAPIResourceConfigSource启用默认设置的GV及其资源。master.DefaultAPIResourceConfigSource将启用资源版本为Stable和Beta的资源,默认不启用Alpha资源版本的资源。通过EnableVersions函数启用指定资源,而通过DisableVersions函数禁用指定资源
3. OpenAPI 相关配置 genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig( … ) genericConfig.OpenAPIConfig用于生成OpenAPI规范。 在默认的 情况下, 通过DefaultOpenAPIConfig函数为其设置默认值
4. 构建 etcd 存储配置信息对象
storageFactoryConfig
storageFactoryConfig := kubeapiserver.NewStorageFactoryConfig()
storageFactoryConfig.Complete(s.Etcd)
kubeapiserver.NewStorageFactoryConfig 函 数 实 例 化 了 storageFactoryConfig对象, 该对象定义了kube-apiserver与Etcd的 交互方式, 例如Etcd认证、 Etcd地址、 存储前缀等。 另外, 该对象也 定义了资源存储方式,例如资源信息、资源编码类型、资源状态等

storageFactoryConfig.Complete 读取 apiserver 配置的 etcd 加密信息
5. 构建 etcd 存储对象
genericConfig.RESTOptionsGetter
storageFactory, lastErr = completedStorageFactoryConfig.New()

s.Etcd.ApplyWithStorageFactoryTo(storageFactory, genericConfig)
根据上面获取的 storageFactoryConfig 配置信息,创建存储通用配置对象 storageFactory

将 storageFactory 存到了 genericConfig.RESTOptionsGetter 字段中
6. 认证配置

genericConfig.Authentication(认证相关信息)

genericConfig.Authenti-cation.Authenticator(认证器列表)
s.Authentication.ApplyTo(&genericConfig.Authentication …)

调用authInfo.Authenticator, openAPIConfig.SecurityDefinitions, err = authenticatorConfig.New()
kube-apiserver目前提供了9种认证机制, 分别是BasicAuth、 ClientCA 、 TokenAuth 、 BootstrapToken 、 RequestHeader 、 WebhookTokenAuth、 Anonymous、 OIDC、 ServiceAccountAuth。 每一种 认证机制被实例化后会成为认证器(Authenticator),每一个认证器 都被封装在http.Handler请求处理函数中, 它们接收组件或客户端的 请求并认证请求。

该函数会生成认证器,其会调用authenticatorConfig.New函数,该函数会在在实例化认证器的过程中,会根据认证的配置信息(由flags命令行参数传入)决定是否启用认证方法,并对启用的认证方法生成对应的HTTPHandler函数,最后通过union函数将已启用的认证器合并到authenticators数组对象中

authenticators中存放的是已启用的认证器列表。union.New函数 将authenticators合并成一个authenticator认证器,实际上将认证器 列表存放在union结构的Handlers []authenticator.Request对象中。 当客户端请求到达kube-apiserver时, kube-apiserver会遍历认证器 列表, 尝试执行每个认证器, 当有一个认证器返回true时, 则认证成 功。
7. 鉴权配置

genericConfig.Authorization.Authorizer (授权器列表)
genericConfig.RuleResolver(授权规则解析器)
BuildAuthorizer(s, genericConfig.EgressSelector, versionedInformers) 在Kubernetes系统组件或客户端请求通过认证阶段之后, 会来到 授权阶段。 kube-apiserver同样支持多种授权机制, 并支持同时开启 多个授权功能,客户端发起一个请求,在经过授权阶段时,只要有一 个授权器通过则授权成功。

kube-apiserver目前提供了6种授权机制, 分别是AlwaysAllow、 AlwaysDeny、Webhook、Node、ABAC、RBAC。每一种授权机制被实例化 后 会 成 为 授 权 器 ( Authorizer ) , 每 一 个 授 权 器 都 被 封 装 在 http.Handler请求处理函数中, 它们接收组件或客户端的请求并授权 请求。kube-apiserver通过BuildAuthorizer函数实例化授权器,

authorizationConfig.New函数在实例化授权器的过程中, 会根 据–authorization-mode参数的配置信息(由flags命令行参数传入) 决 定 是 否 启 用 授 权 方 法 , 并 对 启 用 的 授 权 方 法 生 成 对 应 的 HTTP Handler 函 数 , 最 后 通 过 union 函 数 将 已 启 用 的 授 权 器 合 并 到 authorizers数组对象中

authorizers中存放的是已启用的授权器列表, ruleResolvers中 存放的是已启用的授权器规则解析器,实际上分别将它们存放在union 结构的[]authorizer.Authorizer和[]authorizer.RuleResolver对象 中。 当客户端请求到达kube-apiserver时, kube-apiserver会遍历授 权器列表,并按照顺序执行授权器,排在前面的授权器具有更高的优 先级(允许或拒绝请求)。 客户端发起一个请求, 在经过授权阶段 时,只要有一个授权器通过,则授权成功。
8. Admission 准入控制器配置 cmd/kube-apiserver/app/server.go

NewAPIServerCommand --> options.NewServerRunOptions() --> kubeoptions.NewAdmissionOptions() --> NewAdmissionOptions()

该函数中的如下两个函数实现了所有准入控制器的注册
genericoptions.NewAdmissionOptions()(该函数还包含准入控制器存储结构 Plugins 的初始化)

RegisterAllAdmissionPlugins(options.Plugins)
Kubernetes系统组件或客户端请求通过授权阶段之后, 会来到准 入控制器阶段,它会在认证和授权请求之后,对象被持久化之前,拦 截kube-apiserver的请求, 拦截后的请求进入准入控制器中处理, 对 请求的资源对象进行自定义(校验、 修改或拒绝)等操作。 kubeapiserver支持多种准入控制器机制,并支持同时开启多个准入控制器 功能,如果开启了多个准入控制器,则按照顺序执行准入控制器

kube-apiserver在启动时注册所有准入控制器, 准入控制器通过 Plugins数据结构统一注册、 存放、 管理所有的准入控制器。

vendor/k8s.io/apiserver/pkg/server
/options/admission.go

vendor/k8s.io/apiserver/pkg/server/plugins.go

创建APIExtensionsServer

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

具体流程介绍如下。 (1)创建GenericAPIServer。 (2)实例化CustomResourceDefinitions。(3)实例化APIGroupInfo,将资源版本、资源、资源存储对象进 行相互映射。

( 4 ) InstallAPIGroup 注 册 APIGroup(apiextensions.k8s.io)。

生成通用配置
调用逻辑
cmd/kube-apiserver/app/server.go NewAPIServerCommand --> RunE --> Run --> CreateServerChain
–> createAPIExtensionsServer --> apiextensionsConfig.Complete().New(delegateAPIServer)
genericServer, err := c.GenericConfig.New(“apiextensions-apiserver”, delegationTarget) APIExtensionsServer的运行依赖于GenericAPIServer,通过c.GenericConfig.New函数创建名为apiextensions-apiserver的服务
s := &CustomResourceDefinitions{ GenericAPIServer: genericServer, } APIExtensionsServer(API扩展服务)通过CustomResourceDefinitions对象进行管理,实例化该对象后才能注册APIExtensionsServer下的资源
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(…) APIGroupInfo 对 象 用 于 描 述 资 源 组 信 息 , 其 中 该 对 象 的 VersionedResourcesStorageMap字段用于存储资源与资源存储对象的 对应关系,其表现形式为map[string]map[string]rest.Storage(即< 资 源 版 本 >/< 资 源 >/< 资 源 存 储 对 象 > ) , 例 如 CustomResourceDefinitions 资 源 与 资 源 存 储 对 象 的 映 射 关 系 是 v1beta1/customresourcedefinitions/customResourceDefintionStor age
重要的函数 NewREST 每个资源(包括子资源)都通过类似于NewREST的函数创建资源存 储对象(即RESTStorage)
InstallAPIGroup 将 APIGroupInfo对象中的<资源组>/<资源版本>/<资源>/<子资源>(包括 资源存储对象)注册到APIExtensionsServerHandler函数。 其过程是 遍历APIGroupInfo, 将<资源组>/<资源版本>/<资源名称>映射到HTTP PATH请求路径, 通过InstallREST函数将资源存储对象作为资源的 Handlers方法, 最后使用go-restful的ws.Route将定义好的请求路径 和 Handlers 方 法 添 加 路 由 到 go-restful 中 。 整 个 过 程 为 InstallAPIGroup→s.installAPIResources→InstallREST
InstallREST InstallREST函数接收restful.Container指针对象。 安装过程分 为4步,分别介绍如下。

( 1 ) prefix 定 义 了 HTTP PATH 请 求 路 径 , 其 表 现 形 式 为 <apiPrefix>/<group>/<version>(即/apis/apiextensions.k8s.io/v1beta1)。

(2)实例化APIInstaller安装器。

( 3 ) 在 installer.Install 安 装 器 内 部 创 建 一 个 go-restful WebService, 然后通过a.registerResourceHandlers函数, 为资源注 册对应的Handlers方法(即资源存储对象Resource Storage), 完成 资源与资源Handlers方法的绑定并为go-restful WebService添加该路 由。

( 4 ) 最 后 通 过 container.Add 函 数 将 WebService 添 加 到 gorestful Container中。

APIExtensionsServer负责管理apiextensions.k8s.io资源组下的 所有资源, 该资源有v1beta1版本。 通过访问http://127.0.0.1: 8080/apis/apiextensions.k8s.io/v1获得该资源/子资源的详细信 息

创建KubeAPIServer

调用逻辑 cmd/kube-apiserver/app/server.go NewAPIServerCommand --> RunE --> Run --> CreateServerChain
–> CreateKubeAPIServer

创建KubeAPIServer的流程与创建APIExtensionsServer的流程类 似,其原理都是将<资源组>/<资源版本>/<资源>与资源存储对象进行 映 射 并 将 其 存 储 至 APIGroupInfo 对 象 的 VersionedResourcesStorageMap字段中。 通过installer.Install安装 器 为 资 源 注 册 对 应 的 Handlers 方 法 ( 即 资 源 存 储 对 象 Resource Storage), 完成资源与资源Handlers方法的绑定并为go-restful WebService 添 加 该 路 由 。 最 后 将 WebService 添 加 到 go-restful Container中。创建KubeAPIServer的流程如图7-17所示。

创建KubeAPIServer的流程说明如下。

  1. 创建GenericAPIServer。
  2. 实例化 Instance( 旧版本叫 Master)。
  3. InstallLegacyAPI注册/api资源。(没有组名的资源,pod 的组名就为空,该组也叫作核心组 core group)
    • KubeAPIServer会先判断CoreGroups/v1(即核心资源组/资源版本)是否已启用,如果其已启用,则通过m.InstallLegacyAPI函数将CoreGroups/v1注册到KubeAPIServer的/api/v1下。可以通过访问http://127.0.0.1:8080/api/v1获得CoreGroups/v1下的资源与子资源信息。
  4. InstallAPIs注册/apis资源。(有组名的资源,如 deployment 在 apps group 中)
    • 通过m.InstallAPIsI函数将【拥有组名的资源组】注册到KubeAPIServer的/apis下。可以通过访问http://localhost:8080/apis/apps/v1/deployments获得其下的资源与子资源信息。

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

创建AggregatorServer

同样,创建AggregatorServer的流程与创建APIExtensionsServer的流程类似,其原理都是将<资源组>/<资源版本>/<资源>与资源存储对象进行映射并将其存储至APIGroupInfo对象的VersionedResourcesStorageMap字段中。通过installer.Install安装器为资源注册对应的Handlers方法(即资源存储对象ResourceStorage),完成资源与资源Handlers方法的绑定并为go-restfulWebService添加该路由。最后将WebService添加到go-restfulContainer中。

AggregatorServer负责管理apiregistration.k8s.io资源组下的 所 有 资 源 , 这 些 资 源 有 v1beta1 和 v1 版 本 , 通 过 访 问 http://127.0.0.1:8080/apis/apiregistration.k8s.io/v1可以获得 资源/子资源的详细信息

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

创建GenericAPIServer(小结,分析上面三种Server异同)

  • 上面小结
相同的注册流程
1实例化APIGroupInfo对象 APIGroupInfo 对 象 用 于 描 述 资 源 组 信 息 ( group , version ,scheme,NegotiatedSerializer,ParameterCodec 等)
其中该对象的VersionedResourcesStorageMap字段用于存储资源与资源存储对象的对应关系,其表现形式为map[string]map[string]rest.Storage(即<资源版本>/<资源>/<资源存储对象>),例如CustomResourceDefinitions资源与资源存储对象的映射关系是v1beta1/customresourcedefinitions/customResourceDefintionStorage。
2创建资源存储对象RESTStorage 每个资源(包括子资源)都通过类似于NewREST的函数创建资源存 储对象(即RESTStorage)
(注意:一个资源组对应一个APIGroupInfo对象,该资源组内的每个资源(包括子资源)对应一个资源存储对象RESTStorage。)
3InstallAPIGroup 注 册 APIGroupInfo 该过程非常重要,将APIGroupInfo对象中的<资源组>/<资源版本>/<资源>/<子资源>(包括资源存储对象)注册到APIExtensionsServerHandler函数。其过程是遍历APIGroupInfo,将<资源组>/<资源版本>/<资源名称>映射到HTTPPATH请求路径,通过InstallREST函数将资源存储对象作为资源的Handlers方法,最后使用go-restful的ws.Route将定义好的请求路径和Handlers方法添加路由到go-restful中。整个过程为InstallAPIGroup→s.installAPIResources→InstallREST
资源的操作 kube-apiserver将RESTStorage封装成HTTPHandler函数,资源存储对象以RESTful的方式运行,一个RESTStorage对象负责一个资源的增、删、改、查操作。当操作XX资源数据时,通过对应的RESTStorage资源存储对象与genericregistry.Store进行交互
不同点
APIExtensionsServer 关注CustomResourceDefinitions资源数据
APIExtensionsServer负责管理apiextensions.k8s.io资源组下的所有资源,该资源有v1beta1版本。通过访问http://127.0.0.1:8080/apis/apiextensions.k8s.io/v1获得该资源/子资源的详细信息
KubeAPIServer 关注 k8s 核心资源数据

KubeAPIServer负责管理众多资源组,以apps资源组为例,通过访问http://127.0.0.1:8080/apis/apps/v1可以获得该资源/子资源的详细信息。
【有组名前缀为 /apis】通过m.InstallAPIs函数将拥有组名的资源组注册到KubeAPIServer的/apis下。可以通过访问http://localhost:8080/apis/apps/v1/deployments获得其下的资源与子资源信息。
【没有组名前缀为 /api】KubeAPIServer会先判断CoreGroups/v1(即核心资源组/资源版本)是否已启用,如果其已启用,则通过m.InstallLegacyAPI函数将CoreGroups/v1注册到KubeAPIServer的/api/v1下。可以通过访问http://127.0.0.1:8080/api/v1获得CoreGroups/v1下的资源与子资源信息。
AggregatorServer 关注 ApiService 资源数据
AggregatorServer负责管理apiregistration.k8s.io资源组下的所有资源,这些资源有v1beta1和v1版本,通过访问http://127.0.0.1:8080/apis/apiregistration.k8s.io/v1可以获得资源/子资源的详细信息
底层共同依赖 无论创建APIExtensionsServer、KubeAPIServer,还是AggregatorServer,它们在底层都依赖于GenericAPIServer。通过GenericAPIServer将Kubernetes资源与RESTAPI进行映射
通 过 c.GenericConfig.New 函 数 创 建 GenericAPIServer 。 在 NewAPIServerHandler函数的内部, 通过restful.NewContainer创建 restful Container实例,并设置Router路由
NewAPIServerCommand --> RunE --> Run --> CreateServerChain
–> createAPIExtensionsServer --> apiextensionsConfig.Complete().New --> c.GenericConfig.New --> NewAPIServerHandler 和 installAPI(s, c.Config)

通 过 c.GenericConfig.New 函 数 创 建 GenericAPIServer 。
- 在 NewAPIServerHandler函数的内部, 通过restful.NewContainer创建 restful Container实例,并设置Router路由
- installAPI通过routes注册GenericAPIServer的相关API

启动HTTP服务

  • 好像废弃了,没有找到此部分的调用逻辑
路径 staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go func (s *DeprecatedInsecureServingInfo) Serve

启动HTTPS服务

调用逻辑 cmd/kube-apiserver/app/server.go NewAPIServerCommand --> RunE --> Run --> prepared.Run(stopCh) --> s.runnable.Run(stopCh) --> func (s preparedGenericAPIServer) Run --> s.NonBlockingRun(stopHttpServerCh, shutdownTimeout) --> s.SecureServingInfo.Serve(s.Handler, shutdownTimeout, internalStopCh)
HTTPS服务在http.Server上增加了TLSConfig配置, TLSConfig用 于配置相关证书, 可以通过命令行相关参数(–client-ca-file、 -tls-private-key-file、–tls-cert-file参数)进行配置。

权限控制

kube-apiserver (Kubernetes API Server)作为Kubernetes集群的请求入口,接收集群中组件与客户端的访问请求,kube-apiserver 对接口请求访问,提供了3种安全权限控制,每个请求都需要经过认证、授权及准入控制器才有权限操作资源对象。Kubernetes ApI Server权限控制如图7-20所示。

Kubernetes 支持3种安全权限控制,分别介绍如下。

•认证:针对请求的认证,确认是否具有访问Kubernetes集群的权限。

•授权:针对资源的授权,确认是否对资源具有相关权限。

•准入控制器:在认证和授权之后,对象被特久化之前,拦截 kube-apiserver的请求,拦截后的请求进入准入控制器中处理,对请求的资源对象进行自定义(校验、修改或拒绝)等操作。

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

认证

在开启HTTPS服务后,所有的请求都需要经过认证。kubeapiserver支持多种认证机制,并支持同时开启多个认证功能。当客户端发起一个请求,经过认证阶段时,只要有一个认证器通过,则认证成功。如果认证成功,用户名就会传入授权阶段做进一步的授权验证,而对于认证失败的请求则返回HTTP 401状态码。

kube-apiserver目前提供了9种认证机制,分别是BasicAuth、 ClientCA 、 TokenAuth 、 BootstrapToken 、 RequestHeader、WebhookTokenAuth、 Anonymous、 OIDC、 ServiceAccountAuth。 每一种 认证机制被实例化后会成为认证器(Authenticator),每一个认证器 都被封装在http.Handler请求处理函数中, 它们接收组件或客户端的 请求并认证请求。 当客户端请求通过认证器并返回true时, 则表示认 证通过。认证流程如图7-21所示。

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

假 设 所 有 的 认 证 器 都 被 启 用 , 当 客 户 端 发 送 请 求 到 kubeapiserver服务,该请求会进入Authentication Handler函数(处理认 证相关的Handler函数),在Authentication Handler函数中,会遍历已启用的认证器列表, 尝试执行每个认证器, 当有一个认证器返回 true时,则认证成功,否则继续尝试下一个认证器。

WithAuthentication函数可以作为kube-apiserver的认证Handler 函数。 如果auth认证器为空, 说明kube-apiserver未启用任何认证功 能;如果其不为空, 则通过auth.AuthenticateRequest函数对请求进 行认证。 如果身份认证失败, 则通过failed.ServeHTTP函数返回HTTP 401 Unauthorized, 表示认证被拒绝;如果身份认证成功, 则不再需 要Authorization请求头并进入授权阶段。

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

# 接口
vendor/k8s.io/apiserver/pkg/authentication/authenticator/interfaces.go

# 接口的调用
vendor/k8s.io/apiserver/pkg/server/config.go

# DefaultBuildHandlerChain
vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go

授权

在客户端请求通过认证之后, 会来到授权阶段。 kube-apiserver 同样也支持多种授权机制,并支持同时开启多个授权功能,如果开启 多个授权功能,则按照顺序执行授权器,在前面的授权器具有更高的 优先级来允许或拒绝请求。 客户端发起一个请求, 在经过授权阶段 后,只要有一个授权器通过则授权成功。

kube-apiserver目前提供了6种授权机制, 分别是AlwaysAllow、 AlwaysDeny 、 ABAC 、 Webhook 、 RBAC 、 Node , 可 通 过 指 定 -authorization-mode参数设置授权机制。

● AlwaysAllow :允许所有请求。

● AlwaysDeny :阻止所有请求。

● ABAC :即Attribute-Based Access Control, 基于属性的访问控制。

●Webhook :基于Webhook的一种HTTP协议回调, 可进行远程授 权管理。

● RBAC:即Role-Based Access Control, 基于角色的访问控 制。

● Node :节点授权,专门授权给kubelet发出的API请求。

每一种授权机制被实例化后会成为授权器(Authorizer), 每一 个授权器都被封装在http.Handler函数中, 它们接收组件或客户端的 请求并授权请求。 当客户端请求到达kube-apiserver的授权器, 并返 回DecisionAllow决策状态时,则表示授权成功。

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

上面的WithAuthorization函数是kube-apiserver的授权Handler 方法。 如果a授权器为空, 则说明kube-apiserver未启用任何授权功 能;如果a授权器不为空, 则通过GetAuthorizerAttributes函数从 HTTP请求中获取客户端信息。a.Authorize函数对请求进行授权,如果 授 权 失 败 , 则 通 过 responsewriters.Forbidden 函 数 返 回 HTTP 401 Unauthorized并返回授权失败的原因。如果返回DecisionAllow决策状 态,则表示授权成功,并进入准入控制器阶段。

【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析,Kubernetes学习笔记,kubernetes,容器,云原生

# 接口
vendor/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go

# 接口的调用
vendor/k8s.io/apiserver/pkg/endpoints/filters/authorization.go

# DefaultBuildHandlerChain
vendor/k8s.io/apiserver/pkg/server/config.go

准入控制

准入控制器会在验证和授权请求之后, 对象被持久化之前, 拦截 kube-apiserver的请求, 拦截后的请求进入准入控制器中处理, 对请 求的资源对象执行自定义(校验、修改或拒绝等)操作。准入控制器 以插件的形式运行在kube-apiserver进程中, 插件化的好处在于可扩 展插件并单独启用/禁用指定插件,也可以将每个准入控制器称为准入 控制器插件。

kube-apiserver支持多种准入控制器机制, 并支持同时开启多个 准入控制器功能,如果开启了多个准入控制器,则按照顺序执行准入 控制器。

kube-apiserver目前提供了31种准入控制器,分为两种准入控制器。

  • 变更准入控制器(Mutating Admission Controller):用于变更信息,能够修改用户提交的资源对象信息。

  • 验证准入控制器(Validating Admission Controller):用于身份验证,能够验证用户提交的资源对象信息。

  • 提示 :变更准入控制器运行在验证准入控制器之前。文章来源地址https://www.toymoban.com/news/detail-775057.html

vendor/k8s.io/apiserver/pkg/admission/interfaces.go
// 遍历函数路径:vendor/k8s.io/apiserver/pkg/admission/chain.go
// admission 插件路径: plugin/pkg/admission

到了这里,关于【k8s源码分析-Apiserver-2】kube-apiserver 结构概览以及主体部分源码分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • k8s修改apiserver证书可用年限

    使用 kubeadm 部署的 K8S 集群中,apiserver 证书的默认可用年限只有一年。如果直接用在生产环境,当证书过期后会造成 K8S 集群瘫痪,从而影响现网业务。 1,查看 K8S 集群所有证书存放位置 2,查看 apiserver 证书信息,默认可用年限只有一年 3,查看 ca 证书信息,默认可用年限为

    2024年02月08日
    浏览(38)
  • k8s apiserver如何支持http访问?

    原本是可以通过设置api-server的--insecure-port来实现,但是这个参数已经被废弃了,更好的方法则是使用proxy来实现: 在集群任意一个节点上起一个proxy服务,并设置允许所有host访问: 然后通过 节点IP:8001 进行访问

    2024年02月15日
    浏览(44)
  • 通过keepalived+nginx实现 k8s apiserver节点高可用

    K8s 主机配置: 配置: 4Gib 内存/4vCPU/60G 硬盘 网络:机器相互可以通信 k8s 实验环境网络规划: podSubnet(pod 网段) 10.244.0.0/16 serviceSubnet(service 网段): 10.96.0.0/12 物理机网段:192.168.1.0/24 2个控制节点2个工作节点 K8S集群角色 IP地址 主机名 安装的组件 控制节点 192.168.1.63 xueg

    2024年02月03日
    浏览(40)
  • k8s mysql集群 & 分布式锁 & apiserver & etcd 的关系

    在 Kubernetes (k8s) 中,MySQL 集群可以使用分布式锁来确保在多个实例之间对共享资源的互斥访问。这是通过结合 Kubernetes API Server 和 etcd 来实现的。 Kubernetes API Server 是 k8s 集群中的核心组件之一,它充当了集群的控制平面,提供了对集群资源的管理和操作接口。API Server 是一个

    2024年02月07日
    浏览(52)
  • 【博客682】k8s apiserver bookmarks机制以更高效检测变更

    List-Watch 是kubernetes中server和client通信的最核心的机制, 比如说api-server监听etcd, kubelet监听api-server, scheduler监听api-server等等,其实其他模块监听api-server相当于监听etcd,因为在k8s的设计中,只有api-server能跟etcd通信,其他模块需要etcd的数据就只好监听api-server了。 etcd默认保留

    2024年02月15日
    浏览(45)
  • 【k8s】Unable to restart cluster, will reset it: apiserver healthz异常

    问题描述 该问题在执行 minikube start 命令后出现的无法启动的异常 完整异常描述: 翻译:无法重新启动群集,将重置它:apiserver healthz:apiserver进程从未出现 问题解决办法 问题分析:未构建成功服务,并由于存在国内墙的困扰,哪怕指定了阿里云的镜像库依旧失败,这可能是由

    2023年04月10日
    浏览(44)
  • 【K8S系列】深入解析k8s 网络插件—kube-router

    做一件事并不难,难的是在于坚持。坚持一下也不难,难的是坚持到底。 文章标记颜色说明: 黄色 :重要标题 红色 :用来标记结论 绿色 :用来标记论点 蓝色 :用来标记论点 在现代容器化应用程序的世界中,容器编排平台Kubernetes已经成为标准。Kubernetes是一个分布式系统

    2024年02月08日
    浏览(37)
  • k8s kube-proxy详解

    kube-proxy是kubernetes中网络核心组件,实现了服务暴露和转发等网络功能。kube-proxy支持userspace,ipvs和iptables三种代理模式。userspace性能问题较严重,基本不再使用,应用最多的是iptables和ipvs模式。 kube-proxy 以daemonset的方式运行在每个Node计算节点上,负责Pod网络代理, 它会定时通

    2024年02月10日
    浏览(60)
  • k8s安装kube-promethues(0.7版本)

    目录 k8s安装kube-promethues(0.7版本) 一.检查本地k8s版本,下载对应安装包 二.安装前准备 1.文件分类整理 2.查看K8s集群是否安装NFS持久化存储,如果没有则需要安装配置 1).安装NFS服务 2).k8s注册nfs服务 3.修改Prometheus 持久化 4.修改grafana持久化配置 5.修改 promethus和Grafana的Service 端口

    2024年02月08日
    浏览(42)
  • 详解K8s 镜像缓存管理kube-fledged

    本文分享自华为云社区《K8s 镜像缓存管理 kube-fledged 认知》,作者: 山河已无恙。 我们知道  k8s  上的容器调度需要在调度的节点行拉取当前容器的镜像,在一些特殊场景中, 需要 快速启动和/或扩展 的应用程序。例如,由于数据量激增,执行实时数据处理的应用程序需要

    2024年04月15日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包