从0到1启动kube-apiserver:深入源码解析API Server启动全流程

AI编程·六月创作之星博客挑战赛 10w+人浏览 1.6k人参与

前言

上个月遇到个诡异的集群启动问题:kube-apiserver进程在,日志也没有报错,端口也在监听,但就是无法创建Pod,kubectl命令卡死不动。查看了半小时日志没看出问题,最后只能翻源码排查。

这一翻才发现,原来kube-apiserver内部不是单一的服务,而是创建了3个Server组成服务链(KubeAPIServer、APIExtensionsServer、AggregatorServer)。AggregatorServer初始化时去连接metrics-server超时,导致整个启动流程卡住。

这次经历让我意识到:要真正理解K8s,必须深入apiserver源码。今天就带大家从main函数开始,完整走一遍kube-apiserver的启动流程。

kube-apiserver是什么?

在深入源码前,我们先明确kube-apiserver的地位:

┌─────────────────────────────────────────────────────────────┐
│                        Kubernetes集群                        │
├─────────────────────────────────────────────────────────────┤
│  Master节点                                                  │
│  ├─ kube-apiserver  ← 集群的"大脑",所有API入口              │
│  ├─ kube-controller-manager                                 │
│  ├─ kube-scheduler                                          │
│  └─ etcd                                                    │
├─────────────────────────────────────────────────────────────┤
│  Worker节点                                                  │
│  ├─ kubelet                                                 │
│  └─ kube-proxy                                              │
└─────────────────────────────────────────────────────────────┘

kube-apiserver的核心职责:

  1. API网关:所有K8s资源操作的统一入口(kubectl、kubelet、controller等都通过它操作资源)
  2. 认证鉴权:验证请求身份,检查是否有权限执行操作
  3. 准入控制:对请求进行校验和修改(如自动注入Sidecar)
  4. 数据持久化:将资源状态写入etcd
  5. ** watch机制**:提供长连接监听资源变化

为什么要学apiserver源码?

  • 它是K8s最核心的组件,理解它就理解了K8s的半壁江山
  • 排查集群问题时,80%的问题都能在apiserver找到线索
  • 要开发K8s扩展(CRD、Operator、APIService),必须懂apiserver架构

apiserver启动全流程概览

先看一张完整的启动流程图:

main()
  ↓
NewAPIServerCommand() 创建Cobra命令
  ↓
command.Execute() 执行命令
  ↓
PersistentPreRunE 设置WarningHandler
  ↓
RunE 核心启动流程
  ├─ PrintAndExitIfRequested() 打印版本信息
  ├─ PrintFlags() 打印启动参数
  ├─ checkNonZeroInsecurePort() 检查不安全端口
  ├─ Complete() 补全配置默认值
  ├─ Validate() 校验参数合法性
  ↓
Run() 真正的启动
  ├─ CreateServerChain() 创建3个Server
  │   ├─ CreateKubeAPIServer()         核心API Server
  │   ├─ createAPIExtensionsServer()   CRD扩展Server
  │   └─ createAggregatorServer()      聚合层Server
  ├─ server.PrepareRun() 准备运行
  └─ prepared.Run(stopCh) 启动服务 ← 阻塞在此

关键点:kube-apiserver的启动可以分为三个阶段:

  1. 准备阶段:参数解析、配置补全、参数校验
  2. 创建阶段:创建3个Server组成服务链
  3. 运行阶段:启动HTTP服务,阻塞等待

第一阶段:程序入口与命令创建

main函数:一切的开始

apiserver的入口在cmd/kube-apiserver/apiserver.go

func main() {
    // 初始化随机数种子
    rand.Seed(time.Now().UnixNano())
    
    // 设置pflag标准化函数(将_转换为-)
    pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
    
    // 创建Cobra命令
    command := app.NewAPIServerCommand()
    
    // 初始化日志
    logs.InitLogs()
    defer logs.FlushLogs()
    
    // 执行命令
    if err := command.Execute(); err != nil {
        os.Exit(1)
    }
}

