【controller-runtime】controller-runtime v0.24.1 超深度架构总览之一

controller-runtime v0.24.1 超深度架构总览

一、项目定位

1.1 业务职责

controller-runtime 是 Kubernetes SIG 维护的Operator开发底层框架 ,为kubebuilder和Operator SDK提供运行时基础设施。它封装了controller的核心组件:Manager、Controller、Cache、Client、Webhook、Source、Handler、Predicate等,让开发者只需实现Reconcile方法即可构建完整的Operator。

核心职责:

  1. Manager:管理所有组件的生命周期、依赖注入、Leader选举
  2. Controller:Reconcile循环、WorkQueue、事件分发
  3. Cache:Informer缓存、本地读加速、Field索引
  4. Client:统一的K8s API读写客户端(读走Cache,写走直连)
  5. Webhook:Mutating/Validating/Conversion/Authentication四种Webhook
  6. Source/Handler/Predicate:事件源、事件处理、事件过滤三件套
  7. Builder:流式API构建Controller和Webhook
  8. envtest:本地集成测试环境(etcd + API Server)

1.2 在Kubernetes生态中的位置

#mermaid-svg-27C58H7see4eOEo6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-27C58H7see4eOEo6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-27C58H7see4eOEo6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-27C58H7see4eOEo6 .error-icon{fill:#552222;}#mermaid-svg-27C58H7see4eOEo6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-27C58H7see4eOEo6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-27C58H7see4eOEo6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-27C58H7see4eOEo6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-27C58H7see4eOEo6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-27C58H7see4eOEo6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-27C58H7see4eOEo6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-27C58H7see4eOEo6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-27C58H7see4eOEo6 .marker.cross{stroke:#333333;}#mermaid-svg-27C58H7see4eOEo6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-27C58H7see4eOEo6 p{margin:0;}#mermaid-svg-27C58H7see4eOEo6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-27C58H7see4eOEo6 .cluster-label text{fill:#333;}#mermaid-svg-27C58H7see4eOEo6 .cluster-label span{color:#333;}#mermaid-svg-27C58H7see4eOEo6 .cluster-label span p{background-color:transparent;}#mermaid-svg-27C58H7see4eOEo6 .label text,#mermaid-svg-27C58H7see4eOEo6 span{fill:#333;color:#333;}#mermaid-svg-27C58H7see4eOEo6 .node rect,#mermaid-svg-27C58H7see4eOEo6 .node circle,#mermaid-svg-27C58H7see4eOEo6 .node ellipse,#mermaid-svg-27C58H7see4eOEo6 .node polygon,#mermaid-svg-27C58H7see4eOEo6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-27C58H7see4eOEo6 .rough-node .label text,#mermaid-svg-27C58H7see4eOEo6 .node .label text,#mermaid-svg-27C58H7see4eOEo6 .image-shape .label,#mermaid-svg-27C58H7see4eOEo6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-27C58H7see4eOEo6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-27C58H7see4eOEo6 .rough-node .label,#mermaid-svg-27C58H7see4eOEo6 .node .label,#mermaid-svg-27C58H7see4eOEo6 .image-shape .label,#mermaid-svg-27C58H7see4eOEo6 .icon-shape .label{text-align:center;}#mermaid-svg-27C58H7see4eOEo6 .node.clickable{cursor:pointer;}#mermaid-svg-27C58H7see4eOEo6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-27C58H7see4eOEo6 .arrowheadPath{fill:#333333;}#mermaid-svg-27C58H7see4eOEo6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-27C58H7see4eOEo6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-27C58H7see4eOEo6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-27C58H7see4eOEo6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-27C58H7see4eOEo6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-27C58H7see4eOEo6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-27C58H7see4eOEo6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-27C58H7see4eOEo6 .cluster text{fill:#333;}#mermaid-svg-27C58H7see4eOEo6 .cluster span{color:#333;}#mermaid-svg-27C58H7see4eOEo6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-27C58H7see4eOEo6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-27C58H7see4eOEo6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-27C58H7see4eOEo6 .icon-shape,#mermaid-svg-27C58H7see4eOEo6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-27C58H7see4eOEo6 .icon-shape p,#mermaid-svg-27C58H7see4eOEo6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-27C58H7see4eOEo6 .icon-shape .label rect,#mermaid-svg-27C58H7see4eOEo6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-27C58H7see4eOEo6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-27C58H7see4eOEo6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-27C58H7see4eOEo6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} client-go (K8s底层)
controller-runtime (运行时)
kubebuilder (脚手架)
用户Operator
实现Reconcile
生成代码引用
MyOperator

Reconcile()
kubebuilder CLI

项目生成

CRD生成

RBAC生成
Manager
Controller
Cache
Client
Webhook
Builder
Source
Handler
Predicate
PriorityQueue
envtest
Informer
Lister
Watcher
WorkQueue
RESTClient
controller_runtime

1.3 代码规模

核心文件数 总行数(估) 核心内容
manager/ 5 ~2,400 Manager、RunnableGroup、Server
internal/controller/ 1 565 Controller核心(Reconcile循环)
controller/ 4 ~1,800 Controller外层、PriorityQueue、controllerutil
cache/ 6 ~2,700 Cache、InformerCache、MultiNamespace
client/ 14 ~4,400 Client接口、TypedClient、Patch、Watch
builder/ 3 ~980 Controller/Webhook Builder
source/ 1 316 Kind事件源
handler/ 4 ~730 EventHandler、Enqueue、EnqueueOwner
predicate/ 1 429 过滤条件
webhook/ 6 ~1,400 Server、Admission、Conversion
reconcile/ 1 197 Reconcile接口定义
cluster/ 2 ~420 Cluster抽象
envtest/ 5 ~1,800 测试环境
metrics/ 5 ~600 指标、Server
合计 ~50+ ~20,000 (不含test/fake/internal/testing)

二、核心架构全景

2.1 组件依赖关系

