【K8s源码品读】006:Phase 1 - kube-apiserver - GenericAPIServer的初始化

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 理解kube-apiserver是中的管理核心资源的KubeAPIServer是怎么启动的

聚焦目标

理解kube-apiserver是中的管理核心资源的KubeAPIServer是怎么启动的

目录

  1. genericServer的创建
  2. 创建REST的Handler
  3. Generic的API路由规则
  4. 初始化核心Apiserver
  5. 核心资源的API路由规则
  6. 创建Pod的函数

GenericServer

// 在APIExtensionsServer、KubeAPIServer和AggregatorServer三种Server启动时,我们都能发现这么一个函数
// APIExtensionsServer
genericServer, err := c.GenericConfig.New("apiextensions-apiserver", delegationTarget)
// KubeAPIServer
s, err := c.GenericConfig.New("kube-apiserver", delegationTarget)
// AggregatorServer
genericServer, err := c.GenericConfig.New("kube-aggregator", delegationTarget)

// 都通过GenericConfig创建了genericServer,我们先大致浏览下
func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*GenericAPIServer, error) {
   
    // 新建Handler
    apiServerHandler := NewAPIServerHandler(name, c.Serializer, handlerChainBuilder, delegationTarget.UnprotectedHandler())

    // 实例化一个Server
    s := &GenericAPIServer{
   
    ...
  }

    // 处理钩子hook操作
    for k, v := range delegationTarget.PostStartHooks() {
   
        s.postStartHooks[k] = v
    }

    for k, v := range delegationTarget.PreShutdownHooks() {
   
        s.preShutdownHooks[k] = v
    }

    // 健康监测
    for _, delegateCheck := range delegationTarget.HealthzChecks() {
   
        skip := false
        for _, existingCheck := range c.HealthzChecks {
   
            if existingCheck.Name() == delegateCheck.Name() {
   
                skip = true
                break
            }
        }
        if skip {
   
            continue
        }
        s.AddHealthChecks(delegateCheck)
    }

  // 安装API相关参数,这个是重点
    installAPI(s, c.Config)

    return s, nil
}

NewAPIServerHandler