代码分析

  • 使用rand.Seed初始化随机数(用于生成UUID等)
  • 使用pflag替代标准库flag,支持POSIX风格长选项
  • SetNormalizeFunc--some_flag自动转换为--some-flag
  • 使用logs.InitLogs初始化klog日志系统

NewAPIServerCommand:构建Cobra命令树

func NewAPIServerCommand() *cobra.Command {
    // 创建默认的ServerRunOptions
    opts := options.NewServerRunOptions()
    
    cmd := &cobra.Command{
        Use: "kube-apiserver",
        Long: `The Kubernetes API server validates and configures data...`,
        
        // 持久化PreRun:设置前执行
        PersistentPreRunE: func(*cobra.Command, []string) error {
            // 静默client-go的warning(apiserver自己就是服务端,不需要warning)
            rest.SetDefaultWarningHandler(rest.NoWarnings{})
            return nil
        },
        
        // 核心Run函数
        RunE: func(cmd *cobra.Command, args []string) error {
            verflag.PrintAndExitIfRequested()
            fs := cmd.Flags()
            
            // 打印所有启动参数(便于调试)
            cliflag.PrintFlags(fs)
            
            // 检查不安全端口(已废弃,必须为0)
            if err := checkNonZeroInsecurePort(fs); err != nil {
                return err
            }
            
            // 补全配置(设置默认值)
            completedOptions, err := Complete(opts)
            if err != nil {
                return err
            }
            
            // 校验参数
            if errs := completedOptions.Validate(); len(errs) != 0 {
                return utilerrors.NewAggregate(errs)
            }
            
            // 真正的启动!
            return Run(completedOptions, genericapiserver.SetupSignalHandler())
        },
    }
    
    // 绑定各种选项到命令行参数
    opts.AddFlags(cmd.Flags())
    
    return cmd
}

Cobra执行顺序回顾

PersistentPreRun()
    ↓
PreRun()
    ↓
Run()  ← 核心逻辑
    ↓
PostRun()
    ↓
PersistentPostRun()

第二阶段:参数处理与校验

1. 打印版本信息

verflag.PrintAndExitIfRequested()

如果用户传了--version,打印版本信息后退出:

$ kube-apiserver --version
Kubernetes v1.25.0

2. 打印启动参数

cliflag.PrintFlags(fs)

// 实际输出示例:
// FLAG: --advertise-address="192.168.1.100"
// FLAG: --etcd-servers="https://127.0.0.1:2379"
// FLAG: --secure-port="6443"
// ...

为什么要打印参数?

  • 便于排查问题时确认实际使用的配置
  • 日志审计需要
  • 调试时快速确认参数是否生效

3. 检查不安全端口

func checkNonZeroInsecurePort(fs *pflag.FlagSet) error {
    for _, name := range options.InsecurePortFlags {
        val, err := fs.GetInt(name)
        if err != nil {
            return err
        }
        if val != 0 {
            return fmt.Errorf("invalid port value %d: only zero is allowed", val)
        }
    }
    return nil
}

背景:早期K8s支持非安全端口(HTTP),现在为了安全已废弃,必须为0。

4. Complete:补全配置

Complete函数负责填充配置的默认值:

func Complete(s *options.ServerRunOptions) (completedServerRunOptions, error) {
    var options completedServerRunOptions
    
    // 补全GenericServerRunOptions
    if err := s.GenericServerRunOptions.DefaultAdvertiseAddress(s.SecureServing.SecureBindPort); err != nil {
        return options, err
    }
    
    // 设置默认的ServiceClusterIPRange
    if err := s.ServiceClusterIPRanges.Default("10.0.0.0/24"); err != nil {
        return options, err
    }
    
    // 设置默认的ServiceNodePortRange
    s.ServiceNodePortRange = options.DefaultServiceNodePortRange()
    
    // 补全Etcd配置
    if err := s.Etcd.Complete(storagebackend.Config{}, nil); err != nil {
        return options, err
    }
    
    // 补全认证配置
    if err := s.Authentication.Complete(); err != nil {
        return options, err
    }
    
    // ... 还有很多其他配置
    
    return options, nil
}

