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。
核心职责:
- Manager:管理所有组件的生命周期、依赖注入、Leader选举
- Controller:Reconcile循环、WorkQueue、事件分发
- Cache:Informer缓存、本地读加速、Field索引
- Client:统一的K8s API读写客户端(读走Cache,写走直连)
- Webhook:Mutating/Validating/Conversion/Authentication四种Webhook
- Source/Handler/Predicate:事件源、事件处理、事件过滤三件套
- Builder:流式API构建Controller和Webhook
- 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 }
启动顺序的关键原因:
- HTTP先于Cache:Health Probe必须先启动,否则Conversion Webhook阻塞Cache同步
- Webhook先于Cache:Cache同步时可能触发Conversion Webhook,如果Webhook未就绪会死锁
- Cache先于Controller:Controller的Reconcile依赖Cache数据
- 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 |