#mermaid-svg-aI8uorfb9tjyfcQn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aI8uorfb9tjyfcQn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aI8uorfb9tjyfcQn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aI8uorfb9tjyfcQn .error-icon{fill:#552222;}#mermaid-svg-aI8uorfb9tjyfcQn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aI8uorfb9tjyfcQn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aI8uorfb9tjyfcQn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aI8uorfb9tjyfcQn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aI8uorfb9tjyfcQn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aI8uorfb9tjyfcQn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aI8uorfb9tjyfcQn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aI8uorfb9tjyfcQn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aI8uorfb9tjyfcQn .marker.cross{stroke:#333333;}#mermaid-svg-aI8uorfb9tjyfcQn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aI8uorfb9tjyfcQn p{margin:0;}#mermaid-svg-aI8uorfb9tjyfcQn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-aI8uorfb9tjyfcQn .cluster-label text{fill:#333;}#mermaid-svg-aI8uorfb9tjyfcQn .cluster-label span{color:#333;}#mermaid-svg-aI8uorfb9tjyfcQn .cluster-label span p{background-color:transparent;}#mermaid-svg-aI8uorfb9tjyfcQn .label text,#mermaid-svg-aI8uorfb9tjyfcQn span{fill:#333;color:#333;}#mermaid-svg-aI8uorfb9tjyfcQn .node rect,#mermaid-svg-aI8uorfb9tjyfcQn .node circle,#mermaid-svg-aI8uorfb9tjyfcQn .node ellipse,#mermaid-svg-aI8uorfb9tjyfcQn .node polygon,#mermaid-svg-aI8uorfb9tjyfcQn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aI8uorfb9tjyfcQn .rough-node .label text,#mermaid-svg-aI8uorfb9tjyfcQn .node .label text,#mermaid-svg-aI8uorfb9tjyfcQn .image-shape .label,#mermaid-svg-aI8uorfb9tjyfcQn .icon-shape .label{text-anchor:middle;}#mermaid-svg-aI8uorfb9tjyfcQn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aI8uorfb9tjyfcQn .rough-node .label,#mermaid-svg-aI8uorfb9tjyfcQn .node .label,#mermaid-svg-aI8uorfb9tjyfcQn .image-shape .label,#mermaid-svg-aI8uorfb9tjyfcQn .icon-shape .label{text-align:center;}#mermaid-svg-aI8uorfb9tjyfcQn .node.clickable{cursor:pointer;}#mermaid-svg-aI8uorfb9tjyfcQn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aI8uorfb9tjyfcQn .arrowheadPath{fill:#333333;}#mermaid-svg-aI8uorfb9tjyfcQn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aI8uorfb9tjyfcQn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aI8uorfb9tjyfcQn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aI8uorfb9tjyfcQn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aI8uorfb9tjyfcQn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aI8uorfb9tjyfcQn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aI8uorfb9tjyfcQn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aI8uorfb9tjyfcQn .cluster text{fill:#333;}#mermaid-svg-aI8uorfb9tjyfcQn .cluster span{color:#333;}#mermaid-svg-aI8uorfb9tjyfcQn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aI8uorfb9tjyfcQn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aI8uorfb9tjyfcQn rect.text{fill:none;stroke-width:0;}#mermaid-svg-aI8uorfb9tjyfcQn .icon-shape,#mermaid-svg-aI8uorfb9tjyfcQn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aI8uorfb9tjyfcQn .icon-shape p,#mermaid-svg-aI8uorfb9tjyfcQn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aI8uorfb9tjyfcQn .icon-shape .label rect,#mermaid-svg-aI8uorfb9tjyfcQn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aI8uorfb9tjyfcQn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aI8uorfb9tjyfcQn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aI8uorfb9tjyfcQn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Manager

管理者一切
Cluster

集群连接
Runnables

6组Runnable
Leader Election

选举
Metrics Server
Health Probe
Webhook Server
Cache
Client
RESTMapper
Scheme
EventRecorder
HTTPServers组

Metrics/Health/Pprof
Webhooks组
Caches组
LeaderElection组

Controller/其他
Warmup组
Others组

非Leader选举Runnable
InformerManager

每个GVK一个Informer
SharedInformerFactory
DelegatingClient

读→Cache 写→直连
CacheReader
DirectClient
Controller
PriorityQueue
Source(Kind)
Handler(Enqueue)
Predicate
Reconciler

(用户实现)

2.2 数据流全景

#mermaid-svg-SKNFXMqhpabkUFVb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SKNFXMqhpabkUFVb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SKNFXMqhpabkUFVb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SKNFXMqhpabkUFVb .error-icon{fill:#552222;}#mermaid-svg-SKNFXMqhpabkUFVb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SKNFXMqhpabkUFVb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SKNFXMqhpabkUFVb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SKNFXMqhpabkUFVb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SKNFXMqhpabkUFVb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SKNFXMqhpabkUFVb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SKNFXMqhpabkUFVb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SKNFXMqhpabkUFVb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SKNFXMqhpabkUFVb .marker.cross{stroke:#333333;}#mermaid-svg-SKNFXMqhpabkUFVb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SKNFXMqhpabkUFVb p{margin:0;}#mermaid-svg-SKNFXMqhpabkUFVb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SKNFXMqhpabkUFVb .cluster-label text{fill:#333;}#mermaid-svg-SKNFXMqhpabkUFVb .cluster-label span{color:#333;}#mermaid-svg-SKNFXMqhpabkUFVb .cluster-label span p{background-color:transparent;}#mermaid-svg-SKNFXMqhpabkUFVb .label text,#mermaid-svg-SKNFXMqhpabkUFVb span{fill:#333;color:#333;}#mermaid-svg-SKNFXMqhpabkUFVb .node rect,#mermaid-svg-SKNFXMqhpabkUFVb .node circle,#mermaid-svg-SKNFXMqhpabkUFVb .node ellipse,#mermaid-svg-SKNFXMqhpabkUFVb .node polygon,#mermaid-svg-SKNFXMqhpabkUFVb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SKNFXMqhpabkUFVb .rough-node .label text,#mermaid-svg-SKNFXMqhpabkUFVb .node .label text,#mermaid-svg-SKNFXMqhpabkUFVb .image-shape .label,#mermaid-svg-SKNFXMqhpabkUFVb .icon-shape .label{text-anchor:middle;}#mermaid-svg-SKNFXMqhpabkUFVb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SKNFXMqhpabkUFVb .rough-node .label,#mermaid-svg-SKNFXMqhpabkUFVb .node .label,#mermaid-svg-SKNFXMqhpabkUFVb .image-shape .label,#mermaid-svg-SKNFXMqhpabkUFVb .icon-shape .label{text-align:center;}#mermaid-svg-SKNFXMqhpabkUFVb .node.clickable{cursor:pointer;}#mermaid-svg-SKNFXMqhpabkUFVb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SKNFXMqhpabkUFVb .arrowheadPath{fill:#333333;}#mermaid-svg-SKNFXMqhpabkUFVb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SKNFXMqhpabkUFVb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SKNFXMqhpabkUFVb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SKNFXMqhpabkUFVb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SKNFXMqhpabkUFVb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SKNFXMqhpabkUFVb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SKNFXMqhpabkUFVb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SKNFXMqhpabkUFVb .cluster text{fill:#333;}#mermaid-svg-SKNFXMqhpabkUFVb .cluster span{color:#333;}#mermaid-svg-SKNFXMqhpabkUFVb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SKNFXMqhpabkUFVb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SKNFXMqhpabkUFVb rect.text{fill:none;stroke-width:0;}#mermaid-svg-SKNFXMqhpabkUFVb .icon-shape,#mermaid-svg-SKNFXMqhpabkUFVb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SKNFXMqhpabkUFVb .icon-shape p,#mermaid-svg-SKNFXMqhpabkUFVb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SKNFXMqhpabkUFVb .icon-shape .label rect,#mermaid-svg-SKNFXMqhpabkUFVb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SKNFXMqhpabkUFVb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SKNFXMqhpabkUFVb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SKNFXMqhpabkUFVb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Watch事件
缓存对象
OnChange事件
Predicate过滤
Yes
No
取出Item
调用
读Cache
写API
返回Result
nil error + no requeue
error
RequeueAfter=N
Requeue=true
API Server
Informer

