AKS
AKS 是 Azure 托管的 Kubernetes。
Agent 用它运行 RunnerManager、临时 Runner、LLM Gateway 和运维 Dashboard,并让这些容器能够自动部署、隔离、扩缩容和自我恢复
#mermaid-svg-0SsrbCGFNhfHas4O{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-0SsrbCGFNhfHas4O .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0SsrbCGFNhfHas4O .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0SsrbCGFNhfHas4O .error-icon{fill:#552222;}#mermaid-svg-0SsrbCGFNhfHas4O .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0SsrbCGFNhfHas4O .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0SsrbCGFNhfHas4O .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0SsrbCGFNhfHas4O .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0SsrbCGFNhfHas4O .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0SsrbCGFNhfHas4O .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0SsrbCGFNhfHas4O .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0SsrbCGFNhfHas4O .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0SsrbCGFNhfHas4O .marker.cross{stroke:#333333;}#mermaid-svg-0SsrbCGFNhfHas4O svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0SsrbCGFNhfHas4O p{margin:0;}#mermaid-svg-0SsrbCGFNhfHas4O .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0SsrbCGFNhfHas4O .cluster-label text{fill:#333;}#mermaid-svg-0SsrbCGFNhfHas4O .cluster-label span{color:#333;}#mermaid-svg-0SsrbCGFNhfHas4O .cluster-label span p{background-color:transparent;}#mermaid-svg-0SsrbCGFNhfHas4O .label text,#mermaid-svg-0SsrbCGFNhfHas4O span{fill:#333;color:#333;}#mermaid-svg-0SsrbCGFNhfHas4O .node rect,#mermaid-svg-0SsrbCGFNhfHas4O .node circle,#mermaid-svg-0SsrbCGFNhfHas4O .node ellipse,#mermaid-svg-0SsrbCGFNhfHas4O .node polygon,#mermaid-svg-0SsrbCGFNhfHas4O .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0SsrbCGFNhfHas4O .rough-node .label text,#mermaid-svg-0SsrbCGFNhfHas4O .node .label text,#mermaid-svg-0SsrbCGFNhfHas4O .image-shape .label,#mermaid-svg-0SsrbCGFNhfHas4O .icon-shape .label{text-anchor:middle;}#mermaid-svg-0SsrbCGFNhfHas4O .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0SsrbCGFNhfHas4O .rough-node .label,#mermaid-svg-0SsrbCGFNhfHas4O .node .label,#mermaid-svg-0SsrbCGFNhfHas4O .image-shape .label,#mermaid-svg-0SsrbCGFNhfHas4O .icon-shape .label{text-align:center;}#mermaid-svg-0SsrbCGFNhfHas4O .node.clickable{cursor:pointer;}#mermaid-svg-0SsrbCGFNhfHas4O .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0SsrbCGFNhfHas4O .arrowheadPath{fill:#333333;}#mermaid-svg-0SsrbCGFNhfHas4O .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0SsrbCGFNhfHas4O .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0SsrbCGFNhfHas4O .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0SsrbCGFNhfHas4O .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0SsrbCGFNhfHas4O .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0SsrbCGFNhfHas4O .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0SsrbCGFNhfHas4O .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0SsrbCGFNhfHas4O .cluster text{fill:#333;}#mermaid-svg-0SsrbCGFNhfHas4O .cluster span{color:#333;}#mermaid-svg-0SsrbCGFNhfHas4O 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-0SsrbCGFNhfHas4O .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0SsrbCGFNhfHas4O rect.text{fill:none;stroke-width:0;}#mermaid-svg-0SsrbCGFNhfHas4O .icon-shape,#mermaid-svg-0SsrbCGFNhfHas4O .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0SsrbCGFNhfHas4O .icon-shape p,#mermaid-svg-0SsrbCGFNhfHas4O .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0SsrbCGFNhfHas4O .icon-shape .label rect,#mermaid-svg-0SsrbCGFNhfHas4O .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0SsrbCGFNhfHas4O .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0SsrbCGFNhfHas4O .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0SsrbCGFNhfHas4O :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户提交任务
ApiServiceNg
Azure Service Bus
RunnerManager
AKS / Kubernetes API
临时 Runner Pod
临时 Runner Pod
LLM Gateway
Copilot / Azure AI 模型
一、AKS 是什么
Kubernetes 可以理解为一个"容器操作系统"。普通操作系统管理进程,Kubernetes 管理运行在多台服务器上的容器;AKS 则是 Azure 帮你托管 Kubernetes 控制面的产品。
#mermaid-svg-WLoDGdjHacY7vlCh{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-WLoDGdjHacY7vlCh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WLoDGdjHacY7vlCh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WLoDGdjHacY7vlCh .error-icon{fill:#552222;}#mermaid-svg-WLoDGdjHacY7vlCh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WLoDGdjHacY7vlCh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WLoDGdjHacY7vlCh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WLoDGdjHacY7vlCh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WLoDGdjHacY7vlCh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WLoDGdjHacY7vlCh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WLoDGdjHacY7vlCh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WLoDGdjHacY7vlCh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WLoDGdjHacY7vlCh .marker.cross{stroke:#333333;}#mermaid-svg-WLoDGdjHacY7vlCh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WLoDGdjHacY7vlCh p{margin:0;}#mermaid-svg-WLoDGdjHacY7vlCh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WLoDGdjHacY7vlCh .cluster-label text{fill:#333;}#mermaid-svg-WLoDGdjHacY7vlCh .cluster-label span{color:#333;}#mermaid-svg-WLoDGdjHacY7vlCh .cluster-label span p{background-color:transparent;}#mermaid-svg-WLoDGdjHacY7vlCh .label text,#mermaid-svg-WLoDGdjHacY7vlCh span{fill:#333;color:#333;}#mermaid-svg-WLoDGdjHacY7vlCh .node rect,#mermaid-svg-WLoDGdjHacY7vlCh .node circle,#mermaid-svg-WLoDGdjHacY7vlCh .node ellipse,#mermaid-svg-WLoDGdjHacY7vlCh .node polygon,#mermaid-svg-WLoDGdjHacY7vlCh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WLoDGdjHacY7vlCh .rough-node .label text,#mermaid-svg-WLoDGdjHacY7vlCh .node .label text,#mermaid-svg-WLoDGdjHacY7vlCh .image-shape .label,#mermaid-svg-WLoDGdjHacY7vlCh .icon-shape .label{text-anchor:middle;}#mermaid-svg-WLoDGdjHacY7vlCh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WLoDGdjHacY7vlCh .rough-node .label,#mermaid-svg-WLoDGdjHacY7vlCh .node .label,#mermaid-svg-WLoDGdjHacY7vlCh .image-shape .label,#mermaid-svg-WLoDGdjHacY7vlCh .icon-shape .label{text-align:center;}#mermaid-svg-WLoDGdjHacY7vlCh .node.clickable{cursor:pointer;}#mermaid-svg-WLoDGdjHacY7vlCh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WLoDGdjHacY7vlCh .arrowheadPath{fill:#333333;}#mermaid-svg-WLoDGdjHacY7vlCh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WLoDGdjHacY7vlCh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WLoDGdjHacY7vlCh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WLoDGdjHacY7vlCh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WLoDGdjHacY7vlCh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WLoDGdjHacY7vlCh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WLoDGdjHacY7vlCh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WLoDGdjHacY7vlCh .cluster text{fill:#333;}#mermaid-svg-WLoDGdjHacY7vlCh .cluster span{color:#333;}#mermaid-svg-WLoDGdjHacY7vlCh 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-WLoDGdjHacY7vlCh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WLoDGdjHacY7vlCh rect.text{fill:none;stroke-width:0;}#mermaid-svg-WLoDGdjHacY7vlCh .icon-shape,#mermaid-svg-WLoDGdjHacY7vlCh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WLoDGdjHacY7vlCh .icon-shape p,#mermaid-svg-WLoDGdjHacY7vlCh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WLoDGdjHacY7vlCh .icon-shape .label rect,#mermaid-svg-WLoDGdjHacY7vlCh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WLoDGdjHacY7vlCh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WLoDGdjHacY7vlCh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WLoDGdjHacY7vlCh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Azure Kubernetes Service
工作节点
Linux Node
Pod Pod Pod
控制面
API Server / Scheduler
由 Azure 托管
Windows Node
Runner Pod
Windows Node
Runner Pod
AKS 不等于某一台服务器,也不等于 Docker。三者关系是:
| 概念 | 通俗理解 | 负责什么 |
|---|---|---|
| Docker/Image | 标准集装箱 | 打包程序和依赖 |
| Kubernetes | 港口调度系统 | 安排集装箱运行、迁移和扩容 |
| AKS | Azure 经营的 Kubernetes 港口 | 托管控制面,并和 Azure 网络、身份、磁盘结合 |
| Pod | 一次具体运行 | Kubernetes 最小调度单位 |
| Node | 承载 Pod 的机器 | 真正提供 CPU、内存和操作系统 |
仓库中的 AKS 目录不是 AKS 集群本身,而是描述部分集群资源的 YAML 和安装脚本。运行 kubectl apply 后,这些"期望状态"才会提交给真实集群。
#mermaid-svg-FqULcFO9XDrz07zy{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-FqULcFO9XDrz07zy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FqULcFO9XDrz07zy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FqULcFO9XDrz07zy .error-icon{fill:#552222;}#mermaid-svg-FqULcFO9XDrz07zy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FqULcFO9XDrz07zy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FqULcFO9XDrz07zy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FqULcFO9XDrz07zy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FqULcFO9XDrz07zy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FqULcFO9XDrz07zy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FqULcFO9XDrz07zy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FqULcFO9XDrz07zy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FqULcFO9XDrz07zy .marker.cross{stroke:#333333;}#mermaid-svg-FqULcFO9XDrz07zy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FqULcFO9XDrz07zy p{margin:0;}#mermaid-svg-FqULcFO9XDrz07zy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FqULcFO9XDrz07zy .cluster-label text{fill:#333;}#mermaid-svg-FqULcFO9XDrz07zy .cluster-label span{color:#333;}#mermaid-svg-FqULcFO9XDrz07zy .cluster-label span p{background-color:transparent;}#mermaid-svg-FqULcFO9XDrz07zy .label text,#mermaid-svg-FqULcFO9XDrz07zy span{fill:#333;color:#333;}#mermaid-svg-FqULcFO9XDrz07zy .node rect,#mermaid-svg-FqULcFO9XDrz07zy .node circle,#mermaid-svg-FqULcFO9XDrz07zy .node ellipse,#mermaid-svg-FqULcFO9XDrz07zy .node polygon,#mermaid-svg-FqULcFO9XDrz07zy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FqULcFO9XDrz07zy .rough-node .label text,#mermaid-svg-FqULcFO9XDrz07zy .node .label text,#mermaid-svg-FqULcFO9XDrz07zy .image-shape .label,#mermaid-svg-FqULcFO9XDrz07zy .icon-shape .label{text-anchor:middle;}#mermaid-svg-FqULcFO9XDrz07zy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FqULcFO9XDrz07zy .rough-node .label,#mermaid-svg-FqULcFO9XDrz07zy .node .label,#mermaid-svg-FqULcFO9XDrz07zy .image-shape .label,#mermaid-svg-FqULcFO9XDrz07zy .icon-shape .label{text-align:center;}#mermaid-svg-FqULcFO9XDrz07zy .node.clickable{cursor:pointer;}#mermaid-svg-FqULcFO9XDrz07zy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FqULcFO9XDrz07zy .arrowheadPath{fill:#333333;}#mermaid-svg-FqULcFO9XDrz07zy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FqULcFO9XDrz07zy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FqULcFO9XDrz07zy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FqULcFO9XDrz07zy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FqULcFO9XDrz07zy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FqULcFO9XDrz07zy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FqULcFO9XDrz07zy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FqULcFO9XDrz07zy .cluster text{fill:#333;}#mermaid-svg-FqULcFO9XDrz07zy .cluster span{color:#333;}#mermaid-svg-FqULcFO9XDrz07zy 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-FqULcFO9XDrz07zy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FqULcFO9XDrz07zy rect.text{fill:none;stroke-width:0;}#mermaid-svg-FqULcFO9XDrz07zy .icon-shape,#mermaid-svg-FqULcFO9XDrz07zy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FqULcFO9XDrz07zy .icon-shape p,#mermaid-svg-FqULcFO9XDrz07zy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FqULcFO9XDrz07zy .icon-shape .label rect,#mermaid-svg-FqULcFO9XDrz07zy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FqULcFO9XDrz07zy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FqULcFO9XDrz07zy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FqULcFO9XDrz07zy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} kubectl apply
异常或 Pod 消失
重新创建
Git 中的 YAML
期望状态
Kubernetes API
控制器持续对账
真实状态
Pod / Service / Disk
这种设计叫 声明式管理:告诉 Kubernetes"我要三个 RunnerManager",而不是手工执行"启动进程 1、2、3"。如果一个 Pod 崩溃,控制器会自动补一个。
二、de 为什么需要 AKS
de 的主要计算任务不是固定、均匀的 Web 请求,而是持续时间长、资源需求大、并发数量变化明显的编码任务。
每个任务可能需要独立代码目录、Git 凭据、模型配置和几十 GiB 内存。
#mermaid-svg-gXBxs1UAflJQpjPQ{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-gXBxs1UAflJQpjPQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gXBxs1UAflJQpjPQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gXBxs1UAflJQpjPQ .error-icon{fill:#552222;}#mermaid-svg-gXBxs1UAflJQpjPQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gXBxs1UAflJQpjPQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gXBxs1UAflJQpjPQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gXBxs1UAflJQpjPQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gXBxs1UAflJQpjPQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gXBxs1UAflJQpjPQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gXBxs1UAflJQpjPQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gXBxs1UAflJQpjPQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gXBxs1UAflJQpjPQ .marker.cross{stroke:#333333;}#mermaid-svg-gXBxs1UAflJQpjPQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gXBxs1UAflJQpjPQ p{margin:0;}#mermaid-svg-gXBxs1UAflJQpjPQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gXBxs1UAflJQpjPQ .cluster-label text{fill:#333;}#mermaid-svg-gXBxs1UAflJQpjPQ .cluster-label span{color:#333;}#mermaid-svg-gXBxs1UAflJQpjPQ .cluster-label span p{background-color:transparent;}#mermaid-svg-gXBxs1UAflJQpjPQ .label text,#mermaid-svg-gXBxs1UAflJQpjPQ span{fill:#333;color:#333;}#mermaid-svg-gXBxs1UAflJQpjPQ .node rect,#mermaid-svg-gXBxs1UAflJQpjPQ .node circle,#mermaid-svg-gXBxs1UAflJQpjPQ .node ellipse,#mermaid-svg-gXBxs1UAflJQpjPQ .node polygon,#mermaid-svg-gXBxs1UAflJQpjPQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gXBxs1UAflJQpjPQ .rough-node .label text,#mermaid-svg-gXBxs1UAflJQpjPQ .node .label text,#mermaid-svg-gXBxs1UAflJQpjPQ .image-shape .label,#mermaid-svg-gXBxs1UAflJQpjPQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-gXBxs1UAflJQpjPQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gXBxs1UAflJQpjPQ .rough-node .label,#mermaid-svg-gXBxs1UAflJQpjPQ .node .label,#mermaid-svg-gXBxs1UAflJQpjPQ .image-shape .label,#mermaid-svg-gXBxs1UAflJQpjPQ .icon-shape .label{text-align:center;}#mermaid-svg-gXBxs1UAflJQpjPQ .node.clickable{cursor:pointer;}#mermaid-svg-gXBxs1UAflJQpjPQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gXBxs1UAflJQpjPQ .arrowheadPath{fill:#333333;}#mermaid-svg-gXBxs1UAflJQpjPQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gXBxs1UAflJQpjPQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gXBxs1UAflJQpjPQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gXBxs1UAflJQpjPQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gXBxs1UAflJQpjPQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gXBxs1UAflJQpjPQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gXBxs1UAflJQpjPQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gXBxs1UAflJQpjPQ .cluster text{fill:#333;}#mermaid-svg-gXBxs1UAflJQpjPQ .cluster span{color:#333;}#mermaid-svg-gXBxs1UAflJQpjPQ 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-gXBxs1UAflJQpjPQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gXBxs1UAflJQpjPQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-gXBxs1UAflJQpjPQ .icon-shape,#mermaid-svg-gXBxs1UAflJQpjPQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gXBxs1UAflJQpjPQ .icon-shape p,#mermaid-svg-gXBxs1UAflJQpjPQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gXBxs1UAflJQpjPQ .icon-shape .label rect,#mermaid-svg-gXBxs1UAflJQpjPQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gXBxs1UAflJQpjPQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gXBxs1UAflJQpjPQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gXBxs1UAflJQpjPQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 任务 A
独立 Runner Pod
代码仓库 A
任务 B
独立 Runner Pod
代码仓库 B
任务 C
独立 Runner Pod
代码仓库 C
完成后删除
完成后删除
完成后删除
采用单台 VM 当然也能运行程序,但会带来进程相互干扰、依赖冲突、资源争抢、故障集中和清理困难。一个任务把磁盘写满或进程卡死,可能影响其他所有任务。
采用 Azure Functions 也不合适。Functions 更适合短时间、无状态、事件驱动的函数;de Runner 需要长时间执行、较大的 CPU/内存、持久工作目录、Git 和开发工具链,并可能运行 Windows 工作负载。
采用 AKS 后,每个任务可以拥有独立 Pod:
- 任务之间有进程、文件系统和资源边界。
- 可以给 Runner 设置 CPU 和内存请求及上限。
- 任务到来时创建 Pod,结束后删除。
- Linux 和 Windows 工作负载可以调度到不同节点池。
- Pod 失败后由 RunnerManager 或 Kubernetes 检测并恢复。
高峰期可以增加节点,低峰期可以回收节点。
因此这里选择 AKS,不是因为"Kubernetes 更高级",而是因为工作负载本身具有**动态、隔离、资源密集、生命周期明确**的特点。
三、集群中的主要区域
当前设计使用 Namespace 把不同职责和环境隔开:
#mermaid-svg-ImD2Ako5OH4aqQ9L{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-ImD2Ako5OH4aqQ9L .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ImD2Ako5OH4aqQ9L .error-icon{fill:#552222;}#mermaid-svg-ImD2Ako5OH4aqQ9L .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ImD2Ako5OH4aqQ9L .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .marker.cross{stroke:#333333;}#mermaid-svg-ImD2Ako5OH4aqQ9L svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ImD2Ako5OH4aqQ9L p{margin:0;}#mermaid-svg-ImD2Ako5OH4aqQ9L .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .cluster-label text{fill:#333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .cluster-label span{color:#333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .cluster-label span p{background-color:transparent;}#mermaid-svg-ImD2Ako5OH4aqQ9L .label text,#mermaid-svg-ImD2Ako5OH4aqQ9L span{fill:#333;color:#333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .node rect,#mermaid-svg-ImD2Ako5OH4aqQ9L .node circle,#mermaid-svg-ImD2Ako5OH4aqQ9L .node ellipse,#mermaid-svg-ImD2Ako5OH4aqQ9L .node polygon,#mermaid-svg-ImD2Ako5OH4aqQ9L .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ImD2Ako5OH4aqQ9L .rough-node .label text,#mermaid-svg-ImD2Ako5OH4aqQ9L .node .label text,#mermaid-svg-ImD2Ako5OH4aqQ9L .image-shape .label,#mermaid-svg-ImD2Ako5OH4aqQ9L .icon-shape .label{text-anchor:middle;}#mermaid-svg-ImD2Ako5OH4aqQ9L .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ImD2Ako5OH4aqQ9L .rough-node .label,#mermaid-svg-ImD2Ako5OH4aqQ9L .node .label,#mermaid-svg-ImD2Ako5OH4aqQ9L .image-shape .label,#mermaid-svg-ImD2Ako5OH4aqQ9L .icon-shape .label{text-align:center;}#mermaid-svg-ImD2Ako5OH4aqQ9L .node.clickable{cursor:pointer;}#mermaid-svg-ImD2Ako5OH4aqQ9L .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .arrowheadPath{fill:#333333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ImD2Ako5OH4aqQ9L .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ImD2Ako5OH4aqQ9L .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ImD2Ako5OH4aqQ9L .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ImD2Ako5OH4aqQ9L .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ImD2Ako5OH4aqQ9L .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ImD2Ako5OH4aqQ9L .cluster text{fill:#333;}#mermaid-svg-ImD2Ako5OH4aqQ9L .cluster span{color:#333;}#mermaid-svg-ImD2Ako5OH4aqQ9L 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-ImD2Ako5OH4aqQ9L .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ImD2Ako5OH4aqQ9L rect.text{fill:none;stroke-width:0;}#mermaid-svg-ImD2Ako5OH4aqQ9L .icon-shape,#mermaid-svg-ImD2Ako5OH4aqQ9L .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ImD2Ako5OH4aqQ9L .icon-shape p,#mermaid-svg-ImD2Ako5OH4aqQ9L .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ImD2Ako5OH4aqQ9L .icon-shape .label rect,#mermaid-svg-ImD2Ako5OH4aqQ9L .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ImD2Ako5OH4aqQ9L .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ImD2Ako5OH4aqQ9L .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ImD2Ako5OH4aqQ9L :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} AKS Cluster
Infrastructure
infra / Kubed
runnerdashboard
Staging
runnermanager-staging
runner-staging
llm-proxy-staging
Production
runnermanager
runner
llm-proxy
生产和 Staging 使用不同 Namespace,而不是把所有资源放入 default。好处是名称、配置、Secret、RBAC 和资源查询都可以按环境分开。例如生产 RunnerManager 创建 Pod 时使用 runner,Staging 使用 runner-staging。
为什么不为每个环境建立完全独立的 AKS 集群?独立集群的隔离更强,适合严格合规或高风险系统,但成本、节点利用率、升级和维护工作也会翻倍。Namespace 是一种成本较低的逻辑隔离。它不是完整安全边界,因此仍需要 RBAC、Pod Security 和网络策略共同保护。
Namespace 定义见 namespaces.yaml 和 namespaces-core.yaml。它们统一启用了 Restricted Pod Security:
text
enforce = restricted
audit = baseline
warn = baseline
含义是:违反严格安全规则的 Pod 会被拒绝,同时对基线规则进行审计和警告。
四、RunnerManager 和临时 Runner
RunnerManager 是 AKS 中的任务调度业务服务。它自身以 Deployment 运行三个副本,并通过 Kubernetes API 动态管理 Runner Pod。
LLM Gateway Runner Pod Kubernetes API RunnerManager Service Bus ApiServiceNg LLM Gateway Runner Pod Kubernetes API RunnerManager Service Bus ApiServiceNg #mermaid-svg-KtmfqzB56wYEh3nK{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-KtmfqzB56wYEh3nK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KtmfqzB56wYEh3nK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KtmfqzB56wYEh3nK .error-icon{fill:#552222;}#mermaid-svg-KtmfqzB56wYEh3nK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KtmfqzB56wYEh3nK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KtmfqzB56wYEh3nK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KtmfqzB56wYEh3nK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KtmfqzB56wYEh3nK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KtmfqzB56wYEh3nK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KtmfqzB56wYEh3nK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KtmfqzB56wYEh3nK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KtmfqzB56wYEh3nK .marker.cross{stroke:#333333;}#mermaid-svg-KtmfqzB56wYEh3nK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KtmfqzB56wYEh3nK p{margin:0;}#mermaid-svg-KtmfqzB56wYEh3nK .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KtmfqzB56wYEh3nK text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-KtmfqzB56wYEh3nK .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-KtmfqzB56wYEh3nK .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-KtmfqzB56wYEh3nK .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-KtmfqzB56wYEh3nK .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-KtmfqzB56wYEh3nK #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-KtmfqzB56wYEh3nK .sequenceNumber{fill:white;}#mermaid-svg-KtmfqzB56wYEh3nK #sequencenumber{fill:#333;}#mermaid-svg-KtmfqzB56wYEh3nK #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-KtmfqzB56wYEh3nK .messageText{fill:#333;stroke:none;}#mermaid-svg-KtmfqzB56wYEh3nK .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KtmfqzB56wYEh3nK .labelText,#mermaid-svg-KtmfqzB56wYEh3nK .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-KtmfqzB56wYEh3nK .loopText,#mermaid-svg-KtmfqzB56wYEh3nK .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-KtmfqzB56wYEh3nK .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-KtmfqzB56wYEh3nK .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-KtmfqzB56wYEh3nK .noteText,#mermaid-svg-KtmfqzB56wYEh3nK .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-KtmfqzB56wYEh3nK .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KtmfqzB56wYEh3nK .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KtmfqzB56wYEh3nK .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KtmfqzB56wYEh3nK .actorPopupMenu{position:absolute;}#mermaid-svg-KtmfqzB56wYEh3nK .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-KtmfqzB56wYEh3nK .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KtmfqzB56wYEh3nK .actor-man circle,#mermaid-svg-KtmfqzB56wYEh3nK line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-KtmfqzB56wYEh3nK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 发布编码任务消费任务消息创建带资源与配置的 Pod调度到合适节点请求模型完成编码报告进度、请求审批发布任务状态任务结束后删除 Pod
RunnerManager 配置中,生产 Runner Pod 可以申请最多 16 CPU、36 GiB 内存,并限制单用户最多运行 6 个 Pod,见 config-runnermanager.yaml。
为什么 RunnerManager 自己不直接运行编码任务?因为调度控制和实际计算是两种不同职责:
- RunnerManager 较轻,应该长期稳定运行。
- Runner 很重,数量随任务变化,并可能运行不可信的仓库命令。
- 二者拆开后,一个 Runner 崩溃不会带走调度服务。
- Runner 镜像和模型配置可以独立升级。
RunnerManager 使用 ClusterIP Service,只供集群内部访问,没有公网 Ingress。这是正确的最小暴露设计:外部系统通过 Service Bus 交换消息,Runner Pod 通过集群 DNS 调用它,没有必要为管理 API开放公网入口。相关资源见 deployment.yaml 和 service.yaml。
五、Deployment、Service 和 Ingress 为什么分开
这三个概念经常混淆:
#mermaid-svg-FjgJIJeryR6p65pg{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-FjgJIJeryR6p65pg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FjgJIJeryR6p65pg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FjgJIJeryR6p65pg .error-icon{fill:#552222;}#mermaid-svg-FjgJIJeryR6p65pg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FjgJIJeryR6p65pg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FjgJIJeryR6p65pg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FjgJIJeryR6p65pg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FjgJIJeryR6p65pg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FjgJIJeryR6p65pg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FjgJIJeryR6p65pg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FjgJIJeryR6p65pg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FjgJIJeryR6p65pg .marker.cross{stroke:#333333;}#mermaid-svg-FjgJIJeryR6p65pg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FjgJIJeryR6p65pg p{margin:0;}#mermaid-svg-FjgJIJeryR6p65pg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FjgJIJeryR6p65pg .cluster-label text{fill:#333;}#mermaid-svg-FjgJIJeryR6p65pg .cluster-label span{color:#333;}#mermaid-svg-FjgJIJeryR6p65pg .cluster-label span p{background-color:transparent;}#mermaid-svg-FjgJIJeryR6p65pg .label text,#mermaid-svg-FjgJIJeryR6p65pg span{fill:#333;color:#333;}#mermaid-svg-FjgJIJeryR6p65pg .node rect,#mermaid-svg-FjgJIJeryR6p65pg .node circle,#mermaid-svg-FjgJIJeryR6p65pg .node ellipse,#mermaid-svg-FjgJIJeryR6p65pg .node polygon,#mermaid-svg-FjgJIJeryR6p65pg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FjgJIJeryR6p65pg .rough-node .label text,#mermaid-svg-FjgJIJeryR6p65pg .node .label text,#mermaid-svg-FjgJIJeryR6p65pg .image-shape .label,#mermaid-svg-FjgJIJeryR6p65pg .icon-shape .label{text-anchor:middle;}#mermaid-svg-FjgJIJeryR6p65pg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FjgJIJeryR6p65pg .rough-node .label,#mermaid-svg-FjgJIJeryR6p65pg .node .label,#mermaid-svg-FjgJIJeryR6p65pg .image-shape .label,#mermaid-svg-FjgJIJeryR6p65pg .icon-shape .label{text-align:center;}#mermaid-svg-FjgJIJeryR6p65pg .node.clickable{cursor:pointer;}#mermaid-svg-FjgJIJeryR6p65pg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FjgJIJeryR6p65pg .arrowheadPath{fill:#333333;}#mermaid-svg-FjgJIJeryR6p65pg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FjgJIJeryR6p65pg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FjgJIJeryR6p65pg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FjgJIJeryR6p65pg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FjgJIJeryR6p65pg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FjgJIJeryR6p65pg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FjgJIJeryR6p65pg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FjgJIJeryR6p65pg .cluster text{fill:#333;}#mermaid-svg-FjgJIJeryR6p65pg .cluster span{color:#333;}#mermaid-svg-FjgJIJeryR6p65pg 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-FjgJIJeryR6p65pg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FjgJIJeryR6p65pg rect.text{fill:none;stroke-width:0;}#mermaid-svg-FjgJIJeryR6p65pg .icon-shape,#mermaid-svg-FjgJIJeryR6p65pg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FjgJIJeryR6p65pg .icon-shape p,#mermaid-svg-FjgJIJeryR6p65pg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FjgJIJeryR6p65pg .icon-shape .label rect,#mermaid-svg-FjgJIJeryR6p65pg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FjgJIJeryR6p65pg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FjgJIJeryR6p65pg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FjgJIJeryR6p65pg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 外部请求
Ingress
域名和路径路由
Service
稳定虚拟地址
Pod A
Pod B
Pod C
- Deployment 管 Pod 数量和升级。
- Service 为不断更换 IP 的 Pod 提供稳定名称和负载均衡。
- Ingress 把外部 HTTP 流量引入某个 Service。
Pod 是短暂的,重启后 IP 会变化,所以调用方不应该记住 Pod IP。它只访问 runnermanager.runnermanager.svc.cluster.local:3981 之类的 Service DNS。
Dashboard 和 Copilot2API 需要被指定入口访问,因此配置了 Azure Application Gateway Ingress;RunnerManager 不需要公网访问,所以只有 ClusterIP。这体现了"需要才暴露",而不是所有服务都配置公网 IP。
Dashboard 的完整外部链路是:
#mermaid-svg-SpgQ3R7xUbUa61S8{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-SpgQ3R7xUbUa61S8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SpgQ3R7xUbUa61S8 .error-icon{fill:#552222;}#mermaid-svg-SpgQ3R7xUbUa61S8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SpgQ3R7xUbUa61S8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .marker.cross{stroke:#333333;}#mermaid-svg-SpgQ3R7xUbUa61S8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SpgQ3R7xUbUa61S8 p{margin:0;}#mermaid-svg-SpgQ3R7xUbUa61S8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .cluster-label text{fill:#333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .cluster-label span{color:#333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .cluster-label span p{background-color:transparent;}#mermaid-svg-SpgQ3R7xUbUa61S8 .label text,#mermaid-svg-SpgQ3R7xUbUa61S8 span{fill:#333;color:#333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .node rect,#mermaid-svg-SpgQ3R7xUbUa61S8 .node circle,#mermaid-svg-SpgQ3R7xUbUa61S8 .node ellipse,#mermaid-svg-SpgQ3R7xUbUa61S8 .node polygon,#mermaid-svg-SpgQ3R7xUbUa61S8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SpgQ3R7xUbUa61S8 .rough-node .label text,#mermaid-svg-SpgQ3R7xUbUa61S8 .node .label text,#mermaid-svg-SpgQ3R7xUbUa61S8 .image-shape .label,#mermaid-svg-SpgQ3R7xUbUa61S8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-SpgQ3R7xUbUa61S8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SpgQ3R7xUbUa61S8 .rough-node .label,#mermaid-svg-SpgQ3R7xUbUa61S8 .node .label,#mermaid-svg-SpgQ3R7xUbUa61S8 .image-shape .label,#mermaid-svg-SpgQ3R7xUbUa61S8 .icon-shape .label{text-align:center;}#mermaid-svg-SpgQ3R7xUbUa61S8 .node.clickable{cursor:pointer;}#mermaid-svg-SpgQ3R7xUbUa61S8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .arrowheadPath{fill:#333333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SpgQ3R7xUbUa61S8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SpgQ3R7xUbUa61S8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SpgQ3R7xUbUa61S8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SpgQ3R7xUbUa61S8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SpgQ3R7xUbUa61S8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SpgQ3R7xUbUa61S8 .cluster text{fill:#333;}#mermaid-svg-SpgQ3R7xUbUa61S8 .cluster span{color:#333;}#mermaid-svg-SpgQ3R7xUbUa61S8 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-SpgQ3R7xUbUa61S8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SpgQ3R7xUbUa61S8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-SpgQ3R7xUbUa61S8 .icon-shape,#mermaid-svg-SpgQ3R7xUbUa61S8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SpgQ3R7xUbUa61S8 .icon-shape p,#mermaid-svg-SpgQ3R7xUbUa61S8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SpgQ3R7xUbUa61S8 .icon-shape .label rect,#mermaid-svg-SpgQ3R7xUbUa61S8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SpgQ3R7xUbUa61S8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SpgQ3R7xUbUa61S8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SpgQ3R7xUbUa61S8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 运维人员浏览器
Azure Front Door
Application Gateway
AKS Ingress
ClusterIP Service :80
Dashboard Pod :3085
Ingress 配置见 ingress.yaml。
六、LLM Gateway 为什么分层
LLM 路径包含 Copilot2API,以及仓库中保存的 LiteLLM 路由配置。二者看似都是代理,职责实际上不同:
#mermaid-svg-4qhO0Y45DgmwW5KL{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-4qhO0Y45DgmwW5KL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4qhO0Y45DgmwW5KL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4qhO0Y45DgmwW5KL .error-icon{fill:#552222;}#mermaid-svg-4qhO0Y45DgmwW5KL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4qhO0Y45DgmwW5KL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4qhO0Y45DgmwW5KL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4qhO0Y45DgmwW5KL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4qhO0Y45DgmwW5KL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4qhO0Y45DgmwW5KL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4qhO0Y45DgmwW5KL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4qhO0Y45DgmwW5KL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4qhO0Y45DgmwW5KL .marker.cross{stroke:#333333;}#mermaid-svg-4qhO0Y45DgmwW5KL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4qhO0Y45DgmwW5KL p{margin:0;}#mermaid-svg-4qhO0Y45DgmwW5KL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4qhO0Y45DgmwW5KL .cluster-label text{fill:#333;}#mermaid-svg-4qhO0Y45DgmwW5KL .cluster-label span{color:#333;}#mermaid-svg-4qhO0Y45DgmwW5KL .cluster-label span p{background-color:transparent;}#mermaid-svg-4qhO0Y45DgmwW5KL .label text,#mermaid-svg-4qhO0Y45DgmwW5KL span{fill:#333;color:#333;}#mermaid-svg-4qhO0Y45DgmwW5KL .node rect,#mermaid-svg-4qhO0Y45DgmwW5KL .node circle,#mermaid-svg-4qhO0Y45DgmwW5KL .node ellipse,#mermaid-svg-4qhO0Y45DgmwW5KL .node polygon,#mermaid-svg-4qhO0Y45DgmwW5KL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4qhO0Y45DgmwW5KL .rough-node .label text,#mermaid-svg-4qhO0Y45DgmwW5KL .node .label text,#mermaid-svg-4qhO0Y45DgmwW5KL .image-shape .label,#mermaid-svg-4qhO0Y45DgmwW5KL .icon-shape .label{text-anchor:middle;}#mermaid-svg-4qhO0Y45DgmwW5KL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4qhO0Y45DgmwW5KL .rough-node .label,#mermaid-svg-4qhO0Y45DgmwW5KL .node .label,#mermaid-svg-4qhO0Y45DgmwW5KL .image-shape .label,#mermaid-svg-4qhO0Y45DgmwW5KL .icon-shape .label{text-align:center;}#mermaid-svg-4qhO0Y45DgmwW5KL .node.clickable{cursor:pointer;}#mermaid-svg-4qhO0Y45DgmwW5KL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4qhO0Y45DgmwW5KL .arrowheadPath{fill:#333333;}#mermaid-svg-4qhO0Y45DgmwW5KL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4qhO0Y45DgmwW5KL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4qhO0Y45DgmwW5KL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4qhO0Y45DgmwW5KL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4qhO0Y45DgmwW5KL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4qhO0Y45DgmwW5KL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4qhO0Y45DgmwW5KL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4qhO0Y45DgmwW5KL .cluster text{fill:#333;}#mermaid-svg-4qhO0Y45DgmwW5KL .cluster span{color:#333;}#mermaid-svg-4qhO0Y45DgmwW5KL 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-4qhO0Y45DgmwW5KL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4qhO0Y45DgmwW5KL rect.text{fill:none;stroke-width:0;}#mermaid-svg-4qhO0Y45DgmwW5KL .icon-shape,#mermaid-svg-4qhO0Y45DgmwW5KL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4qhO0Y45DgmwW5KL .icon-shape p,#mermaid-svg-4qhO0Y45DgmwW5KL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4qhO0Y45DgmwW5KL .icon-shape .label rect,#mermaid-svg-4qhO0Y45DgmwW5KL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4qhO0Y45DgmwW5KL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4qhO0Y45DgmwW5KL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4qhO0Y45DgmwW5KL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Runner
LiteLLM / Gateway
统一模型名、重试、路由
Copilot 账号 1
Copilot 账号 2
Copilot 账号 3
Azure AI fallback
-
Copilot2API 负责把 GitHub Copilot 能力转换成 OpenAI、Anthropic 等兼容接口,并管理账号认证。
-
LiteLLM 配置负责把同一模型映射到多个账号,采用
simple-shuffle分流,失败后重试三次,并配置 Opus 到 Sonnet 的降级,见 litellm-config.yaml。
为什么不让每个 Runner 自己选择账号和实现重试?
- 账号池规则会散落到所有 Runner 镜像。
- 更换账号需要重新构建或重启大量 Runner。
- 重试、降级和统计逻辑容易不一致。
- 密钥暴露范围更大。
集中 Gateway 后,Runner 只需要知道一个内部地址和逻辑模型名。路由政策可以独立调整。不过也会增加一跳网络延迟,并形成重要依赖,因此 Gateway 需要监控、重试和容量规划。
需要注意:当前 litellm 只保存 LiteLLM 配置,没有它的 Deployment 或安装脚本;部分 Runner 配置还会直接访问 Copilot2API 的 /gw/api。所以这个目录表达的是路由配置和目标架构,不能单凭这些文件认定所有请求一定先经过独立 LiteLLM Pod。
七、为什么 Copilot2API 只有一个副本
Copilot2API 把账号 Token 和数据库保存在 Azure Disk PVC 中。PVC 使用 ReadWriteOnce,表示同一时刻只能挂载到一个节点。
#mermaid-svg-nfGFM7im8Z6OQLwF{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-nfGFM7im8Z6OQLwF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nfGFM7im8Z6OQLwF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nfGFM7im8Z6OQLwF .error-icon{fill:#552222;}#mermaid-svg-nfGFM7im8Z6OQLwF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nfGFM7im8Z6OQLwF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nfGFM7im8Z6OQLwF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nfGFM7im8Z6OQLwF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nfGFM7im8Z6OQLwF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nfGFM7im8Z6OQLwF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nfGFM7im8Z6OQLwF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nfGFM7im8Z6OQLwF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nfGFM7im8Z6OQLwF .marker.cross{stroke:#333333;}#mermaid-svg-nfGFM7im8Z6OQLwF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nfGFM7im8Z6OQLwF p{margin:0;}#mermaid-svg-nfGFM7im8Z6OQLwF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nfGFM7im8Z6OQLwF .cluster-label text{fill:#333;}#mermaid-svg-nfGFM7im8Z6OQLwF .cluster-label span{color:#333;}#mermaid-svg-nfGFM7im8Z6OQLwF .cluster-label span p{background-color:transparent;}#mermaid-svg-nfGFM7im8Z6OQLwF .label text,#mermaid-svg-nfGFM7im8Z6OQLwF span{fill:#333;color:#333;}#mermaid-svg-nfGFM7im8Z6OQLwF .node rect,#mermaid-svg-nfGFM7im8Z6OQLwF .node circle,#mermaid-svg-nfGFM7im8Z6OQLwF .node ellipse,#mermaid-svg-nfGFM7im8Z6OQLwF .node polygon,#mermaid-svg-nfGFM7im8Z6OQLwF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nfGFM7im8Z6OQLwF .rough-node .label text,#mermaid-svg-nfGFM7im8Z6OQLwF .node .label text,#mermaid-svg-nfGFM7im8Z6OQLwF .image-shape .label,#mermaid-svg-nfGFM7im8Z6OQLwF .icon-shape .label{text-anchor:middle;}#mermaid-svg-nfGFM7im8Z6OQLwF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nfGFM7im8Z6OQLwF .rough-node .label,#mermaid-svg-nfGFM7im8Z6OQLwF .node .label,#mermaid-svg-nfGFM7im8Z6OQLwF .image-shape .label,#mermaid-svg-nfGFM7im8Z6OQLwF .icon-shape .label{text-align:center;}#mermaid-svg-nfGFM7im8Z6OQLwF .node.clickable{cursor:pointer;}#mermaid-svg-nfGFM7im8Z6OQLwF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nfGFM7im8Z6OQLwF .arrowheadPath{fill:#333333;}#mermaid-svg-nfGFM7im8Z6OQLwF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nfGFM7im8Z6OQLwF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nfGFM7im8Z6OQLwF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nfGFM7im8Z6OQLwF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nfGFM7im8Z6OQLwF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nfGFM7im8Z6OQLwF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nfGFM7im8Z6OQLwF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nfGFM7im8Z6OQLwF .cluster text{fill:#333;}#mermaid-svg-nfGFM7im8Z6OQLwF .cluster span{color:#333;}#mermaid-svg-nfGFM7im8Z6OQLwF 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-nfGFM7im8Z6OQLwF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nfGFM7im8Z6OQLwF rect.text{fill:none;stroke-width:0;}#mermaid-svg-nfGFM7im8Z6OQLwF .icon-shape,#mermaid-svg-nfGFM7im8Z6OQLwF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nfGFM7im8Z6OQLwF .icon-shape p,#mermaid-svg-nfGFM7im8Z6OQLwF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nfGFM7im8Z6OQLwF .icon-shape .label rect,#mermaid-svg-nfGFM7im8Z6OQLwF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nfGFM7im8Z6OQLwF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nfGFM7im8Z6OQLwF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nfGFM7im8Z6OQLwF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Copilot2API Pod
PVC 8 GiB
ReadWriteOnce
Azure Premium SSD
Retain
Pod 重建
如果使用默认 RollingUpdate,新 Pod 会先启动,但磁盘仍挂在旧 Pod 所在节点,新 Pod就可能一直等待挂载。当前采用 Recreate:
#mermaid-svg-kAQlC7TTIfGLKFmK{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-kAQlC7TTIfGLKFmK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kAQlC7TTIfGLKFmK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kAQlC7TTIfGLKFmK .error-icon{fill:#552222;}#mermaid-svg-kAQlC7TTIfGLKFmK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kAQlC7TTIfGLKFmK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kAQlC7TTIfGLKFmK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kAQlC7TTIfGLKFmK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kAQlC7TTIfGLKFmK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kAQlC7TTIfGLKFmK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kAQlC7TTIfGLKFmK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kAQlC7TTIfGLKFmK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kAQlC7TTIfGLKFmK .marker.cross{stroke:#333333;}#mermaid-svg-kAQlC7TTIfGLKFmK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kAQlC7TTIfGLKFmK p{margin:0;}#mermaid-svg-kAQlC7TTIfGLKFmK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kAQlC7TTIfGLKFmK .cluster-label text{fill:#333;}#mermaid-svg-kAQlC7TTIfGLKFmK .cluster-label span{color:#333;}#mermaid-svg-kAQlC7TTIfGLKFmK .cluster-label span p{background-color:transparent;}#mermaid-svg-kAQlC7TTIfGLKFmK .label text,#mermaid-svg-kAQlC7TTIfGLKFmK span{fill:#333;color:#333;}#mermaid-svg-kAQlC7TTIfGLKFmK .node rect,#mermaid-svg-kAQlC7TTIfGLKFmK .node circle,#mermaid-svg-kAQlC7TTIfGLKFmK .node ellipse,#mermaid-svg-kAQlC7TTIfGLKFmK .node polygon,#mermaid-svg-kAQlC7TTIfGLKFmK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kAQlC7TTIfGLKFmK .rough-node .label text,#mermaid-svg-kAQlC7TTIfGLKFmK .node .label text,#mermaid-svg-kAQlC7TTIfGLKFmK .image-shape .label,#mermaid-svg-kAQlC7TTIfGLKFmK .icon-shape .label{text-anchor:middle;}#mermaid-svg-kAQlC7TTIfGLKFmK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kAQlC7TTIfGLKFmK .rough-node .label,#mermaid-svg-kAQlC7TTIfGLKFmK .node .label,#mermaid-svg-kAQlC7TTIfGLKFmK .image-shape .label,#mermaid-svg-kAQlC7TTIfGLKFmK .icon-shape .label{text-align:center;}#mermaid-svg-kAQlC7TTIfGLKFmK .node.clickable{cursor:pointer;}#mermaid-svg-kAQlC7TTIfGLKFmK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kAQlC7TTIfGLKFmK .arrowheadPath{fill:#333333;}#mermaid-svg-kAQlC7TTIfGLKFmK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kAQlC7TTIfGLKFmK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kAQlC7TTIfGLKFmK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kAQlC7TTIfGLKFmK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kAQlC7TTIfGLKFmK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kAQlC7TTIfGLKFmK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kAQlC7TTIfGLKFmK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kAQlC7TTIfGLKFmK .cluster text{fill:#333;}#mermaid-svg-kAQlC7TTIfGLKFmK .cluster span{color:#333;}#mermaid-svg-kAQlC7TTIfGLKFmK 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-kAQlC7TTIfGLKFmK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kAQlC7TTIfGLKFmK rect.text{fill:none;stroke-width:0;}#mermaid-svg-kAQlC7TTIfGLKFmK .icon-shape,#mermaid-svg-kAQlC7TTIfGLKFmK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kAQlC7TTIfGLKFmK .icon-shape p,#mermaid-svg-kAQlC7TTIfGLKFmK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kAQlC7TTIfGLKFmK .icon-shape .label rect,#mermaid-svg-kAQlC7TTIfGLKFmK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kAQlC7TTIfGLKFmK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kAQlC7TTIfGLKFmK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kAQlC7TTIfGLKFmK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 停止旧 Pod
释放 Azure Disk
启动新 Pod
挂载原有账号数据
这牺牲了升级期间的短暂停机,换取简单可靠的磁盘挂载。另一种方案是把状态迁移到外部数据库或支持多写的存储,然后运行多个无状态副本;可用性更高,但实现和运维复杂度也更高。
StorageClass 使用 Premium SSD、Retain 回收策略和 WaitForFirstConsumer,见 storageclass.yaml:
Premium_LRS:降低状态读写延迟。Retain:删除 PVC 后不自动删除底层数据,降低误删账号数据的风险。WaitForFirstConsumer:等 Pod 确定节点后再分配磁盘,避免磁盘区域和节点不匹配。allowVolumeExpansion:未来可以扩容。
八、扩缩容和自我恢复
RunnerManager Deployment 固定从三个副本起步,HPA 可扩展到五个副本:
#mermaid-svg-CjCHANrw2bRhYdZh{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-CjCHANrw2bRhYdZh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CjCHANrw2bRhYdZh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CjCHANrw2bRhYdZh .error-icon{fill:#552222;}#mermaid-svg-CjCHANrw2bRhYdZh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CjCHANrw2bRhYdZh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CjCHANrw2bRhYdZh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CjCHANrw2bRhYdZh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CjCHANrw2bRhYdZh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CjCHANrw2bRhYdZh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CjCHANrw2bRhYdZh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CjCHANrw2bRhYdZh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CjCHANrw2bRhYdZh .marker.cross{stroke:#333333;}#mermaid-svg-CjCHANrw2bRhYdZh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CjCHANrw2bRhYdZh p{margin:0;}#mermaid-svg-CjCHANrw2bRhYdZh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CjCHANrw2bRhYdZh .cluster-label text{fill:#333;}#mermaid-svg-CjCHANrw2bRhYdZh .cluster-label span{color:#333;}#mermaid-svg-CjCHANrw2bRhYdZh .cluster-label span p{background-color:transparent;}#mermaid-svg-CjCHANrw2bRhYdZh .label text,#mermaid-svg-CjCHANrw2bRhYdZh span{fill:#333;color:#333;}#mermaid-svg-CjCHANrw2bRhYdZh .node rect,#mermaid-svg-CjCHANrw2bRhYdZh .node circle,#mermaid-svg-CjCHANrw2bRhYdZh .node ellipse,#mermaid-svg-CjCHANrw2bRhYdZh .node polygon,#mermaid-svg-CjCHANrw2bRhYdZh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CjCHANrw2bRhYdZh .rough-node .label text,#mermaid-svg-CjCHANrw2bRhYdZh .node .label text,#mermaid-svg-CjCHANrw2bRhYdZh .image-shape .label,#mermaid-svg-CjCHANrw2bRhYdZh .icon-shape .label{text-anchor:middle;}#mermaid-svg-CjCHANrw2bRhYdZh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CjCHANrw2bRhYdZh .rough-node .label,#mermaid-svg-CjCHANrw2bRhYdZh .node .label,#mermaid-svg-CjCHANrw2bRhYdZh .image-shape .label,#mermaid-svg-CjCHANrw2bRhYdZh .icon-shape .label{text-align:center;}#mermaid-svg-CjCHANrw2bRhYdZh .node.clickable{cursor:pointer;}#mermaid-svg-CjCHANrw2bRhYdZh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CjCHANrw2bRhYdZh .arrowheadPath{fill:#333333;}#mermaid-svg-CjCHANrw2bRhYdZh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CjCHANrw2bRhYdZh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CjCHANrw2bRhYdZh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CjCHANrw2bRhYdZh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CjCHANrw2bRhYdZh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CjCHANrw2bRhYdZh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CjCHANrw2bRhYdZh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CjCHANrw2bRhYdZh .cluster text{fill:#333;}#mermaid-svg-CjCHANrw2bRhYdZh .cluster span{color:#333;}#mermaid-svg-CjCHANrw2bRhYdZh 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-CjCHANrw2bRhYdZh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CjCHANrw2bRhYdZh rect.text{fill:none;stroke-width:0;}#mermaid-svg-CjCHANrw2bRhYdZh .icon-shape,#mermaid-svg-CjCHANrw2bRhYdZh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CjCHANrw2bRhYdZh .icon-shape p,#mermaid-svg-CjCHANrw2bRhYdZh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CjCHANrw2bRhYdZh .icon-shape .label rect,#mermaid-svg-CjCHANrw2bRhYdZh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CjCHANrw2bRhYdZh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CjCHANrw2bRhYdZh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CjCHANrw2bRhYdZh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} CPU > 70%
内存 > 80%
持续下降
CPU / 内存指标
超过阈值?
增加副本
等待 300 秒稳定窗口
缓慢缩容
配置见 hpa.yaml。扩容快、缩容慢,是为了避免短暂波动导致副本数量来回震荡。三个最小副本则保证一个 Pod 重启或节点维护时服务仍有余量。
每个长期服务还配置了探针:
startupProbe:应用是否完成启动。readinessProbe:是否可以接收流量。livenessProbe:是否已经卡死,需要重启。
这比单纯判断"进程还在不在"更可靠。进程可能存活,但数据库、事件循环或内部服务已经无法工作。
资源 requests 告诉调度器至少预留多少资源;limits 防止单个容器无限消耗节点。没有 requests,调度器很难正确放置 Pod;没有 limits,一个异常容器可能拖累整个节点。
九、身份、Secret 与最小权限
de 没有给所有 Pod 一个万能管理员身份,而是采用 ServiceAccount、RBAC 和 Azure Workload Identity:
#mermaid-svg-KnYrfgTQ2xjSlqQO{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-KnYrfgTQ2xjSlqQO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KnYrfgTQ2xjSlqQO .error-icon{fill:#552222;}#mermaid-svg-KnYrfgTQ2xjSlqQO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KnYrfgTQ2xjSlqQO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .marker.cross{stroke:#333333;}#mermaid-svg-KnYrfgTQ2xjSlqQO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KnYrfgTQ2xjSlqQO p{margin:0;}#mermaid-svg-KnYrfgTQ2xjSlqQO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .cluster-label text{fill:#333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .cluster-label span{color:#333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .cluster-label span p{background-color:transparent;}#mermaid-svg-KnYrfgTQ2xjSlqQO .label text,#mermaid-svg-KnYrfgTQ2xjSlqQO span{fill:#333;color:#333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .node rect,#mermaid-svg-KnYrfgTQ2xjSlqQO .node circle,#mermaid-svg-KnYrfgTQ2xjSlqQO .node ellipse,#mermaid-svg-KnYrfgTQ2xjSlqQO .node polygon,#mermaid-svg-KnYrfgTQ2xjSlqQO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KnYrfgTQ2xjSlqQO .rough-node .label text,#mermaid-svg-KnYrfgTQ2xjSlqQO .node .label text,#mermaid-svg-KnYrfgTQ2xjSlqQO .image-shape .label,#mermaid-svg-KnYrfgTQ2xjSlqQO .icon-shape .label{text-anchor:middle;}#mermaid-svg-KnYrfgTQ2xjSlqQO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KnYrfgTQ2xjSlqQO .rough-node .label,#mermaid-svg-KnYrfgTQ2xjSlqQO .node .label,#mermaid-svg-KnYrfgTQ2xjSlqQO .image-shape .label,#mermaid-svg-KnYrfgTQ2xjSlqQO .icon-shape .label{text-align:center;}#mermaid-svg-KnYrfgTQ2xjSlqQO .node.clickable{cursor:pointer;}#mermaid-svg-KnYrfgTQ2xjSlqQO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .arrowheadPath{fill:#333333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KnYrfgTQ2xjSlqQO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KnYrfgTQ2xjSlqQO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KnYrfgTQ2xjSlqQO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KnYrfgTQ2xjSlqQO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KnYrfgTQ2xjSlqQO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KnYrfgTQ2xjSlqQO .cluster text{fill:#333;}#mermaid-svg-KnYrfgTQ2xjSlqQO .cluster span{color:#333;}#mermaid-svg-KnYrfgTQ2xjSlqQO 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-KnYrfgTQ2xjSlqQO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KnYrfgTQ2xjSlqQO rect.text{fill:none;stroke-width:0;}#mermaid-svg-KnYrfgTQ2xjSlqQO .icon-shape,#mermaid-svg-KnYrfgTQ2xjSlqQO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KnYrfgTQ2xjSlqQO .icon-shape p,#mermaid-svg-KnYrfgTQ2xjSlqQO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KnYrfgTQ2xjSlqQO .icon-shape .label rect,#mermaid-svg-KnYrfgTQ2xjSlqQO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KnYrfgTQ2xjSlqQO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KnYrfgTQ2xjSlqQO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KnYrfgTQ2xjSlqQO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Pod
Kubernetes ServiceAccount
Federated Identity
Azure Managed Identity
Key Vault / Azure AI / 其他 Azure 服务
Workload Identity 避免把长期 Client Secret 写进镜像或 YAML。Pod 获得短期 Token,身份权限也可以独立控制。
RunnerManager 容器还设置了:
- 非 root 用户
10001。 - 禁止提权和 privileged。
- 删除全部 Linux capabilities。
- 只读根文件系统。
RuntimeDefaultseccomp。- 临时写入只能进入 tmp 的
emptyDir。
这比"容器本来就隔离,所以直接 root 运行"更安全。容器不是虚拟机级安全边界;一旦应用存在漏洞,最小权限能减少进一步攻击节点的机会。
Dashboard 的 RBAC 也很有代表性:
#mermaid-svg-FGQKfz5hMlTIkpZt{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-FGQKfz5hMlTIkpZt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FGQKfz5hMlTIkpZt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FGQKfz5hMlTIkpZt .error-icon{fill:#552222;}#mermaid-svg-FGQKfz5hMlTIkpZt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FGQKfz5hMlTIkpZt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FGQKfz5hMlTIkpZt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FGQKfz5hMlTIkpZt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FGQKfz5hMlTIkpZt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FGQKfz5hMlTIkpZt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FGQKfz5hMlTIkpZt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FGQKfz5hMlTIkpZt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FGQKfz5hMlTIkpZt .marker.cross{stroke:#333333;}#mermaid-svg-FGQKfz5hMlTIkpZt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FGQKfz5hMlTIkpZt p{margin:0;}#mermaid-svg-FGQKfz5hMlTIkpZt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FGQKfz5hMlTIkpZt .cluster-label text{fill:#333;}#mermaid-svg-FGQKfz5hMlTIkpZt .cluster-label span{color:#333;}#mermaid-svg-FGQKfz5hMlTIkpZt .cluster-label span p{background-color:transparent;}#mermaid-svg-FGQKfz5hMlTIkpZt .label text,#mermaid-svg-FGQKfz5hMlTIkpZt span{fill:#333;color:#333;}#mermaid-svg-FGQKfz5hMlTIkpZt .node rect,#mermaid-svg-FGQKfz5hMlTIkpZt .node circle,#mermaid-svg-FGQKfz5hMlTIkpZt .node ellipse,#mermaid-svg-FGQKfz5hMlTIkpZt .node polygon,#mermaid-svg-FGQKfz5hMlTIkpZt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FGQKfz5hMlTIkpZt .rough-node .label text,#mermaid-svg-FGQKfz5hMlTIkpZt .node .label text,#mermaid-svg-FGQKfz5hMlTIkpZt .image-shape .label,#mermaid-svg-FGQKfz5hMlTIkpZt .icon-shape .label{text-anchor:middle;}#mermaid-svg-FGQKfz5hMlTIkpZt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FGQKfz5hMlTIkpZt .rough-node .label,#mermaid-svg-FGQKfz5hMlTIkpZt .node .label,#mermaid-svg-FGQKfz5hMlTIkpZt .image-shape .label,#mermaid-svg-FGQKfz5hMlTIkpZt .icon-shape .label{text-align:center;}#mermaid-svg-FGQKfz5hMlTIkpZt .node.clickable{cursor:pointer;}#mermaid-svg-FGQKfz5hMlTIkpZt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FGQKfz5hMlTIkpZt .arrowheadPath{fill:#333333;}#mermaid-svg-FGQKfz5hMlTIkpZt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FGQKfz5hMlTIkpZt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FGQKfz5hMlTIkpZt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FGQKfz5hMlTIkpZt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FGQKfz5hMlTIkpZt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FGQKfz5hMlTIkpZt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FGQKfz5hMlTIkpZt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FGQKfz5hMlTIkpZt .cluster text{fill:#333;}#mermaid-svg-FGQKfz5hMlTIkpZt .cluster span{color:#333;}#mermaid-svg-FGQKfz5hMlTIkpZt 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-FGQKfz5hMlTIkpZt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FGQKfz5hMlTIkpZt rect.text{fill:none;stroke-width:0;}#mermaid-svg-FGQKfz5hMlTIkpZt .icon-shape,#mermaid-svg-FGQKfz5hMlTIkpZt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FGQKfz5hMlTIkpZt .icon-shape p,#mermaid-svg-FGQKfz5hMlTIkpZt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FGQKfz5hMlTIkpZt .icon-shape .label rect,#mermaid-svg-FGQKfz5hMlTIkpZt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FGQKfz5hMlTIkpZt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FGQKfz5hMlTIkpZt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FGQKfz5hMlTIkpZt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Dashboard
全局只读
Pod / 日志 / 事件 / 指标
Staging 指定 Deployment
允许 patch
生产 RunnerManager
只允许 get
指定预拉取 DaemonSet
允许 patch/delete Pod
它没有获得 cluster-admin。写权限细化到 Namespace、资源类型和 resourceNames,见 rbac.yaml。这样 Dashboard 即使发生错误,也不能随意删除生产 Deployment 或读取全部 Secret。
ACR 拉取凭据由 acr-msit Secret 提供。Kubed 根据注解把它同步到各 Namespace:
#mermaid-svg-GTP4vX6tSqhNpnAr{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-GTP4vX6tSqhNpnAr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GTP4vX6tSqhNpnAr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GTP4vX6tSqhNpnAr .error-icon{fill:#552222;}#mermaid-svg-GTP4vX6tSqhNpnAr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GTP4vX6tSqhNpnAr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GTP4vX6tSqhNpnAr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GTP4vX6tSqhNpnAr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GTP4vX6tSqhNpnAr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GTP4vX6tSqhNpnAr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GTP4vX6tSqhNpnAr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GTP4vX6tSqhNpnAr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GTP4vX6tSqhNpnAr .marker.cross{stroke:#333333;}#mermaid-svg-GTP4vX6tSqhNpnAr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GTP4vX6tSqhNpnAr p{margin:0;}#mermaid-svg-GTP4vX6tSqhNpnAr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GTP4vX6tSqhNpnAr .cluster-label text{fill:#333;}#mermaid-svg-GTP4vX6tSqhNpnAr .cluster-label span{color:#333;}#mermaid-svg-GTP4vX6tSqhNpnAr .cluster-label span p{background-color:transparent;}#mermaid-svg-GTP4vX6tSqhNpnAr .label text,#mermaid-svg-GTP4vX6tSqhNpnAr span{fill:#333;color:#333;}#mermaid-svg-GTP4vX6tSqhNpnAr .node rect,#mermaid-svg-GTP4vX6tSqhNpnAr .node circle,#mermaid-svg-GTP4vX6tSqhNpnAr .node ellipse,#mermaid-svg-GTP4vX6tSqhNpnAr .node polygon,#mermaid-svg-GTP4vX6tSqhNpnAr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GTP4vX6tSqhNpnAr .rough-node .label text,#mermaid-svg-GTP4vX6tSqhNpnAr .node .label text,#mermaid-svg-GTP4vX6tSqhNpnAr .image-shape .label,#mermaid-svg-GTP4vX6tSqhNpnAr .icon-shape .label{text-anchor:middle;}#mermaid-svg-GTP4vX6tSqhNpnAr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GTP4vX6tSqhNpnAr .rough-node .label,#mermaid-svg-GTP4vX6tSqhNpnAr .node .label,#mermaid-svg-GTP4vX6tSqhNpnAr .image-shape .label,#mermaid-svg-GTP4vX6tSqhNpnAr .icon-shape .label{text-align:center;}#mermaid-svg-GTP4vX6tSqhNpnAr .node.clickable{cursor:pointer;}#mermaid-svg-GTP4vX6tSqhNpnAr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GTP4vX6tSqhNpnAr .arrowheadPath{fill:#333333;}#mermaid-svg-GTP4vX6tSqhNpnAr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GTP4vX6tSqhNpnAr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GTP4vX6tSqhNpnAr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GTP4vX6tSqhNpnAr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GTP4vX6tSqhNpnAr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GTP4vX6tSqhNpnAr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GTP4vX6tSqhNpnAr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GTP4vX6tSqhNpnAr .cluster text{fill:#333;}#mermaid-svg-GTP4vX6tSqhNpnAr .cluster span{color:#333;}#mermaid-svg-GTP4vX6tSqhNpnAr 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-GTP4vX6tSqhNpnAr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GTP4vX6tSqhNpnAr rect.text{fill:none;stroke-width:0;}#mermaid-svg-GTP4vX6tSqhNpnAr .icon-shape,#mermaid-svg-GTP4vX6tSqhNpnAr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GTP4vX6tSqhNpnAr .icon-shape p,#mermaid-svg-GTP4vX6tSqhNpnAr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GTP4vX6tSqhNpnAr .icon-shape .label rect,#mermaid-svg-GTP4vX6tSqhNpnAr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GTP4vX6tSqhNpnAr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GTP4vX6tSqhNpnAr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GTP4vX6tSqhNpnAr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} infra/acr-msit
Kubed Secret Syncer
runner
runnermanager
llm-proxy
runnerdashboard
选择 Kubed 是因为逐个 Namespace 手工复制 Secret 容易遗漏,而且轮换凭据时可能出现不同步。代价是 Kubed 本身拥有跨 Namespace 操作 Secret 的高权限,因此必须保护 infra Namespace 并严格控制同步注解。
Kubed 的 Helm 包直接保存在仓库中,是因为部署使用的 SAW 环境无法自由访问外部 Registry。这牺牲了一部分依赖更新便利性,但换来可重复的离线安装。
十、Staging 和生产为什么采用不同镜像策略
Copilot2API 的 Staging 使用 :latest 和 imagePullPolicy: Always,生产使用固定的日期与提交标签。
#mermaid-svg-BChozgfaBK0zwtNj{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-BChozgfaBK0zwtNj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BChozgfaBK0zwtNj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BChozgfaBK0zwtNj .error-icon{fill:#552222;}#mermaid-svg-BChozgfaBK0zwtNj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BChozgfaBK0zwtNj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BChozgfaBK0zwtNj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BChozgfaBK0zwtNj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BChozgfaBK0zwtNj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BChozgfaBK0zwtNj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BChozgfaBK0zwtNj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BChozgfaBK0zwtNj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BChozgfaBK0zwtNj .marker.cross{stroke:#333333;}#mermaid-svg-BChozgfaBK0zwtNj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BChozgfaBK0zwtNj p{margin:0;}#mermaid-svg-BChozgfaBK0zwtNj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BChozgfaBK0zwtNj .cluster-label text{fill:#333;}#mermaid-svg-BChozgfaBK0zwtNj .cluster-label span{color:#333;}#mermaid-svg-BChozgfaBK0zwtNj .cluster-label span p{background-color:transparent;}#mermaid-svg-BChozgfaBK0zwtNj .label text,#mermaid-svg-BChozgfaBK0zwtNj span{fill:#333;color:#333;}#mermaid-svg-BChozgfaBK0zwtNj .node rect,#mermaid-svg-BChozgfaBK0zwtNj .node circle,#mermaid-svg-BChozgfaBK0zwtNj .node ellipse,#mermaid-svg-BChozgfaBK0zwtNj .node polygon,#mermaid-svg-BChozgfaBK0zwtNj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BChozgfaBK0zwtNj .rough-node .label text,#mermaid-svg-BChozgfaBK0zwtNj .node .label text,#mermaid-svg-BChozgfaBK0zwtNj .image-shape .label,#mermaid-svg-BChozgfaBK0zwtNj .icon-shape .label{text-anchor:middle;}#mermaid-svg-BChozgfaBK0zwtNj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BChozgfaBK0zwtNj .rough-node .label,#mermaid-svg-BChozgfaBK0zwtNj .node .label,#mermaid-svg-BChozgfaBK0zwtNj .image-shape .label,#mermaid-svg-BChozgfaBK0zwtNj .icon-shape .label{text-align:center;}#mermaid-svg-BChozgfaBK0zwtNj .node.clickable{cursor:pointer;}#mermaid-svg-BChozgfaBK0zwtNj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BChozgfaBK0zwtNj .arrowheadPath{fill:#333333;}#mermaid-svg-BChozgfaBK0zwtNj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BChozgfaBK0zwtNj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BChozgfaBK0zwtNj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BChozgfaBK0zwtNj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BChozgfaBK0zwtNj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BChozgfaBK0zwtNj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BChozgfaBK0zwtNj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BChozgfaBK0zwtNj .cluster text{fill:#333;}#mermaid-svg-BChozgfaBK0zwtNj .cluster span{color:#333;}#mermaid-svg-BChozgfaBK0zwtNj 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-BChozgfaBK0zwtNj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BChozgfaBK0zwtNj rect.text{fill:none;stroke-width:0;}#mermaid-svg-BChozgfaBK0zwtNj .icon-shape,#mermaid-svg-BChozgfaBK0zwtNj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BChozgfaBK0zwtNj .icon-shape p,#mermaid-svg-BChozgfaBK0zwtNj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BChozgfaBK0zwtNj .icon-shape .label rect,#mermaid-svg-BChozgfaBK0zwtNj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BChozgfaBK0zwtNj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BChozgfaBK0zwtNj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BChozgfaBK0zwtNj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 新镜像构建
Staging :latest
快速验证
验证通过
Production 固定 Tag
可追踪、可回滚
Staging 的目标是快速获得最新构建;生产的目标是可复现。如果生产也使用 latest,同一个 YAML 在不同时间可能启动不同代码,事故调查和回滚会很困难。反过来,如果 Staging 每次都人工改固定 Tag,反馈速度会下降。
Dashboard 目前也使用 latest,更方便快速更新,但从生产可复现性角度看,固定 Tag 通常更稳妥。
十一、实际部署怎么做
基础安装脚本 install.ps1 当前只负责:
#mermaid-svg-DiR31u4AscMSzivh{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-DiR31u4AscMSzivh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DiR31u4AscMSzivh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DiR31u4AscMSzivh .error-icon{fill:#552222;}#mermaid-svg-DiR31u4AscMSzivh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DiR31u4AscMSzivh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DiR31u4AscMSzivh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DiR31u4AscMSzivh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DiR31u4AscMSzivh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DiR31u4AscMSzivh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DiR31u4AscMSzivh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DiR31u4AscMSzivh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DiR31u4AscMSzivh .marker.cross{stroke:#333333;}#mermaid-svg-DiR31u4AscMSzivh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DiR31u4AscMSzivh p{margin:0;}#mermaid-svg-DiR31u4AscMSzivh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DiR31u4AscMSzivh .cluster-label text{fill:#333;}#mermaid-svg-DiR31u4AscMSzivh .cluster-label span{color:#333;}#mermaid-svg-DiR31u4AscMSzivh .cluster-label span p{background-color:transparent;}#mermaid-svg-DiR31u4AscMSzivh .label text,#mermaid-svg-DiR31u4AscMSzivh span{fill:#333;color:#333;}#mermaid-svg-DiR31u4AscMSzivh .node rect,#mermaid-svg-DiR31u4AscMSzivh .node circle,#mermaid-svg-DiR31u4AscMSzivh .node ellipse,#mermaid-svg-DiR31u4AscMSzivh .node polygon,#mermaid-svg-DiR31u4AscMSzivh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DiR31u4AscMSzivh .rough-node .label text,#mermaid-svg-DiR31u4AscMSzivh .node .label text,#mermaid-svg-DiR31u4AscMSzivh .image-shape .label,#mermaid-svg-DiR31u4AscMSzivh .icon-shape .label{text-anchor:middle;}#mermaid-svg-DiR31u4AscMSzivh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DiR31u4AscMSzivh .rough-node .label,#mermaid-svg-DiR31u4AscMSzivh .node .label,#mermaid-svg-DiR31u4AscMSzivh .image-shape .label,#mermaid-svg-DiR31u4AscMSzivh .icon-shape .label{text-align:center;}#mermaid-svg-DiR31u4AscMSzivh .node.clickable{cursor:pointer;}#mermaid-svg-DiR31u4AscMSzivh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DiR31u4AscMSzivh .arrowheadPath{fill:#333333;}#mermaid-svg-DiR31u4AscMSzivh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DiR31u4AscMSzivh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DiR31u4AscMSzivh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DiR31u4AscMSzivh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DiR31u4AscMSzivh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DiR31u4AscMSzivh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DiR31u4AscMSzivh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DiR31u4AscMSzivh .cluster text{fill:#333;}#mermaid-svg-DiR31u4AscMSzivh .cluster span{color:#333;}#mermaid-svg-DiR31u4AscMSzivh 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-DiR31u4AscMSzivh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DiR31u4AscMSzivh rect.text{fill:none;stroke-width:0;}#mermaid-svg-DiR31u4AscMSzivh .icon-shape,#mermaid-svg-DiR31u4AscMSzivh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DiR31u4AscMSzivh .icon-shape p,#mermaid-svg-DiR31u4AscMSzivh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DiR31u4AscMSzivh .icon-shape .label rect,#mermaid-svg-DiR31u4AscMSzivh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DiR31u4AscMSzivh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DiR31u4AscMSzivh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DiR31u4AscMSzivh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建基础 Namespace
安装 ACR Secret
安装 Kubed
它并不是完整的一键部署。Copilot2API 需要另外运行 install.ps1,Dashboard 需要分别应用 RBAC、Deployment、Service 和 Ingress;RunnerManager 的主要清单则位于 k8s。
典型顺序是:
- 使用
kubectl apply创建生产与 Staging Namespace。 - 创建 ACR Secret,再安装 Kubed 进行同步。
- 部署 RunnerManager 的 ConfigMap、Secret、RBAC、Deployment、Service 和 HPA。
- 部署 Copilot2API 的 StorageClass、PVC、凭据、Deployment 和 Service。
- 配置账号池和 LLM 路由。
- 部署 Dashboard 的 RBAC、Deployment、Service 和 Ingress。
- 使用
kubectl get pods -A、事件、探针和 Dashboard 验证状态。
这里有两个实际注意点:顶层 README 仍写着旧路径 copilot2api/install.ps1,现在对应目录是 llm-gateway;另外基础 namespaces.yaml 没有声明 llm-proxy-staging,但 Staging Gateway 安装脚本默认使用它。因此部署前需要确认目标集群是否已由其他流程创建该 Namespace,不能把顶层脚本理解成完整环境初始化器。
十二、最终心智模型
#mermaid-svg-LJrQptbQf2t9m1Ia{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-LJrQptbQf2t9m1Ia .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LJrQptbQf2t9m1Ia .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LJrQptbQf2t9m1Ia .error-icon{fill:#552222;}#mermaid-svg-LJrQptbQf2t9m1Ia .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LJrQptbQf2t9m1Ia .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LJrQptbQf2t9m1Ia .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LJrQptbQf2t9m1Ia .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LJrQptbQf2t9m1Ia .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LJrQptbQf2t9m1Ia .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LJrQptbQf2t9m1Ia .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LJrQptbQf2t9m1Ia .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LJrQptbQf2t9m1Ia .marker.cross{stroke:#333333;}#mermaid-svg-LJrQptbQf2t9m1Ia svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LJrQptbQf2t9m1Ia p{margin:0;}#mermaid-svg-LJrQptbQf2t9m1Ia .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LJrQptbQf2t9m1Ia .cluster-label text{fill:#333;}#mermaid-svg-LJrQptbQf2t9m1Ia .cluster-label span{color:#333;}#mermaid-svg-LJrQptbQf2t9m1Ia .cluster-label span p{background-color:transparent;}#mermaid-svg-LJrQptbQf2t9m1Ia .label text,#mermaid-svg-LJrQptbQf2t9m1Ia span{fill:#333;color:#333;}#mermaid-svg-LJrQptbQf2t9m1Ia .node rect,#mermaid-svg-LJrQptbQf2t9m1Ia .node circle,#mermaid-svg-LJrQptbQf2t9m1Ia .node ellipse,#mermaid-svg-LJrQptbQf2t9m1Ia .node polygon,#mermaid-svg-LJrQptbQf2t9m1Ia .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LJrQptbQf2t9m1Ia .rough-node .label text,#mermaid-svg-LJrQptbQf2t9m1Ia .node .label text,#mermaid-svg-LJrQptbQf2t9m1Ia .image-shape .label,#mermaid-svg-LJrQptbQf2t9m1Ia .icon-shape .label{text-anchor:middle;}#mermaid-svg-LJrQptbQf2t9m1Ia .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LJrQptbQf2t9m1Ia .rough-node .label,#mermaid-svg-LJrQptbQf2t9m1Ia .node .label,#mermaid-svg-LJrQptbQf2t9m1Ia .image-shape .label,#mermaid-svg-LJrQptbQf2t9m1Ia .icon-shape .label{text-align:center;}#mermaid-svg-LJrQptbQf2t9m1Ia .node.clickable{cursor:pointer;}#mermaid-svg-LJrQptbQf2t9m1Ia .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LJrQptbQf2t9m1Ia .arrowheadPath{fill:#333333;}#mermaid-svg-LJrQptbQf2t9m1Ia .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LJrQptbQf2t9m1Ia .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LJrQptbQf2t9m1Ia .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LJrQptbQf2t9m1Ia .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LJrQptbQf2t9m1Ia .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LJrQptbQf2t9m1Ia .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LJrQptbQf2t9m1Ia .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LJrQptbQf2t9m1Ia .cluster text{fill:#333;}#mermaid-svg-LJrQptbQf2t9m1Ia .cluster span{color:#333;}#mermaid-svg-LJrQptbQf2t9m1Ia 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-LJrQptbQf2t9m1Ia .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LJrQptbQf2t9m1Ia rect.text{fill:none;stroke-width:0;}#mermaid-svg-LJrQptbQf2t9m1Ia .icon-shape,#mermaid-svg-LJrQptbQf2t9m1Ia .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LJrQptbQf2t9m1Ia .icon-shape p,#mermaid-svg-LJrQptbQf2t9m1Ia .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LJrQptbQf2t9m1Ia .icon-shape .label rect,#mermaid-svg-LJrQptbQf2t9m1Ia .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LJrQptbQf2t9m1Ia .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LJrQptbQf2t9m1Ia .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LJrQptbQf2t9m1Ia :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} AKS
容器运行与调度平台
RunnerManager
控制任务生命周期
Runner Pods
执行实际编码任务
LLM Gateway
统一模型访问
Dashboard
观察和有限运维
Kubed / PVC / RBAC
基础设施能力
可以把整个设计记成:
- **RunnerManager 是调度员,Runner Pod 是临时工位,LLM Gateway 是统一模型入口,Dashboard 是控制室,Kubed 和 Azure Disk 是后勤系统
- AKS 是让这些角色能够安全、动态、可恢复地协同工作的运行平台。**
它不比 VM 天然"更好",而是更适合de 当前这种大量动态 Runner、生产与 Staging 隔离、多种模型路由以及持续运维观察的工作负载。
代价则是 YAML、RBAC、网络、存储、镜像和集群升级都需要更专业的管理。