func NewAPIServerHandler(name string, s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler {
   
    // 采用了 github.com/emicklei/go-restful 这个库作为 RESTful 接口的设计,目前了解即可
    gorestfulContainer := restful.NewContainer()

}

installAPI

func installAPI(s *GenericAPIServer, c *Config) {
   
  // 添加 /index.html 路由规则
    if c.EnableIndex {
   
        routes.Index{
   }.Install(s.listedPathProvider, s.Handler.NonGoRestfulMux)
    }
  // 添加go语言 /pprof 的路由规则,常用于性能分析
    if c.EnableProfiling {
   
        routes.Profiling{
   }.Install(s.Handler.NonGoRestfulMux)
        if c.EnableContentionProfiling {
   
            goruntime.SetBlockProfileRate(1)
        }
        routes.DebugFlags{
   }.Install(s.Handler.NonGoRestfulMux, "v", routes.StringFlagPutHandler(logs.GlogSetter))
    }
  // 添加监控相关的 /metrics 的指标路由规则
    if c.EnableMetrics {
   
        if c.EnableProfiling {
   
            routes.MetricsWithReset{
   }.Install(s.Handler.NonGoRestfulMux)
        } else {
   
            routes.DefaultMetrics{
   }.Install(s.Handler.NonGoRestfulMux)
        }
    }
    // 添加版本 /version 的路由规则
    routes.Version{
   Version: c.Version}.Install(s.Handler.GoRestfulContainer)
    // 开启服务发现
    if c.EnableDiscovery {
   
        s.Handler.GoRestfulContainer.Add(s.DiscoveryGroupManager.WebService())
    }
    if feature.DefaultFeatureGate.Enabled(features.APIPriorityAndFairness) {
   
        c.FlowControl.Install(s.Handler.NonGoRestfulMux)
    }
}

Apiserver

func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*Master, error) {
   
    // genericServer的初始化
    s, err := c.GenericConfig.New("kube-apiserver", delegationTarget)
    // 核心KubeAPIServer的实例化
    m := &Master{
   
        GenericAPIServer:          s,
        ClusterAuthenticationInfo: c.ExtraConfig.ClusterAuthenticationInfo,
    }

    // 注册Legacy API的注册
    if c.ExtraConfig.APIResourceConfigSource.VersionEnabled(apiv1.SchemeGroupVersion) {
   
        legacyRESTStorageProvider := corerest.LegacyRESTStorageProvider{
   }
        if err := m.InstallLegacyAPI(&c, c.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider); err != nil {
   
            return nil, err
        }
    }
    // REST接口的存储定义,可以看到很多k8s上的常见定义,比如node节点/storage存储/event事件等等
    restStorageProviders := []RESTStorageProvider{
   
        authenticationrest.RESTStorageProvider{
   Authenticator: c.GenericConfig.Authentication.Authenticator, APIAudiences: c.GenericConfig.Authentication.APIAudiences},
        authorizationrest.RESTStorageProvider{
   Authorizer: c.GenericConfig.Authorization.Authorizer, RuleResolver: c.GenericConfig.RuleResolver},
        autoscalingrest.RESTStorageProvider{
   },
        batchrest.RESTStorageProvider{
   },
        certificatesrest.RESTStorageProvider{
   },
        coordinationrest.RESTStorageProvider{
   },
        discoveryrest.StorageProvider{
   },
        extensionsrest.RESTStorageProvider{
   },
        networkingrest.RESTStorageProvider{
   },
        noderest.RESTStorageProvider{
   },
        policyrest.RESTStorageProvider{
   },
        rbacrest.RESTStorageProvider{
   Authorizer: c.GenericConfig.Authorization.Authorizer},
        schedulingrest.RESTStorageProvider{
   },
        settingsrest.RESTStorageProvider{
   },
        storagerest.RESTStorageProvider{
   },
        flowcontrolrest.RESTStorageProvider{
   },
        // keep apps after extensions so legacy clients resolve the extensions versions of shared resource names.
        // See https://github.com/kubernetes/kubernetes/issues/42392
        appsrest.StorageProvider{
   },
        admissionregistrationrest.RESTStorageProvider{
   },
        eventsrest.RESTStorageProvider{
   TTL: c.ExtraConfig.EventTTL},
    }
  // 注册API
    if err := m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...); err != nil {
   
        return nil, err
    }
    // 添加Hook
    m.GenericAPIServer.AddPostStartHookOrDie("start-cluster-authentication-info-controller", func(hookContext genericapiserver.PostStartHookContext) error {
   
    })
    return m, nil
}

注册API的关键在InstallLegacyAPIInstallAPIs,如果你对kubernetes的资源有一定的了解,会知道核心资源都放在Legacy中(如果不了解的话,点击函数看一下,就能有所有了解)

InstallLegacyAPI

func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) error {
   
  // RESTStorage的初始化
    legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter)

  // 前缀为 /api,注册上对应的Version和Resource
  // Pod作为核心资源,没有Group的概念
    if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil {
   
        return fmt.Errorf("error in registering group versions: %v", err)
    }
    return nil
}

// 我们再细看这个RESTStorage的初始化
func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generic.RESTOptionsGetter) (LegacyRESTStorage, genericapiserver.APIGroupInfo, error) {
   
    // pod 模板
    podTemplateStorage, err := podtemplatestore.NewREST(restOptionsGetter)
    // event事件
    eventStorage, err := eventstore.NewREST(restOptionsGetter, uint64(c.EventTTL.Seconds()))
    // limitRange资源限制
    limitRangeStorage, err := limitrangestore.NewREST(restOptionsGetter)
    // resourceQuota资源配额
    resourceQuotaStorage, resourceQuotaStatusStorage, err := resourcequotastore.NewREST(restOptionsGetter)
    // secret加密
    secretStorage, err := secretstore.NewREST(restOptionsGetter)
    // PV 存储
    persistentVolumeStorage, persistentVolumeStatusStorage, err := pvstore.NewREST(restOptionsGetter)
    // PVC 存储
    persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage, err := pvcstore.NewREST(restOptionsGetter)
    // ConfigMap 配置
    configMapStorage, err := configmapstore.NewREST(restOptionsGetter)
    // 等等核心资源,暂不一一列举

  // pod模板,我们的示例nginx-pod属于这个类型的资源
  podStorage, err := podstore.NewStorage()

  // 保存storage的对应关系
  restStorageMap := map[string]rest.Storage{
   
        "pods":             podStorage.Pod,
        "pods/attach":      podStorage.Attach,
        "pods/status":      podStorage.Status,
        "pods/log":         podStorage.Log,
        "pods/exec":        podStorage.Exec,
        "pods/portforward": podStorage.PortForward,
        "pods/proxy":       podStorage.Proxy,
        "pods/binding":     podStorage.Binding,
        "bindings":         podStorage.LegacyBinding,
    ...
  }
}