(client-go)
ThreadSafeStore
EventHandler

(Enqueue)
Predicate

通过?
入队

namespace/name
丢弃事件
PriorityQueue

(去重+限流)
Worker Goroutine
Reconcile(ctx, req)
Cache.Get/List
Client.Create/Update/Delete/Patch
Result?
Forget

不再重新入队
AddRateLimited

指数退避重试
AddAfter(N)

延迟N秒重试
AddRateLimited

2.3 Manager启动顺序

Controllers LeaderElection Warmup Others Caches Webhooks HTTPServers Manager main() Controllers LeaderElection Warmup Others Caches Webhooks HTTPServers Manager main() #mermaid-svg-lMetazEsEUt8AbIy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lMetazEsEUt8AbIy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lMetazEsEUt8AbIy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lMetazEsEUt8AbIy .error-icon{fill:#552222;}#mermaid-svg-lMetazEsEUt8AbIy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lMetazEsEUt8AbIy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lMetazEsEUt8AbIy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lMetazEsEUt8AbIy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lMetazEsEUt8AbIy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lMetazEsEUt8AbIy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lMetazEsEUt8AbIy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lMetazEsEUt8AbIy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lMetazEsEUt8AbIy .marker.cross{stroke:#333333;}#mermaid-svg-lMetazEsEUt8AbIy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lMetazEsEUt8AbIy p{margin:0;}#mermaid-svg-lMetazEsEUt8AbIy .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-lMetazEsEUt8AbIy text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-lMetazEsEUt8AbIy .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-lMetazEsEUt8AbIy .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-lMetazEsEUt8AbIy .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-lMetazEsEUt8AbIy .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-lMetazEsEUt8AbIy #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-lMetazEsEUt8AbIy .sequenceNumber{fill:white;}#mermaid-svg-lMetazEsEUt8AbIy #sequencenumber{fill:#333;}#mermaid-svg-lMetazEsEUt8AbIy #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-lMetazEsEUt8AbIy .messageText{fill:#333;stroke:none;}#mermaid-svg-lMetazEsEUt8AbIy .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-lMetazEsEUt8AbIy .labelText,#mermaid-svg-lMetazEsEUt8AbIy .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-lMetazEsEUt8AbIy .loopText,#mermaid-svg-lMetazEsEUt8AbIy .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-lMetazEsEUt8AbIy .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-lMetazEsEUt8AbIy .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-lMetazEsEUt8AbIy .noteText,#mermaid-svg-lMetazEsEUt8AbIy .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-lMetazEsEUt8AbIy .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-lMetazEsEUt8AbIy .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-lMetazEsEUt8AbIy .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-lMetazEsEUt8AbIy .actorPopupMenu{position:absolute;}#mermaid-svg-lMetazEsEUt8AbIy .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-lMetazEsEUt8AbIy .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-lMetazEsEUt8AbIy .actor-man circle,#mermaid-svg-lMetazEsEUt8AbIy line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-lMetazEsEUt8AbIy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. 初始化internal context 2. 初始化Leader Elector 3. 添加Cluster到Runnables 4. 启动HTTP服务器(必须最先!) Metrics/Health/Pprof 5. 启动Webhook(必须在Cache之前!) Conversion/Mutating/Validating 6. 启动Cache并等待同步 启动所有InformerWaitForCacheSync 7. 启动非Leader选举Runnable 8. 启动Warmup Runnable 9. 启动Leader选举 启动所有Controller alt启用了Leader选举未启用Leader选举 10. 阻塞等待 mgr.Start(ctx)internalCtx, internalCancel = context.WithCancel(ctx)initLeaderElector()Add(cluster)HTTPServers.Start()就绪Webhooks.Start()就绪Caches.Start()Cache同步完成Others.Start()Warmup.Start()leaderElector.Run()竞争LeaseOnStartedLeadingLeaderElection.Start()立即启动所有Controllerselect { case <-ctx.Done() | case <-errChan }

启动顺序的关键原因

  1. HTTP先于Cache:Health Probe必须先启动,否则Conversion Webhook阻塞Cache同步
  2. Webhook先于Cache:Cache同步时可能触发Conversion Webhook,如果Webhook未就绪会死锁
  3. Cache先于Controller:Controller的Reconcile依赖Cache数据
  4. Leader选举最后:只有当选Leader后才启动Controller

2.4 Manager关闭顺序

HTTPServers Webhooks Caches LeaderElection Others Warmup Manager Context HTTPServers Webhooks Caches LeaderElection Others Warmup Manager Context #mermaid-svg-EYJiXZBzN8llmvdF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EYJiXZBzN8llmvdF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EYJiXZBzN8llmvdF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EYJiXZBzN8llmvdF .error-icon{fill:#552222;}#mermaid-svg-EYJiXZBzN8llmvdF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EYJiXZBzN8llmvdF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EYJiXZBzN8llmvdF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EYJiXZBzN8llmvdF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EYJiXZBzN8llmvdF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EYJiXZBzN8llmvdF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EYJiXZBzN8llmvdF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EYJiXZBzN8llmvdF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EYJiXZBzN8llmvdF .marker.cross{stroke:#333333;}#mermaid-svg-EYJiXZBzN8llmvdF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EYJiXZBzN8llmvdF p{margin:0;}#mermaid-svg-EYJiXZBzN8llmvdF .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EYJiXZBzN8llmvdF text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-EYJiXZBzN8llmvdF .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-EYJiXZBzN8llmvdF .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-EYJiXZBzN8llmvdF .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-EYJiXZBzN8llmvdF .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-EYJiXZBzN8llmvdF #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-EYJiXZBzN8llmvdF .sequenceNumber{fill:white;}#mermaid-svg-EYJiXZBzN8llmvdF #sequencenumber{fill:#333;}#mermaid-svg-EYJiXZBzN8llmvdF #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-EYJiXZBzN8llmvdF .messageText{fill:#333;stroke:none;}#mermaid-svg-EYJiXZBzN8llmvdF .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EYJiXZBzN8llmvdF .labelText,#mermaid-svg-EYJiXZBzN8llmvdF .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-EYJiXZBzN8llmvdF .loopText,#mermaid-svg-EYJiXZBzN8llmvdF .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-EYJiXZBzN8llmvdF .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-EYJiXZBzN8llmvdF .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-EYJiXZBzN8llmvdF .noteText,#mermaid-svg-EYJiXZBzN8llmvdF .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-EYJiXZBzN8llmvdF .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EYJiXZBzN8llmvdF .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EYJiXZBzN8llmvdF .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-EYJiXZBzN8llmvdF .actorPopupMenu{position:absolute;}#mermaid-svg-EYJiXZBzN8llmvdF .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-EYJiXZBzN8llmvdF .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-EYJiXZBzN8llmvdF .actor-man circle,#mermaid-svg-EYJiXZBzN8llmvdF line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-EYJiXZBzN8llmvdF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} gracefulShutdownTimeout倒计时 先停非Leader Runnable 停止所有Controller 停Cache(防止新事件入队) Webhook和HTTP最后停 取消Leader选举 ctx.Done()StopAndWait()StopAndWait()StopAndWait()StopAndWait()StopAndWait()StopAndWait()leaderElectionCancel()