Common配置项

配置项说明默认值
--advertise-address对外公告的地址自动检测
--secure-portHTTPS监听端口6443
--etcd-serversetcd集群地址无(必须指定)
--service-cluster-ip-rangeService VIP网段10.0.0.0/24
--service-node-port-rangeNodePort范围30000-32767

5. Validate:参数校验

Validate函数对配置进行全面的合法性校验:

func (s *ServerRunOptions) Validate() []error {
    var errs []error
    
    // 校验MasterCount
    if s.MasterCount <= 0 {
        errs = append(errs, fmt.Errorf("--apiserver-count should be positive"))
    }
    
    // 校验Etcd配置
    errs = append(errs, s.Etcd.Validate()...)
    
    // 校验ClusterIP配置
    errs = append(errs, validateClusterIPFlags(s)...)
    
    // 校验NodePort范围
    errs = append(errs, validateServiceNodePort(s)...)
    
    // 校验API优先级和公平性
    errs = append(errs, validateAPIPriorityAndFairness(s)...)
    
    // 校验安全配置
    errs = append(errs, s.SecureServing.Validate()...)
    
    // 校验认证配置
    errs = append(errs, s.Authentication.Validate()...)
    
    // 校验鉴权配置
    errs = append(errs, s.Authorization.Validate()...)
    
    // 校验审计配置
    errs = append(errs, s.Audit.Validate()...)
    
    // 校验准入控制配置
    errs = append(errs, s.Admission.Validate()...)
    
    // 校验API启用配置
    errs = append(errs, s.APIEnablement.Validate(...)...)
    
    // ... 更多校验
    
    return errs
}

校验示例:etcd配置校验

func (s *EtcdOptions) Validate() []error {
    var allErrors []error
    
    // 必须指定etcd地址
    if len(s.StorageConfig.Transport.ServerList) == 0 {
        allErrors = append(allErrors, fmt.Errorf("--etcd-servers must be specified"))
    }
    
    // 校验存储后端类型
    if s.StorageConfig.Type != storagebackend.StorageTypeUnset && 
       !storageTypes.Has(s.StorageConfig.Type) {
        allErrors = append(allErrors, fmt.Errorf("--storage-backend invalid"))
    }
    
    // 校验etcd-servers-overrides格式
    for _, override := range s.EtcdServersOverrides {
        tokens := strings.Split(override, "#")
        if len(tokens) != 2 {
            allErrors = append(allErrors, fmt.Errorf("--etcd-servers-overrides invalid"))
            continue
        }
        // ... 更多校验
    }
    
    return allErrors
}

第三阶段:核心启动流程

Run函数:启动的入口

func Run(completeOptions completedServerRunOptions, stopCh <-chan struct{}) error {
    // 打印版本信息
    klog.Infof("Version: %+v", version.Get())
    
    // 创建Server链(核心!)
    server, err := CreateServerChain(completeOptions, stopCh)
    if err != nil {
        return err
    }
    
    // 准备运行
    prepared, err := server.PrepareRun()
    if err != nil {
        return err
    }
    
    // 运行(阻塞)
    return prepared.Run(stopCh)
}

StopCh:优雅关闭机制

stopCh用于接收系统信号,实现优雅关闭:

// 创建信号处理器
stopCh := genericapiserver.SetupSignalHandler()

// SetupSignalHandler的实现
func SetupSignalHandler() <-chan struct{} {
    return SetupSignalContext().Done()
}

func SetupSignalContext() context.Context {
    close(onlyOneSignalHandler) // 确保只调用一次
    
    shutdownHandler = make(chan os.Signal, 2)
    
    ctx, cancel := context.WithCancel(context.Background())
    
    // 监听SIGTERM和SIGINT信号
    signal.Notify(shutdownHandler, shutdownSignals...)
    
    go func() {
        // 第一次收到信号,取消context
        <-shutdownHandler
        cancel()
        
        // 第二次收到信号,直接退出
        <-shutdownHandler
        os.Exit(1)
    }()
    
    return ctx
}

