menu

Kubernetes 知识

  • date_range 23/01/2023 12:12
    点击量:
    info
    sort
    CNCF
    label
    aPAAS
    iPAAS
    IaaS
    SaaS
    CNCF

// 所有 Operator 的核心:Reconcile 函数 // “期望状态 vs 实际状态 → 执行动作”

你的 Elevate-SaaS 项目中的 SPI 插件扩展机制:

Java SPI = 应用层的扩展机制(加载 .jar 插件) K8s CRD = 平台层的扩展机制(加载新资源类型)

面试可以类比: “SPI 让 Java 应用可以动态加载插件, CRD 让 K8s 平台可以动态扩展 API。 我们在 PaaS 层用 CRD 定义了 TenantConfig 资源, Operator 自动根据租户配置创建对应的 namespace、 ResourceQuota、NetworkPolicy, 实现了租户 onboard 自动化。”

“RBAC 和 OPA 是互补的——RBAC 控制’谁能操作什么资源’,OPA 控制’操作的内容是否合规’。 比如开发者有权创建 Deployment(RBAC 允许),但 OPA 会检查这个 Deployment 是否设置了资源限制、是否使用了 latest 标签(策略合规)。”

ConfigMap = 明文配置(数据库地址、端口号、功能开关) Secret = 加密配置(密码、Token、证书)

Elevate-SaaS 多租户隔离四层模型:

第1层:Namespace 隔离(资源边界) → 每个租户一个 namespace

第2层:RBAC 隔离(权限边界) → 租户只能访问自己的 namespace

第3层:NetworkPolicy / Kube-OVN VPC 隔离(网络边界) → 租户之间网络不通

第4层:ResourceQuota 隔离(资源边界) → 每个租户限制 CPU/内存/存储上限

PVC = 租户说”我要一块 50G 的硬盘”(申请) PV = 实际提供的硬盘(Longhorn 自动创建) SC = StorageClass,定义用什么存储后端(Longhorn/Ceph/EBS)

PVC → 找匹配的 SC → SC 调用 CSI → CSI 让 Longhorn 创建实际的卷 → 绑定为 PV 用户请求 ↓ Ingress/Gateway(Emissary)→ 外部流量入口 ↓ Service(ClusterIP/NodePort)→ 服务发现 + 负载均衡 ↓ Deployment / StatefulSet / DaemonSet → 管理 Pod 生命周期 ↓ Pod(容器 + Sidecar)→ 跑你的代码 ↓ ConfigMap(配置)+ Secret(密码)→ 注入环境变量 ↓ PVC/PV(Longhorn)→ 持久化存储 ↓ Namespace → 以上所有资源的隔离边界 ↓ RBAC → 谁能操作这些资源 ↓ CRD + Operator → 扩展以上所有(VirtualMachine、Vpc…)

Multus 是什么 Kubernetes 默认每个 Pod(或 KubeVirt 的 VMI)只有一张网卡(eth0),由集群的主 CNI(比如 Calico、Flannel)管理。但 VNF 天然需要多张网卡——管理口、WAN 口、LAN 口各一张。 Multus 就是一个”CNI 多路复用器”,它本身不做网络,而是让你在主 CNI 之外,再给 Pod/VM 额外挂多张网卡,每张网卡可以用不同的网络插件。 用一个生活类比:主 CNI 像每个房间标配的一个网口,Multus 就是一个多口交换机,让你在这个房间里再接几根额外的网线,每根线还可以来自不同的运营商。 工作流程大致是这样的:

先定义 NetworkAttachmentDefinition(NAD)这个 CRD,描述额外网卡用什么插件、连哪个网段 在 Pod/VMI 的 annotation 里引用这些 NAD Multus 在 Pod 创建时依次调用各个 CNI 插件,把网卡都挂上

OVN/OVS 能不能实现服务链串接 先说结论:能,但不是开箱即用,需要做流表编排或借助 OVN 的逻辑路由/交换能力。 OVS(Open vSwitch)是什么 OVS 是一个软件交换机,跑在每个节点上,所有 VM/Pod 的虚拟网卡都接在它上面。它的核心能力是可编程的流表——你可以精确定义”从哪个端口进来的包、匹配什么特征、送到哪个端口去”。 OVN 是什么 OVN 是 OVS 之上的一层逻辑网络抽象,提供逻辑交换机、逻辑路由器、ACL、NAT 等概念,然后自动编译成底层 OVS 流表。相当于 OVS 是数据面引擎,OVN 是控制面大脑。 怎么串成 vRouter → vFirewall → vLB 有两种思路: 思路一:OVS 流表手动编排(底层但精确)

伪流表示意

用户流量进来 → 转给 vRouter 的 port

table=0, in_port=外部入口, actions=output:vRouter_port

vRouter 处理完出来 → 转给 vFirewall

table=0, in_port=vRouter_out, actions=output:vFirewall_port

vFirewall 处理完 → 转给 vLB

table=0, in_port=vFirewall_out, actions=output:vLB_port

vLB 处理完 → 转给后端服务