三、核心概念详解

3.1 Manager

Manager是controller-runtime的根对象,管理所有共享依赖和组件生命周期。
#mermaid-svg-LOJCrBHrutPvceZN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LOJCrBHrutPvceZN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LOJCrBHrutPvceZN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LOJCrBHrutPvceZN .error-icon{fill:#552222;}#mermaid-svg-LOJCrBHrutPvceZN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LOJCrBHrutPvceZN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LOJCrBHrutPvceZN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LOJCrBHrutPvceZN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LOJCrBHrutPvceZN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LOJCrBHrutPvceZN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LOJCrBHrutPvceZN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LOJCrBHrutPvceZN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LOJCrBHrutPvceZN .marker.cross{stroke:#333333;}#mermaid-svg-LOJCrBHrutPvceZN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LOJCrBHrutPvceZN p{margin:0;}#mermaid-svg-LOJCrBHrutPvceZN g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-LOJCrBHrutPvceZN g.classGroup text .title{font-weight:bolder;}#mermaid-svg-LOJCrBHrutPvceZN .cluster-label text{fill:#333;}#mermaid-svg-LOJCrBHrutPvceZN .cluster-label span{color:#333;}#mermaid-svg-LOJCrBHrutPvceZN .cluster-label span p{background-color:transparent;}#mermaid-svg-LOJCrBHrutPvceZN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LOJCrBHrutPvceZN .cluster text{fill:#333;}#mermaid-svg-LOJCrBHrutPvceZN .cluster span{color:#333;}#mermaid-svg-LOJCrBHrutPvceZN .nodeLabel,#mermaid-svg-LOJCrBHrutPvceZN .edgeLabel{color:#131300;}#mermaid-svg-LOJCrBHrutPvceZN .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-LOJCrBHrutPvceZN .label text{fill:#131300;}#mermaid-svg-LOJCrBHrutPvceZN .labelBkg{background:#ECECFF;}#mermaid-svg-LOJCrBHrutPvceZN .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-LOJCrBHrutPvceZN .classTitle{font-weight:bolder;}#mermaid-svg-LOJCrBHrutPvceZN .node rect,#mermaid-svg-LOJCrBHrutPvceZN .node circle,#mermaid-svg-LOJCrBHrutPvceZN .node ellipse,#mermaid-svg-LOJCrBHrutPvceZN .node polygon,#mermaid-svg-LOJCrBHrutPvceZN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LOJCrBHrutPvceZN .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN g.clickable{cursor:pointer;}#mermaid-svg-LOJCrBHrutPvceZN g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-LOJCrBHrutPvceZN g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-LOJCrBHrutPvceZN .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-LOJCrBHrutPvceZN .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-LOJCrBHrutPvceZN .dashed-line{stroke-dasharray:3;}#mermaid-svg-LOJCrBHrutPvceZN .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-LOJCrBHrutPvceZN #compositionStart,#mermaid-svg-LOJCrBHrutPvceZN .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #compositionEnd,#mermaid-svg-LOJCrBHrutPvceZN .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #dependencyStart,#mermaid-svg-LOJCrBHrutPvceZN .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #dependencyStart,#mermaid-svg-LOJCrBHrutPvceZN .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #extensionStart,#mermaid-svg-LOJCrBHrutPvceZN .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #extensionEnd,#mermaid-svg-LOJCrBHrutPvceZN .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #aggregationStart,#mermaid-svg-LOJCrBHrutPvceZN .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #aggregationEnd,#mermaid-svg-LOJCrBHrutPvceZN .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #lollipopStart,#mermaid-svg-LOJCrBHrutPvceZN .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN #lollipopEnd,#mermaid-svg-LOJCrBHrutPvceZN .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-LOJCrBHrutPvceZN .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-LOJCrBHrutPvceZN .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LOJCrBHrutPvceZN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LOJCrBHrutPvceZN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LOJCrBHrutPvceZN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} implements
created by New(config, Options)
<<interface>>
Manager
+Cluster : cluster.Cluster
+Add(Runnable) : error
+Elected() : ←chan struct
+AddMetricsServerExtraHandler(path, handler) : error
+AddHealthzCheck(name, check) : error
+AddReadyzCheck(name, check) : error
+Start(ctx) : error
+GetWebhookServer() : webhook.Server
+GetLogger() : logr.Logger
+GetControllerOptions() : config.Controller
+GetConverterRegistry() : conversion.Registry
controllerManager
-sync.Mutex
-started bool
-stopProcedureEngaged *int64
-errChan chan error
-runnables *runnables
-cluster cluster.Cluster
-recorderProvider *intrec.Provider
-resourceLock resourcelock.Interface
-metricsServer metricsserver.Server
-healthProbeListener net.Listener
-pprofListener net.Listener
-controllerConfig config.Controller
-logger logr.Logger
-elected chan struct
-webhookServer webhook.Server
-converterRegistry conversion.Registry
-leaseDuration time.Duration
-renewDeadline time.Duration
-retryPeriod time.Duration
-gracefulShutdownTimeout time.Duration
-internalCtx context.Context
-internalCancel context.CancelFunc
Options
+Scheme *runtime.Scheme
+MapperProvider func
+Cache cache.Options
+NewCache cache.NewCacheFunc
+Client client.Options
+NewClient client.NewClientFunc
+Logger logr.Logger
+LeaderElection bool
+LeaderElectionResourceLock string
+LeaderElectionNamespace string
+LeaderElectionID string
+LeaseDuration *time.Duration
+RenewDeadline *time.Duration
+RetryPeriod *time.Duration
+Metrics metricsserver.Options
+HealthProbeBindAddress string
+WebhookServer webhook.Server
+BaseContext BaseContextFunc
+GracefulShutdownTimeout *time.Duration
+Controller config.Controller