优雅关闭流程

  1. 收到SIGTERM信号(如kubectl delete pod)
  2. 取消context,触发stopCh关闭
  3. HTTP服务器开始优雅关闭(停止接受新连接)
  4. 等待现有请求处理完成
  5. 清理资源,退出进程

第四阶段:创建Server链(核心!)

这是kube-apiserver启动最核心的部分——创建3个Server组成服务链

func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan struct{}) (*aggregatorapiserver.APIAggregator, error) {
    // 1. 创建KubeAPIServer(核心API)
    kubeAPIServerConfig, insecureServingInfo, serviceResolver, pluginInitializer, err := 
        CreateKubeAPIServerConfig(completedOptions)
    
    kubeAPIServer, err := CreateKubeAPIServer(
        kubeAPIServerConfig, 
        apiExtensionsConfig.GenericConfig,
        completedOptions.APIEnablement.AggregateAPILogger,
    )
    
    // 2. 创建APIExtensionsServer(CRD扩展)
    apiExtensionsConfig, err := createAPIExtensionsConfig(...)
    apiExtensionsServer, err := createAPIExtensionsServer(
        apiExtensionsConfig,
        kubeAPIServer.GenericAPIServer,
    )
    
    // 3. 创建AggregatorServer(API聚合层)
    aggregatorConfig, err := createAggregatorConfig(...)
    aggregatorServer, err := createAggregatorServer(
        aggregatorConfig,
        kubeAPIServer.GenericAPIServer,
        apiExtensionsServer.Informers,
    )
    
    return aggregatorServer, nil
}

3个Server的职责

请求路径
    │
    ▼
┌─────────────────────────────────────────────────────────────┐
│                   AggregatorServer                          │
│  ├─ 路由/metrics → metrics-server                           │
│  ├─ 路由/custom.metrics.k8s.io → custom-metrics-server      │
│  └─ 其他请求 → 转发到下一层                                  │
└──────────────────┬──────────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────────────────────┐
│                APIExtensionsServer                          │
│  ├─ 路由/apis/apiextensions.k8s.io → 处理CRD                │
│  └─ 其他请求 → 转发到下一层                                  │
└──────────────────┬──────────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────────────────────┐
│                   KubeAPIServer                             │
│  ├─ 路由/api/v1 → 核心API(Pod/Service/Node等)             │
│  ├─ 路由/apis/apps/v1 → 应用API(Deployment/DaemonSet等)   │
│  └─ 其他请求 → 返回404                                      │
└─────────────────────────────────────────────────────────────┘

1. KubeAPIServer:核心API服务

KubeAPIServer是K8s最核心的API服务,提供原生资源的管理能力:

func CreateKubeAPIServerConfig(opts completedServerRunOptions) (*master.Config, ...) {
    // 创建GenericConfig(通用配置)
    genericConfig := genericapiserver.NewConfig(legacyscheme.Codecs)
    
    // 设置认证、鉴权、审计等配置
    genericConfig.Authentication = opts.Authentication.ToAuthenticationConfig()
    genericConfig.Authorization = opts.Authorization.ToAuthorizationConfig()
    genericConfig.AuditBackend = opts.Audit.NewBackend()
    
    // 设置存储配置(etcd)
    storageFactory, err := opts.Etcd.CreateStorageFactory()
    
    // 创建Master配置
    config := &master.Config{
        GenericConfig: genericConfig,
        ExtraConfig: master.ExtraConfig{
            StorageFactory:          storageFactory,
            APIResourceConfigSource: opts.APIEnablement,
            // ... 其他配置
        },
    }
    
    return config, nil
}

KubeAPIServer提供的API

路径说明示例资源
/api/v1核心APIPod、Service、Node、Namespace
/apis/apps/v1应用APIDeployment、StatefulSet、DaemonSet
/apis/networking.k8s.io/v1网络APIIngress、NetworkPolicy
/apis/rbac.authorization.k8s.io/v1RBAC APIRole、RoleBinding、ClusterRole

2. APIExtensionsServer:CRD扩展服务