table=0, in_port=vLB_out, actions=output:backend_port 本质就是用流表强制改变包的转发路径,让流量按你定义的顺序经过每个 VNF。 思路二:OVN 逻辑拓扑编排(更高层抽象) 用 OVN 创建多个逻辑交换机,每两个 VNF 之间用一个独立的逻辑网段连接: 用户 ──▶ [LS-1] ──▶ vRouter ──▶ [LS-2] ──▶ vFirewall ──▶ [LS-3] ──▶ vLB ──▶ [LS-4] ──▶ 后端 每个 VNF 有两张网卡,分别接入前后两个逻辑交换机,流量自然就按拓扑顺序流过去了。OVN 会自动把这个逻辑拓扑编译成底层的 OVS 流表,不用你手写。 和你之前做的 SDN 工作的关联 这其实跟你在紫金山实验室做的 SDN 控制面是同一套思路——通过集中控制器(OVN Northd 相当于一个轻量 SDN Controller)下发转发规则到数据面(OVS)。区别在于 OpenStack Neutron + SFC 插件把这套流程产品化了,有标准的 Port Chain API;而在纯 Kubernetes + KubeVirt 环境下,目前还没有同等成熟度的 SFC 标准,需要自己用 OVN 逻辑拓扑或 OVS 流表来实现。

“我是石洋洋,9年后端/平台架构经验。核心项目有三个: 第一个是 Elevate-SaaS 多租户 PaaS 平台,服务40+行业租户,基于 K8s + Dapr + NocoBase 构建元数据驱动的 aPaaS,实现了租户定制交付从3个月压缩到1天。 第二个是紫金山实验室的网络云融合平台,基于 SRv6/DetNet 技术的 SDN 控制面开发,实现了确定性网络与云原生架构的融合。 第三个是正在做的 AskOS 企业知识平台,基于 RAG+Agent 架构,多租户知识库管理。 技术栈方面,我对 K8s 生态有完整的实操经验——从裸机搭建 HA 集群、CNCF 全栈组件部署,到 Karmada 多云纳管、KubeVirt 虚拟化、Kube-OVN 网络,全部手操安装调试过。”

Saga 分布式事务编排 先理解问题:为什么需要 Saga 单体应用时代(一个数据库):