3.2 Runnable体系

#mermaid-svg-uY4ImQr6hzCnLVmo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uY4ImQr6hzCnLVmo .error-icon{fill:#552222;}#mermaid-svg-uY4ImQr6hzCnLVmo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uY4ImQr6hzCnLVmo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uY4ImQr6hzCnLVmo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uY4ImQr6hzCnLVmo .marker.cross{stroke:#333333;}#mermaid-svg-uY4ImQr6hzCnLVmo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uY4ImQr6hzCnLVmo p{margin:0;}#mermaid-svg-uY4ImQr6hzCnLVmo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uY4ImQr6hzCnLVmo .cluster-label text{fill:#333;}#mermaid-svg-uY4ImQr6hzCnLVmo .cluster-label span{color:#333;}#mermaid-svg-uY4ImQr6hzCnLVmo .cluster-label span p{background-color:transparent;}#mermaid-svg-uY4ImQr6hzCnLVmo .label text,#mermaid-svg-uY4ImQr6hzCnLVmo span{fill:#333;color:#333;}#mermaid-svg-uY4ImQr6hzCnLVmo .node rect,#mermaid-svg-uY4ImQr6hzCnLVmo .node circle,#mermaid-svg-uY4ImQr6hzCnLVmo .node ellipse,#mermaid-svg-uY4ImQr6hzCnLVmo .node polygon,#mermaid-svg-uY4ImQr6hzCnLVmo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uY4ImQr6hzCnLVmo .rough-node .label text,#mermaid-svg-uY4ImQr6hzCnLVmo .node .label text,#mermaid-svg-uY4ImQr6hzCnLVmo .image-shape .label,#mermaid-svg-uY4ImQr6hzCnLVmo .icon-shape .label{text-anchor:middle;}#mermaid-svg-uY4ImQr6hzCnLVmo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uY4ImQr6hzCnLVmo .rough-node .label,#mermaid-svg-uY4ImQr6hzCnLVmo .node .label,#mermaid-svg-uY4ImQr6hzCnLVmo .image-shape .label,#mermaid-svg-uY4ImQr6hzCnLVmo .icon-shape .label{text-align:center;}#mermaid-svg-uY4ImQr6hzCnLVmo .node.clickable{cursor:pointer;}#mermaid-svg-uY4ImQr6hzCnLVmo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uY4ImQr6hzCnLVmo .arrowheadPath{fill:#333333;}#mermaid-svg-uY4ImQr6hzCnLVmo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uY4ImQr6hzCnLVmo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uY4ImQr6hzCnLVmo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uY4ImQr6hzCnLVmo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uY4ImQr6hzCnLVmo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uY4ImQr6hzCnLVmo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uY4ImQr6hzCnLVmo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uY4ImQr6hzCnLVmo .cluster text{fill:#333;}#mermaid-svg-uY4ImQr6hzCnLVmo .cluster span{color:#333;}#mermaid-svg-uY4ImQr6hzCnLVmo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uY4ImQr6hzCnLVmo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uY4ImQr6hzCnLVmo rect.text{fill:none;stroke-width:0;}#mermaid-svg-uY4ImQr6hzCnLVmo .icon-shape,#mermaid-svg-uY4ImQr6hzCnLVmo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uY4ImQr6hzCnLVmo .icon-shape p,#mermaid-svg-uY4ImQr6hzCnLVmo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uY4ImQr6hzCnLVmo .icon-shape .label rect,#mermaid-svg-uY4ImQr6hzCnLVmo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uY4ImQr6hzCnLVmo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uY4ImQr6hzCnLVmo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uY4ImQr6hzCnLVmo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Yes
No
Runnable interface

Start(ctx) error
RunnableFunc

func(ctx) error
LeaderElectionRunnable

NeedLeaderElection() bool
warmupRunnable

(未导出)

Warmup(ctx) error
NeedLeaderElection=true

→ LeaderElection组
NeedLeaderElection=false

→ Others组
EnableWarmup=true

→ Warmup组 + LeaderElection组
hasCache

GetCache() cache.Cache
→ Caches组
webhook.Server
→ Webhooks组
*Server

HTTP/HTTPS服务器
NeedLeaderElection?
→ LeaderElection组
→ HTTPServers组
默认

→ LeaderElection组

3.3 Runnables六组分类

组名 启动时机 典型成员 Leader选举要求
HTTPServers 最先启动 Metrics Server, Health Probe, Pprof
Webhooks Cache之前 Mutating/Validating/Conversion Webhook
Caches Webhook之后 Cluster(InformerCache)
Others Cache之后 非Leader选举Runnable
Warmup Leader选举前 启用Warmup的Controller源
LeaderElection 当选Leader后 Controller, Leader选举Runnable

3.4 Controller架构