Create Pod

// 查看Pod初始化
func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGetter, proxyTransport http.RoundTripper, podDisruptionBudgetClient policyclient.PodDisruptionBudgetsGetter) (PodStorage, error) {
   

    store := &genericregistry.Store{
   
        NewFunc:                  func() runtime.Object {
    return &api.Pod{
   } },
        NewListFunc:              func() runtime.Object {
    return &api.PodList{
   } },
        PredicateFunc:            registrypod.MatchPod,
        DefaultQualifiedResource: api.Resource("pods"),
        // 增改删的策略
        CreateStrategy:      registrypod.Strategy,
        UpdateStrategy:      registrypod.Strategy,
        DeleteStrategy:      registrypod.Strategy,
        ReturnDeletedObject: true,

        TableConvertor: printerstorage.TableConvertor{
   TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
    }
}
// 查看 Strategy 的初始化
var Strategy = podStrategy{
   legacyscheme.Scheme, names.SimpleNameGenerator}

// 又查询到Scheme的初始化。Schema可以理解为Kubernetes的注册表,即所有的资源类型必须先注册进Schema才可使用
var Scheme = runtime.NewScheme()
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
Kubernetes 流计算 容器
Flink on k8s的话,怎么在容器运行前初始化一些脚本?
Flink on k8s的话,怎么在容器运行前初始化一些脚本?
78 1
|
7天前
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
|
1月前
|
Kubernetes 安全 Linux
ansible-install-k8s 之 1 初始化环境
ansible-install-k8s 之 1 初始化环境
|
6月前
|
Kubernetes 搜索推荐 网络协议
使用 kubeadm 部署 Kubernetes 集群(三)kubeadm 初始化 k8s 证书过期解决方案
使用 kubeadm 部署 Kubernetes 集群(三)kubeadm 初始化 k8s 证书过期解决方案
354 8
|
4月前
|
Kubernetes 负载均衡 调度
k8s初始化pod-pod标签
k8s初始化pod-pod标签
49 1
|
3月前
|
消息中间件 Kubernetes 数据库
在k8S中,初始化容器(init container)概念原理是什么?
在k8S中,初始化容器(init container)概念原理是什么?
|
6月前
|
Kubernetes Ubuntu Docker
初始化k8s多结点集群
在Ubuntu22.04.3 LTS上设置k8s多节点集群,采用Docker v24.0.6、kubeadm v1.28和cir-dockerd v0.3.4。首先安装docker和cri-dockerd,更新k8s三件套至v1.28。然后,参照官方文档进行`kubeadm init`初始化集群,配置包括自定义镜像仓库、控制面端点等。成功初始化后,显示了相关证书和配置信息。最后,提供了一些额外的kubectl命令以管理节点。
75 1
|
6月前
|
Kubernetes 容器 Perl
K8S集群重新初始化--详细过程
K8S集群重新初始化--详细过程
320 0
|
6月前
|
Kubernetes Ubuntu Linux
玩转Kubernetes—尝试以不同方式初始化集群
玩转Kubernetes—尝试以不同方式初始化集群
85 0
|
6月前
|
Kubernetes Cloud Native 虚拟化
云原生|kubernetes|找回丢失的etcd集群节点---etcd节点重新添加,扩容和重新初始化k8s的master节点
云原生|kubernetes|找回丢失的etcd集群节点---etcd节点重新添加,扩容和重新初始化k8s的master节点
233 0