APIExtensionsServer提供CustomResourceDefinition(自定义资源定义)的能力:

func createAPIExtensionsServer(
    apiExtensionsConfig *apiextensionsapiserver.Config,
    delegateAPIServer genericapiserver.DelegationTarget,
) (*apiextensionsapiserver.CustomResourceDefinitions, error) {
    
    // 创建APIExtensions服务器
    server, err := apiExtensionsConfig.Complete().New(delegateAPIServer)
    if err != nil {
        return nil, err
    }
    
    return server, nil
}

CRD的作用

  • 允许用户自定义K8s资源类型
  • 不需要修改apiserver代码就能扩展API
  • Operator的基础

3. AggregatorServer:API聚合层

AggregatorServer是K8s API聚合层的实现,允许将第三方API服务注册到K8s API中:

func createAggregatorServer(
    aggregatorConfig *aggregatorapiserver.Config,
    delegateAPIServer genericapiserver.DelegationTarget,
    apiExtensionInformers apiextensioninformers.SharedInformerFactory,
) (*aggregatorapiserver.APIAggregator, error) {
    
    // 创建Aggregator服务器
    aggregatorServer, err := aggregatorConfig.Complete().NewWithDelegate(delegateAPIServer)
    if err != nil {
        return nil, err
    }
    
    return aggregatorServer, nil
}

Aggregator的应用场景

服务说明API路径
metrics-server资源指标(CPU/内存)/apis/metrics.k8s.io
custom-metrics-server自定义指标(业务指标)/apis/custom.metrics.k8s.io
external-metrics-server外部指标(云服务指标)/apis/external.metrics.k8s.io
service-catalog服务目录/apis/servicecatalog.k8s.io

第五阶段:准备与运行

PrepareRun:启动前的最后准备

func (s *APIAggregator) PrepareRun() (preparedAPIAggregator, error) {
    // 准备GenericAPIServer
    genericPrepared, err := s.GenericAPIServer.PrepareRun()
    if err != nil {
        return preparedAPIAggregator{}, err
    }
    
    // 注册控制器
    // ...
    
    return preparedAPIAggregator{
        APIAggregator:       s,
        GenericAPIServer:    genericPrepared,
    }, nil
}

Run:启动HTTP服务

func (s preparedAPIAggregator) Run(stopCh <-chan struct{}) error {
    // 启动GenericAPIServer(阻塞)
    return s.GenericAPIServer.Run(stopCh)
}

// GenericAPIServer.Run
func (s *GenericAPIServer) Run(stopCh <-chan struct{}) error {
    // 启动HTTP/HTTPS服务
    // ...
    
    // 阻塞等待stopCh
    <-stopCh
    
    // 优雅关闭
    return nil
}

启动流程总结

┌────────────────────────────────────────────────────────────────┐
│                      kube-apiserver启动流程                     │
├────────────────────────────────────────────────────────────────┤
│  Phase 1: 程序入口                                               │
│  ├─ main()                                                     │
│  ├─ NewAPIServerCommand() 创建Cobra命令                         │
│  └─ Execute() 执行                                              │
├────────────────────────────────────────────────────────────────┤
│  Phase 2: 参数处理                                               │
│  ├─ PersistentPreRunE() 设置WarningHandler                      │
│  ├─ PrintFlags() 打印启动参数                                    │
│  ├─ checkNonZeroInsecurePort() 检查不安全端口                    │
│  ├─ Complete() 补全配置默认值                                    │
│  └─ Validate() 校验参数合法性                                    │
├────────────────────────────────────────────────────────────────┤
│  Phase 3: Server链创建(核心)                                   │
│  ├─ CreateKubeAPIServerConfig() 创建核心API配置                   │
│  ├─ CreateKubeAPIServer() 创建核心API服务器                       │
│  ├─ createAPIExtensionsServer() 创建CRD扩展服务器                 │
│  └─ createAggregatorServer() 创建聚合层服务器                     │
├────────────────────────────────────────────────────────────────┤
│  Phase 4: 启动服务                                               │
│  ├─ PrepareRun() 准备运行                                        │
│  ├─ Run() 启动HTTP服务                                           │
│  └─ <-stopCh 阻塞等待关闭信号                                     │
└────────────────────────────────────────────────────────────────┘