#mermaid-svg-5uy2pHPM5XLkNhNa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5uy2pHPM5XLkNhNa .error-icon{fill:#552222;}#mermaid-svg-5uy2pHPM5XLkNhNa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5uy2pHPM5XLkNhNa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5uy2pHPM5XLkNhNa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5uy2pHPM5XLkNhNa .marker.cross{stroke:#333333;}#mermaid-svg-5uy2pHPM5XLkNhNa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5uy2pHPM5XLkNhNa p{margin:0;}#mermaid-svg-5uy2pHPM5XLkNhNa g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-5uy2pHPM5XLkNhNa g.classGroup text .title{font-weight:bolder;}#mermaid-svg-5uy2pHPM5XLkNhNa .cluster-label text{fill:#333;}#mermaid-svg-5uy2pHPM5XLkNhNa .cluster-label span{color:#333;}#mermaid-svg-5uy2pHPM5XLkNhNa .cluster-label span p{background-color:transparent;}#mermaid-svg-5uy2pHPM5XLkNhNa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5uy2pHPM5XLkNhNa .cluster text{fill:#333;}#mermaid-svg-5uy2pHPM5XLkNhNa .cluster span{color:#333;}#mermaid-svg-5uy2pHPM5XLkNhNa .nodeLabel,#mermaid-svg-5uy2pHPM5XLkNhNa .edgeLabel{color:#131300;}#mermaid-svg-5uy2pHPM5XLkNhNa .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-5uy2pHPM5XLkNhNa .label text{fill:#131300;}#mermaid-svg-5uy2pHPM5XLkNhNa .labelBkg{background:#ECECFF;}#mermaid-svg-5uy2pHPM5XLkNhNa .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-5uy2pHPM5XLkNhNa .classTitle{font-weight:bolder;}#mermaid-svg-5uy2pHPM5XLkNhNa .node rect,#mermaid-svg-5uy2pHPM5XLkNhNa .node circle,#mermaid-svg-5uy2pHPM5XLkNhNa .node ellipse,#mermaid-svg-5uy2pHPM5XLkNhNa .node polygon,#mermaid-svg-5uy2pHPM5XLkNhNa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5uy2pHPM5XLkNhNa .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa g.clickable{cursor:pointer;}#mermaid-svg-5uy2pHPM5XLkNhNa g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-5uy2pHPM5XLkNhNa g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-5uy2pHPM5XLkNhNa .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-5uy2pHPM5XLkNhNa .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-5uy2pHPM5XLkNhNa .dashed-line{stroke-dasharray:3;}#mermaid-svg-5uy2pHPM5XLkNhNa .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-5uy2pHPM5XLkNhNa #compositionStart,#mermaid-svg-5uy2pHPM5XLkNhNa .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #compositionEnd,#mermaid-svg-5uy2pHPM5XLkNhNa .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #dependencyStart,#mermaid-svg-5uy2pHPM5XLkNhNa .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #dependencyStart,#mermaid-svg-5uy2pHPM5XLkNhNa .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #extensionStart,#mermaid-svg-5uy2pHPM5XLkNhNa .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #extensionEnd,#mermaid-svg-5uy2pHPM5XLkNhNa .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #aggregationStart,#mermaid-svg-5uy2pHPM5XLkNhNa .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #aggregationEnd,#mermaid-svg-5uy2pHPM5XLkNhNa .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #lollipopStart,#mermaid-svg-5uy2pHPM5XLkNhNa .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa #lollipopEnd,#mermaid-svg-5uy2pHPM5XLkNhNa .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-5uy2pHPM5XLkNhNa .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-5uy2pHPM5XLkNhNa .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5uy2pHPM5XLkNhNa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5uy2pHPM5XLkNhNa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5uy2pHPM5XLkNhNa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Do
returns
input
Controller<request>
+Name string
+MaxConcurrentReconciles int
+Do reconcile.TypedReconcilerrequest
+RateLimiter workqueue.TypedRateLimiterrequest
+NewQueue func
+Queue priorityqueue.PriorityQueuerequest
+Started bool
+CacheSyncTimeout time.Duration
+RecoverPanic *bool
+LeaderElected *bool
+EnableWarmup *bool
+ReconciliationTimeout time.Duration
-startWatches \[\]source.TypedSourcerequest
-startedEventSourcesAndQueue bool
-mu sync.Mutex
-ctx context.Context
+Reconcile(ctx, req)(Result, error)
+Watch(src) : error
+Start(ctx) : error
+Warmup(ctx) : error
+NeedLeaderElection() : bool
-processNextWorkItem(ctx) : bool
-reconcileHandler(ctx, req, priority)
-startEventSourcesAndQueueLocked(ctx) : error
<<interface>>
TypedReconciler<request>
+Reconcile(ctx, request)(Result, error)
Result
+Requeue bool
+RequeueAfter time.Duration
+Priority *int
+IsZero() : bool
Request
+NamespacedName types.NamespacedName

3.5 Reconcile返回值处理矩阵

#mermaid-svg-hYDegcSYilnsGYJY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hYDegcSYilnsGYJY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hYDegcSYilnsGYJY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hYDegcSYilnsGYJY .error-icon{fill:#552222;}#mermaid-svg-hYDegcSYilnsGYJY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hYDegcSYilnsGYJY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hYDegcSYilnsGYJY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hYDegcSYilnsGYJY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hYDegcSYilnsGYJY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hYDegcSYilnsGYJY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hYDegcSYilnsGYJY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hYDegcSYilnsGYJY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hYDegcSYilnsGYJY .marker.cross{stroke:#333333;}#mermaid-svg-hYDegcSYilnsGYJY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hYDegcSYilnsGYJY p{margin:0;}#mermaid-svg-hYDegcSYilnsGYJY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hYDegcSYilnsGYJY .cluster-label text{fill:#333;}#mermaid-svg-hYDegcSYilnsGYJY .cluster-label span{color:#333;}#mermaid-svg-hYDegcSYilnsGYJY .cluster-label span p{background-color:transparent;}#mermaid-svg-hYDegcSYilnsGYJY .label text,#mermaid-svg-hYDegcSYilnsGYJY span{fill:#333;color:#333;}#mermaid-svg-hYDegcSYilnsGYJY .node rect,#mermaid-svg-hYDegcSYilnsGYJY .node circle,#mermaid-svg-hYDegcSYilnsGYJY .node ellipse,#mermaid-svg-hYDegcSYilnsGYJY .node polygon,#mermaid-svg-hYDegcSYilnsGYJY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hYDegcSYilnsGYJY .rough-node .label text,#mermaid-svg-hYDegcSYilnsGYJY .node .label text,#mermaid-svg-hYDegcSYilnsGYJY .image-shape .label,#mermaid-svg-hYDegcSYilnsGYJY .icon-shape .label{text-anchor:middle;}#mermaid-svg-hYDegcSYilnsGYJY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hYDegcSYilnsGYJY .rough-node .label,#mermaid-svg-hYDegcSYilnsGYJY .node .label,#mermaid-svg-hYDegcSYilnsGYJY .image-shape .label,#mermaid-svg-hYDegcSYilnsGYJY .icon-shape .label{text-align:center;}#mermaid-svg-hYDegcSYilnsGYJY .node.clickable{cursor:pointer;}#mermaid-svg-hYDegcSYilnsGYJY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hYDegcSYilnsGYJY .arrowheadPath{fill:#333333;}#mermaid-svg-hYDegcSYilnsGYJY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hYDegcSYilnsGYJY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hYDegcSYilnsGYJY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hYDegcSYilnsGYJY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hYDegcSYilnsGYJY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hYDegcSYilnsGYJY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hYDegcSYilnsGYJY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hYDegcSYilnsGYJY .cluster text{fill:#333;}#mermaid-svg-hYDegcSYilnsGYJY .cluster span{color:#333;}#mermaid-svg-hYDegcSYilnsGYJY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hYDegcSYilnsGYJY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hYDegcSYilnsGYJY rect.text{fill:none;stroke-width:0;}#mermaid-svg-hYDegcSYilnsGYJY .icon-shape,#mermaid-svg-hYDegcSYilnsGYJY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hYDegcSYilnsGYJY .icon-shape p,#mermaid-svg-hYDegcSYilnsGYJY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hYDegcSYilnsGYJY .icon-shape .label rect,#mermaid-svg-hYDegcSYilnsGYJY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hYDegcSYilnsGYJY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hYDegcSYilnsGYJY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hYDegcSYilnsGYJY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Yes
Yes
No
No
Yes
No
Yes
No
Reconcile返回
err != nil?
TerminalError?
TerminalReconcileErrors++

不重新入队

记录错误日志
AddRateLimited(req)

指数退避重试

ReconcileErrors++