@Transactional public void createOrder() { orderDao.insert(order); // 写订单表 paymentDao.deduct(amount); // 扣款 inventoryDao.reduce(sku); // 减库存 logisticsDao.create(ship); // 创建物流 } // 任何一步失败 → 数据库自动全部回滚 // 简单,因为都在一个数据库事务里

微服务时代(每个服务自己的数据库):

订单服务 → 订单数据库 支付服务 → 支付数据库 库存服务 → 库存数据库 物流服务 → 物流数据库

4 个数据库,没法用一个事务包住 订单创建成功了,支付也成功了 但库存扣减失败了 → 怎么办? → 订单和支付要回滚! → 但它们在不同的数据库里,没法自动回滚! Saga 模式 Saga = 每一步都有对应的”补偿动作” 失败时按反向顺序逐个补偿

正向流程(每步成功就继续): ① 创建订单 → 成功 ② 扣款 → 成功 ③ 减库存 → 失败!

反向补偿(从失败点往回退): ③ 库存不用补偿(本来就没减成功) ② 退款(补偿扣款) ① 取消订单(补偿创建订单)

最终:所有操作都撤销,数据一致 类比 没有 Saga: 你订了机票、酒店、景点门票 景点门票没买到 但机票和酒店已经付款了 → 你得自己手动退机票、退酒店 → 万一忘了就亏钱了

有了 Saga: 你订了机票 ✅ → 订了酒店 ✅ → 买门票 ❌ 失败 → 自动退酒店 → 自动退机票 → 全部撤销,不用你操心 为什么用 Argo Workflows 自己写 Saga(Java 代码里硬编码): if (paymentFailed) { orderService.cancel(orderId); } → 补偿逻辑散落在各个服务代码里 → 难以维护、难以追踪、容易遗漏

用 Argo Workflows: 把 Saga 流程定义成一个 YAML 工作流 每个步骤是一个容器 成功/失败/补偿全部声明式定义 Argo 自动执行正向流程和反向补偿 → 流程可视化、可追踪、可重试

执行流程 场景1:全部成功 ✅

用户下单 → 触发 Argo Workflow

① 创建订单 → 200 OK,status=CREATED ✅ ② 扣款 ¥15999 → 200 OK,status=SUCCESS ✅ ③ 减库存 2台 → 200 OK,status=SUCCESS ✅ ④ 创建物流 → 200 OK,status=CREATED ✅

Workflow 状态:Succeeded 数据库最终状态: 订单:CREATED 账户:余额 -15999 库存:stock -2 物流:已创建

═══════════════════════════════════════════════

场景2:第3步库存不足 ❌

用户下单 → 触发 Argo Workflow

① 创建订单 → 200 OK,status=CREATED ✅ ② 扣款 ¥15999 → 200 OK,status=SUCCESS ✅ ③ 减库存 2台 → 200 OK,status=INSUFFICIENT_STOCK ❌ → exit 1 → Argo 检测到失败 → 触发反向补偿链

补偿开始(反向顺序): ③ 库存不用补偿(本来就没减成功) ② 退款 ¥15999 → 200 OK,status=REFUNDED ✅ ① 取消订单 → 200 OK,status=CANCELLED ✅

Workflow 状态:Failed(但数据已补偿) 数据库最终状态: 订单:CANCELLED(补偿回来了) 账户:余额恢复(退款了) 库存:不变(本来就没减) 物流:没创建(没执行到)

用户看到:下单失败,库存不足,钱已退回

═══════════════════════════════════════════════

场景3:第4步物流创建失败 ❌

① 创建订单 ✅ ② 扣款 ✅ ③ 减库存 ✅ ④ 创建物流 ❌(物流系统宕机)

补偿: ④ 物流不用补偿(没创建成功) ③ 恢复库存 +2 ✅ ② 退款 ¥15999 ✅ ① 取消订单 ✅

最终:所有操作回滚,数据一致 Argo Workflows 界面上看到的 Argo UI(http://10.10.10.121:30800):

全部成功时: ┌──────────────────────────────────────────┐ │ order-saga Succeeded │ │ │ │ ┌────────────┐ │ │ │create-order│ ✅ │ │ └─────┬──────┘ │ │ ↓ │ │ ┌────────────┐ │ │ │ payment │ ✅ │ │ └─────┬──────┘ │ │ ↓ │ │ ┌────────────┐ │ │ │ inventory │ ✅ │ │ └─────┬──────┘ │ │ ↓ │ │ ┌────────────┐ │ │ │ shipment │ ✅ │ │ └────────────┘ │ └──────────────────────────────────────────┘

库存不足失败时: ┌──────────────────────────────────────────┐ │ order-saga Failed │ │ │ │ ┌────────────┐ ┌──────────────────┐ │ │ │create-order│ ✅│compensate-order │ ✅ │ │ └─────┬──────┘ └──────────────────┘ │ │ ↓ │ │ ┌────────────┐ ┌──────────────────┐ │ │ │ payment │ ✅│compensate-payment│ ✅ │ │ └─────┬──────┘ └──────────────────┘ │ │ ↓ │ │ ┌────────────┐ │ │ │ inventory │ ❌ INSUFFICIENT_STOCK │ │ └────────────┘ │ │ │ │ 补偿链自动执行 ✅ │ └──────────────────────────────────────────┘

每个步骤可以点进去看日志 补偿是否成功一目了然 和传统方式对比 传统方式(Java 代码硬编码补偿):

public void createOrder(OrderRequest req) { try { orderService.create(req); try { paymentService.pay(req); try { inventoryService.reduce(req); try { logisticsService.create(req); } catch (Exception e) { inventoryService.restore(req); // 补偿3 paymentService.refund(req); // 补偿2 orderService.cancel(req); // 补偿1 throw e; } } catch (Exception e) { paymentService.refund(req); // 补偿2 orderService.cancel(req); // 补偿1 throw e; } } catch (Exception e) { orderService.cancel(req); // 补偿1 throw e; } } catch (Exception e) { throw new OrderFailedException(e); } }

// 问题: // ❌ 嵌套 try-catch 地狱 // ❌ 补偿逻辑和业务逻辑耦合 // ❌ 补偿失败了怎么办?没有重试机制 // ❌ 看不到执行状态,排查困难 // ❌ 新增一步要改大量代码

Argo Workflows 方式: // ✅ YAML 声明式,每步独立容器 // ✅ 补偿逻辑和业务逻辑分离 // ✅ Argo 自动重试补偿(可配置重试次数) // ✅ UI 可视化每步状态 // ✅ 新增一步只加一段 YAML 面试话术 “我们用 Argo Workflows 实现了 Saga 分布式事务编排。传统方式把补偿逻辑硬编码在 Java 嵌套 try-catch 里,耦合度高且无法追踪。我们的方案是把 Saga 流程定义为 Argo Workflow YAML——每个业务步骤(创建订单、扣款、减库存、创建物流)是一个独立容器,每个步骤通过 onExit 关联对应的补偿容器(取消订单、退款、恢复库存、取消物流)。Argo 自动管理执行顺序,任一步骤失败自动触发反向补偿链。配合 Argo UI 可以可视化看到每一步的执行状态和补偿结果,MTTD 从原来的人工排查 30 分钟降到页面上一眼就能看到。整个 Saga 流程对微服务代码无侵入——每个服务只需要暴露正向 API 和补偿 API,编排逻辑完全由 Argo Workflow YAML 管理。”

“Argo Workflows 支持 DAG 和 Steps 两种编排模式。我们的 Saga 事务用 DAG 模式——通过 dependencies 声明步骤间的依赖关系,Argo 自动分析依赖图,没有依赖的步骤并行执行,有依赖的等前置完成。相比 Steps 串行模式,DAG 在复杂订单场景(风控+验证+支付+库存+优惠券+积分)中并行度更高,端到端耗时缩短 40%。”


评论:


技术文章推送

手机、电脑实用软件分享

微信搜索公众号: AndrewYG的算法世界
wechat 微信公众号:AndrewYG的算法世界

热门文章