踩坑实录:apiserver启动常见问题

坑1:etcd连接失败

现象:apiserver启动报错,--etcd-servers must be specified或连接超时

根因

  • 没有指定etcd地址
  • etcd证书配置错误
  • 网络不通

解决方案

# 检查etcd是否运行
etcdctl endpoint health --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/etcd/ca.crt \
  --cert=/etc/etcd/etcd.crt \
  --key=/etc/etcd/etcd.key

# 检查apiserver启动参数
kube-apiserver \
  --etcd-servers=https://192.168.1.100:2379,https://192.168.1.101:2379 \
  --etcd-cafile=/etc/etcd/ca.crt \
  --etcd-certfile=/etc/etcd/apiserver-etcd-client.crt \
  --etcd-keyfile=/etc/etcd/apiserver-etcd-client.key

坑2:端口冲突

现象:报错bind: address already in use

根因:6443端口被其他进程占用

解决方案

# 查找占用端口的进程
sudo lsof -i :6443

# 或者使用netstat
sudo netstat -tlnp | grep 6443

# 修改apiserver监听端口(不推荐,最好释放端口)
kube-apiserver --secure-port=6444

坑3:证书问题

现象:TLS握手失败,证书验证错误

根因

  • 证书过期
  • 证书CN/SAN不匹配
  • 证书链不完整

解决方案

# 检查证书有效期
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates

# 检查证书SAN
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep -A5 "Subject Alternative Name"

坑4:Aggregator初始化卡住

现象:apiserver日志显示aggregator相关错误,服务无法就绪

根因:AggregatorServer初始化时需要连接metrics-server,如果metrics-server不可用会卡住

解决方案

# 检查metrics-server状态
kubectl get pods -n kube-system | grep metrics-server

# 暂时禁用Aggregator(开发测试环境)
kube-apiserver --enable-aggregator-routing=false

坑5:内存/CPU不足

现象:apiserver启动后OOM或被系统kill

根因:资源限制太小,etcd数据量大

解决方案

# 如果是容器化部署,增加资源限制
resources:
  limits:
    cpu: "2000m"
    memory: "2Gi"
  requests:
    cpu: "500m"
    memory: "512Mi"

调试技巧:如何跟踪启动流程

1. 使用-v参数查看详细日志

# -v=0: 默认
# -v=2: 重要信息
# -v=4: 详细信息
# -v=6: HTTP请求详情
# -v=8: 完整HTTP内容

kube-apiserver -v=6

2. 查看启动参数

# 查看apiserver进程启动参数
ps aux | grep kube-apiserver

# 或者查看静态Pod配置
cat /etc/kubernetes/manifests/kube-apiserver.yaml

3. 使用pprof分析启动性能

# 启用pprof
kube-apiserver --profiling=true

# 采集CPU profile
curl http://localhost:8080/debug/pprof/profile > cpu.pprof

下一步学习路线

理解了apiserver启动流程后,建议按以下路线继续深入学习:

  1. HTTP服务启动:GenericAPIServer如何启动HTTP/HTTPS服务
  2. 认证鉴权链:请求如何经过认证→鉴权→准入控制
  3. RESTful路由:请求如何路由到对应的handler
  4. etcd存储:资源如何序列化并存储到etcd
  5. watch机制:如何实现资源变化的长连接通知

总结

通过本篇源码分析,我们完整了解了kube-apiserver的启动流程:

  1. 程序入口:main → NewAPIServerCommand → Execute
  2. 参数处理:PrintFlags → Complete → Validate
  3. Server链创建:KubeAPIServer → APIExtensionsServer → AggregatorServer
  4. 服务启动:PrepareRun → Run → 阻塞等待

核心设计:

  • 使用Cobra框架处理命令行
  • 三阶段模式(Complete→Validate→Run)
  • 三层Server架构(核心→扩展→聚合)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加倍巴巴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值