ReconcileTotalerror++
RequeueAfter > 0?
Forget(req)

AddAfter(RequeueAfter)

ReconcileTotalrequeue_after++
Requeue == true?
AddRateLimited(req)

ReconcileTotalrequeue++
Forget(req)

ReconcileTotalsuccess++

返回组合 行为 使用场景
Result{}, nil 成功,Forget 操作完成,等待新事件
Result{RequeueAfter: 30s}, nil 30秒后重入队 定期检查/轮询
Result{Requeue: true}, nil 限流重入队 (已废弃,用RequeueAfter)
Result{}, err 指数退避重试 暂时性错误
Result{}, TerminalError(err) 不重试 不可恢复错误
Result{RequeueAfter: N}, err 忽略RequeueAfter,按err处理 错误优先

3.6 Cache架构

#mermaid-svg-uJTtMgfmYsyiKJiq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uJTtMgfmYsyiKJiq .error-icon{fill:#552222;}#mermaid-svg-uJTtMgfmYsyiKJiq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uJTtMgfmYsyiKJiq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uJTtMgfmYsyiKJiq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uJTtMgfmYsyiKJiq .marker.cross{stroke:#333333;}#mermaid-svg-uJTtMgfmYsyiKJiq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uJTtMgfmYsyiKJiq p{margin:0;}#mermaid-svg-uJTtMgfmYsyiKJiq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uJTtMgfmYsyiKJiq .cluster-label text{fill:#333;}#mermaid-svg-uJTtMgfmYsyiKJiq .cluster-label span{color:#333;}#mermaid-svg-uJTtMgfmYsyiKJiq .cluster-label span p{background-color:transparent;}#mermaid-svg-uJTtMgfmYsyiKJiq .label text,#mermaid-svg-uJTtMgfmYsyiKJiq span{fill:#333;color:#333;}#mermaid-svg-uJTtMgfmYsyiKJiq .node rect,#mermaid-svg-uJTtMgfmYsyiKJiq .node circle,#mermaid-svg-uJTtMgfmYsyiKJiq .node ellipse,#mermaid-svg-uJTtMgfmYsyiKJiq .node polygon,#mermaid-svg-uJTtMgfmYsyiKJiq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uJTtMgfmYsyiKJiq .rough-node .label text,#mermaid-svg-uJTtMgfmYsyiKJiq .node .label text,#mermaid-svg-uJTtMgfmYsyiKJiq .image-shape .label,#mermaid-svg-uJTtMgfmYsyiKJiq .icon-shape .label{text-anchor:middle;}#mermaid-svg-uJTtMgfmYsyiKJiq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uJTtMgfmYsyiKJiq .rough-node .label,#mermaid-svg-uJTtMgfmYsyiKJiq .node .label,#mermaid-svg-uJTtMgfmYsyiKJiq .image-shape .label,#mermaid-svg-uJTtMgfmYsyiKJiq .icon-shape .label{text-align:center;}#mermaid-svg-uJTtMgfmYsyiKJiq .node.clickable{cursor:pointer;}#mermaid-svg-uJTtMgfmYsyiKJiq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uJTtMgfmYsyiKJiq .arrowheadPath{fill:#333333;}#mermaid-svg-uJTtMgfmYsyiKJiq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uJTtMgfmYsyiKJiq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uJTtMgfmYsyiKJiq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uJTtMgfmYsyiKJiq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uJTtMgfmYsyiKJiq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uJTtMgfmYsyiKJiq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uJTtMgfmYsyiKJiq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uJTtMgfmYsyiKJiq .cluster text{fill:#333;}#mermaid-svg-uJTtMgfmYsyiKJiq .cluster span{color:#333;}#mermaid-svg-uJTtMgfmYsyiKJiq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uJTtMgfmYsyiKJiq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uJTtMgfmYsyiKJiq rect.text{fill:none;stroke-width:0;}#mermaid-svg-uJTtMgfmYsyiKJiq .icon-shape,#mermaid-svg-uJTtMgfmYsyiKJiq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uJTtMgfmYsyiKJiq .icon-shape p,#mermaid-svg-uJTtMgfmYsyiKJiq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uJTtMgfmYsyiKJiq .icon-shape .label rect,#mermaid-svg-uJTtMgfmYsyiKJiq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uJTtMgfmYsyiKJiq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uJTtMgfmYsyiKJiq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uJTtMgfmYsyiKJiq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OnChange
经过Predicate
Cache interface
client.Reader

Get/List
Informers interface

GetInformer

GetInformerForKind

Start

WaitForCacheSync

FieldIndexer
informerCache

(实现)
InformersMap

每个GVK一个Informer
SharedInformer

(client-go)
CacheReader

从Informer的Store读取
ResourceEventHandler
Controller Handler

3.7 Client架构

#mermaid-svg-BfeiZI96C23PdpbI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BfeiZI96C23PdpbI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BfeiZI96C23PdpbI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BfeiZI96C23PdpbI .error-icon{fill:#552222;}#mermaid-svg-BfeiZI96C23PdpbI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BfeiZI96C23PdpbI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BfeiZI96C23PdpbI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BfeiZI96C23PdpbI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BfeiZI96C23PdpbI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BfeiZI96C23PdpbI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BfeiZI96C23PdpbI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BfeiZI96C23PdpbI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BfeiZI96C23PdpbI .marker.cross{stroke:#333333;}#mermaid-svg-BfeiZI96C23PdpbI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BfeiZI96C23PdpbI p{margin:0;}#mermaid-svg-BfeiZI96C23PdpbI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BfeiZI96C23PdpbI .cluster-label text{fill:#333;}#mermaid-svg-BfeiZI96C23PdpbI .cluster-label span{color:#333;}#mermaid-svg-BfeiZI96C23PdpbI .cluster-label span p{background-color:transparent;}#mermaid-svg-BfeiZI96C23PdpbI .label text,#mermaid-svg-BfeiZI96C23PdpbI span{fill:#333;color:#333;}#mermaid-svg-BfeiZI96C23PdpbI .node rect,#mermaid-svg-BfeiZI96C23PdpbI .node circle,#mermaid-svg-BfeiZI96C23PdpbI .node ellipse,#mermaid-svg-BfeiZI96C23PdpbI .node polygon,#mermaid-svg-BfeiZI96C23PdpbI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BfeiZI96C23PdpbI .rough-node .label text,#mermaid-svg-BfeiZI96C23PdpbI .node .label text,#mermaid-svg-BfeiZI96C23PdpbI .image-shape .label,#mermaid-svg-BfeiZI96C23PdpbI .icon-shape .label{text-anchor:middle;}#mermaid-svg-BfeiZI96C23PdpbI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BfeiZI96C23PdpbI .rough-node .label,#mermaid-svg-BfeiZI96C23PdpbI .node .label,#mermaid-svg-BfeiZI96C23PdpbI .image-shape .label,#mermaid-svg-BfeiZI96C23PdpbI .icon-shape .label{text-align:center;}#mermaid-svg-BfeiZI96C23PdpbI .node.clickable{cursor:pointer;}#mermaid-svg-BfeiZI96C23PdpbI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BfeiZI96C23PdpbI .arrowheadPath{fill:#333333;}#mermaid-svg-BfeiZI96C23PdpbI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BfeiZI96C23PdpbI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BfeiZI96C23PdpbI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BfeiZI96C23PdpbI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BfeiZI96C23PdpbI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BfeiZI96C23PdpbI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BfeiZI96C23PdpbI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BfeiZI96C23PdpbI .cluster text{fill:#333;}#mermaid-svg-BfeiZI96C23PdpbI .cluster span{color:#333;}#mermaid-svg-BfeiZI96C23PdpbI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BfeiZI96C23PdpbI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BfeiZI96C23PdpbI rect.text{fill:none;stroke-width:0;}#mermaid-svg-BfeiZI96C23PdpbI .icon-shape,#mermaid-svg-BfeiZI96C23PdpbI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BfeiZI96C23PdpbI .icon-shape p,#mermaid-svg-BfeiZI96C23PdpbI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BfeiZI96C23PdpbI .icon-shape .label rect,#mermaid-svg-BfeiZI96C23PdpbI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BfeiZI96C23PdpbI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BfeiZI96C23PdpbI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BfeiZI96C23PdpbI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 读操作
写操作
client.Client interface

Get/List/Create

Update/Delete/Patch
DelegatingClient
CacheReader

从Informer缓存读取
DirectClient

直接调用API Server
APIReader

绕过Cache直读
TypedClient

类型化Client
UnstructuredClient
MetadataClient
Patch

MergePatch/StrategicMergePatch

JSONPatch/ApplyConfiguration


四、包依赖拓扑

#mermaid-svg-19V4BsChjYBEgWc0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-19V4BsChjYBEgWc0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-19V4BsChjYBEgWc0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-19V4BsChjYBEgWc0 .error-icon{fill:#552222;}#mermaid-svg-19V4BsChjYBEgWc0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-19V4BsChjYBEgWc0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-19V4BsChjYBEgWc0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-19V4BsChjYBEgWc0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-19V4BsChjYBEgWc0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-19V4BsChjYBEgWc0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-19V4BsChjYBEgWc0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-19V4BsChjYBEgWc0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-19V4BsChjYBEgWc0 .marker.cross{stroke:#333333;}#mermaid-svg-19V4BsChjYBEgWc0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-19V4BsChjYBEgWc0 p{margin:0;}#mermaid-svg-19V4BsChjYBEgWc0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-19V4BsChjYBEgWc0 .cluster-label text{fill:#333;}#mermaid-svg-19V4BsChjYBEgWc0 .cluster-label span{color:#333;}#mermaid-svg-19V4BsChjYBEgWc0 .cluster-label span p{background-color:transparent;}#mermaid-svg-19V4BsChjYBEgWc0 .label text,#mermaid-svg-19V4BsChjYBEgWc0 span{fill:#333;color:#333;}#mermaid-svg-19V4BsChjYBEgWc0 .node rect,#mermaid-svg-19V4BsChjYBEgWc0 .node circle,#mermaid-svg-19V4BsChjYBEgWc0 .node ellipse,#mermaid-svg-19V4BsChjYBEgWc0 .node polygon,#mermaid-svg-19V4BsChjYBEgWc0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-19V4BsChjYBEgWc0 .rough-node .label text,#mermaid-svg-19V4BsChjYBEgWc0 .node .label text,#mermaid-svg-19V4BsChjYBEgWc0 .image-shape .label,#mermaid-svg-19V4BsChjYBEgWc0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-19V4BsChjYBEgWc0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-19V4BsChjYBEgWc0 .rough-node .label,#mermaid-svg-19V4BsChjYBEgWc0 .node .label,#mermaid-svg-19V4BsChjYBEgWc0 .image-shape .label,#mermaid-svg-19V4BsChjYBEgWc0 .icon-shape .label{text-align:center;}#mermaid-svg-19V4BsChjYBEgWc0 .node.clickable{cursor:pointer;}#mermaid-svg-19V4BsChjYBEgWc0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-19V4BsChjYBEgWc0 .arrowheadPath{fill:#333333;}#mermaid-svg-19V4BsChjYBEgWc0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-19V4BsChjYBEgWc0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-19V4BsChjYBEgWc0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-19V4BsChjYBEgWc0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-19V4BsChjYBEgWc0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-19V4BsChjYBEgWc0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-19V4BsChjYBEgWc0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-19V4BsChjYBEgWc0 .cluster text{fill:#333;}#mermaid-svg-19V4BsChjYBEgWc0 .cluster span{color:#333;}#mermaid-svg-19V4BsChjYBEgWc0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-19V4BsChjYBEgWc0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-19V4BsChjYBEgWc0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-19V4BsChjYBEgWc0 .icon-shape,#mermaid-svg-19V4BsChjYBEgWc0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-19V4BsChjYBEgWc0 .icon-shape p,#mermaid-svg-19V4BsChjYBEgWc0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-19V4BsChjYBEgWc0 .icon-shape .label rect,#mermaid-svg-19V4BsChjYBEgWc0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-19V4BsChjYBEgWc0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-19V4BsChjYBEgWc0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-19V4BsChjYBEgWc0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} pkg/manager
pkg/cluster
pkg/cache
pkg/client
pkg/webhook
pkg/leaderelection
pkg/metrics
pkg/healthz
pkg/recorder
pkg/scheme
pkg/builder
pkg/controller
pkg/source
pkg/handler
pkg/predicate
pkg/internal/controller
pkg/controller/priorityqueue
pkg/controller/controllerutil
pkg/reconcile
pkg/event
pkg/webhook/admission
pkg/webhook/conversion
pkg/webhook/authentication


五、文档规划

文档 核心内容 预估行数
00-总览架构文档(本文件) 架构全景、数据流、包依赖 ~500
01-Manager深度分析 New()/Start()/Stop/RunnableGroup/Leader选举 ~800
02-Controller深度分析 Reconcile循环/Worker/PriorityQueue/Watch ~900
03-Cache深度分析 InformerCache/InformerMap/CacheReader/MultiNS ~800
04-Client深度分析 DelegatingClient/Patch/TypedClient/Watch ~800
05-Source-Handler-Predicate深度分析 Kind/Enqueue/EnqueueOwner/Predicate ~700
06-Webhook深度分析 Server/Admission/Conversion/Authentication ~800
07-Builder-Reconcile-Cluster深度分析 流式构建/Reconcile接口/Cluster ~600