想象你在城市最繁华的写字楼一层开了一家“智能餐厅”。餐厅很聪明:客流少的时候,后厨和服务员都回家休息,大门虚掩,只留一盏小灯;一旦有客人推门,门铃一响,厨师几分钟内赶回来点火开灶。客人多的时候,餐厅自动从隔壁劳务公司紧急调来更多服务员,高峰过去再让他们离开。而招牌、菜单配方、排班制度,始终保存在办公室里——不会因为打烊而消失。 这就是Knative Serving在Kubernetes(以下简称K8s)上做的事情。K8s好比一座设施齐全的综合商场,提供了水电、消防、安保(容器调度、资源管理),但商场不会帮每家店铺按客流自动调配人手——这是餐厅自己的经营智慧。Knative Serving就是这套自动经营系统:它让服务“按请求营业”,没请求时缩容到零,有请求时从零快速拉起,还能像上新菜一样对流量做灰度切分。对AI从业者来说,这就意味着可以为模型推理、批量任务构建一个按量付费、自动伸缩的Serverless运行时,把资源花在刀刃上。
掌握Knative Serving,你就能为AI模型推理和业务服务搭建“按请求营业”的弹性平台,从零到N自动伸缩、流量灰度发布、缩容到零省成本——这是云原生时代AI平台工程师的必备技能。
可视化演示
演示Knative Serving在K8s上从零到N的Pod自动伸缩、流量突发响应与新旧版本流量切分的灰度发布过程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
Knative Serving伸缩 缩容到零 流量突发 自动扩容 流量切分 从零到N弹性伸缩
Knative架构概览
商场里的店铺各有各的算盘。有些店雇了十个店员,但一天只有两三波客人,店员闲得刷手机——这是传统的常驻服务器,资源利用率低得可怜。K8s这个商场只管提供场地和基础水电,不会替店铺思考“什么时候该上几个人”。Knative就是那套让店铺自己聪明起来的经营系统,它让你不再为闲置的店员付工资。
Knative运行在K8s之上,由两个模块组成:Serving负责“按请求营业”——客来了开灶、客走了打烊,适合在线API和模型推理;Eventing负责“按事件开张”——商场广播一响(比如定时任务、消息队列来了消息),才临时开店处理,适合事件驱动的批量任务。用公式表示,就是两者的功能并集:
在Knative内部,Serving模块又分控制面和数据面。控制面是餐厅的“管理办公室”——Controller组件像值班经理,时刻盯着K8s里的资源状态,发现实际与预期不符就立刻协调修正(K8s把这套机制叫协调循环);Webhook像前台文员,负责校验你提交的经营方案(配置)是否合法,并补上默认值。数据面则是“一线员工”——Activator是门口的门铃兼临时接待,Queue Proxy是站在每个服务员身后的计时器,负责统计这位服务员正在同时服务几桌客人。
如果说传统常驻服务是“请了一整队店员坐等生意”,那Knative就是按客流动态排班的智慧餐厅:生意好时全员上阵,生意差时关门歇业。这套模式的本质,是把过去常年闲置的资源利用率,从“空转”拉向“满载”。
- Serving 表示请求驱动模块客人主动推门点菜(发HTTP请求),餐厅才安排接待。对应在线推理、Web API等场景。
- Eventing 表示事件驱动模块商场广播通知“备菜大赛开始”(外部事件触发),餐厅才响应开工。对应定时批处理、消息队列消费等任务。
- ∪ 表示两者能力并集将两类能力组合在一起,形成完整的Serverless平台。
核心对象模型
餐厅办公室白板上写着四个角色的分工。Service(服务)是挂在大门上的那块招牌——客人(调用方)只需要记住这一个入口,不需要知道后厨怎么运作。Configuration(配置)是那本总菜谱,记录了菜品(镜像)、做法(环境变量)、分量(资源限制)。Route(路由)是站在门口的门迎,负责告诉客人“今天该坐哪一桌”。而每当你更新一次菜谱(比如把辣椒从二两改成三两),后厨就会把新旧做法各拍一张“做法快照”,这张快照就叫Revision(修订版本)。
这四个对象的关系,可以浓缩成一条管理链:
Revision是一个只读的“历史菜单册”。线上每一版代码、每一个环境变量组合,都被冻结成一个不可变的快照。这样做的好处是:想回滚就回滚,想对比新旧版本的线上表现也随时可以——因为每个版本都保留了当时完整的“做菜记录”。实际使用中,用户写好一个Knative Service的YAML文件提交给K8s,Knative的Controller就会自动编排好这套对象关系。餐厅挂上招牌(Service),备好菜谱(Configuration),门迎认路(Route),每版做法留档(Revision)——四个角色各就各位,一家店就能自动运转了。
- Service 表示服务的统一入口用户部署服务时只需创建一个Service对象,就像客人进餐厅只认招牌,不需要知道后厨细节。
- Route 表示流量路由规则Service自动创建一个Route,它知道当前所有可用Revision的地址,并按权重把请求分发过去。
- Configuration 表示期望配置模板Service也自动创建一个Configuration,它是“总菜谱”,任何一次修改都会触发新快照的生成。
- Revision 表示不可变版本快照每次Configuration变更,Knative都会为当时的“菜谱+原料”生成一个不可变的Revision。它一旦创建就不能再改,只能在上面做伸缩和流量分发。
自动扩缩容
餐厅的大堂经理最关心一个问题:现在排队的有多少人,我应该安排几个服务员?他不能凭感觉拍脑袋,得靠数据说话。Knative里每个Pod旁边都站着一个“计时员”——Queue Proxy容器。它默默数着当前这个Pod正在同时处理多少请求(并发数),并定期把数字报给中央调度台——Autoscaler。
大堂经理的计算逻辑并不复杂:用当前的总并发数,除以一个服务员最多能同时服务的桌数,向上取整,就是需要的人手。Knative里,期望副本数的计算正是如此:
其中R是最近时间窗口内观测到的平均并发请求数,C是每个Pod允许同时处理的请求上限(由containerConcurrency参数配置),P就是Autoscaler算出的期望Pod副本数。
不过大堂经理不会每分钟都在疯狂调人。Knative设计了两种调度模式:稳定模式(Stable)下,每60秒评估一次,缓慢调整副本数,避免“多一个少一个”来回抖;恐慌模式(Panic)下,如果流量在几秒钟内暴涨到稳定窗口平均值的两倍,调度台立刻进入“紧急状态”,按观测到的最大值快速扩容,先把客人接住再说。当然,人手也不是无限制的——minReplicas和maxReplicas字段像餐厅的“最低排班数”和“最大工位上限”,把副本数约束在合理区间内。大堂经理看数据算人手,高峰加人、低谷减人,这套逻辑就是Knative自动扩缩容的全部秘密。
- R 表示平均并发请求数R是Queue Proxy在最近观测窗口内汇总的平均并发量,相当于餐厅门口队伍的平均长度。窗口默认看60秒的数据,避免偶发抖动干扰判断。
- C 表示单Pod并发上限C是每个Pod同时能处理的请求数上限,由
containerConcurrency字段指定。它相当于一个服务员最多能同时服务几桌客人——定得太小浪费人手,定得太大容易手忙脚乱。 - ⌈⌉ 表示向上取整只要有除不尽的零头,也要多算一个Pod来兜底。就像4.2桌客人的租也要安排5个服务员。
- P 表示期望副本数P是当前流量下需要的最少Pod数量。Autoscaler算出P后,会去调整底层Deployment的副本数,让实际Pod数量向P靠拢。
缩容到零
晚上十点,客流彻底断了。大堂经理盯着计时器记录:连续60秒,一个客人都没有。于是他拿起对讲机:“后厨下班,服务员回家,大门上锁。”这就是Knative最招牌的能力——缩容到零。需要强调的是,打烊不等于关店:招牌(Service)、菜谱(Configuration)、门迎路线(Route)都还在办公室的文件柜里,只是所有正在跑的业务Pod被回收了。
打烊的触发条件用公式表达就是:
意思是在稳定窗口Δ t内,平均并发请求数持续低于一个极小阈值ε(通常视为小于1),Autoscaler就把期望副本数设为0。
那客人半夜来敲门怎么办?这时Activator(门铃兼临时接待)就派上用场了。打烊期间,所有到达的请求都不会直接404,而是被Activator稳稳接住——它一边把请求暂时挂起,一边立刻通知K8s“来客人了,开门营业!”厨房从零开始忙活:拉取镜像、启动容器、等待就绪探针通过,通常需要几秒到十几秒。等到新Pod一切就绪,Activator才把挂起的请求转交过去。
从客人推门到第一口菜上桌的时间,就是冷启动延迟。这是缩容到零的唯一代价。聪明的餐厅会想尽办法缩短这个时间:后厨提前备好半成品菜(镜像预热)、把招牌菜做成预制菜(优化镜像启动)、甚至留一个值班厨师(minReplicas=1)——这些调优手段我们后面会细讲。总而言之,打烊省下了整夜的房租水电,代价只是客人进门后需要多等一会儿——这正是Serverless“用延迟换成本”的核心取舍。
- P → 0 表示副本数收敛到零P是期望Pod副本数,当它收敛到0时,Knative会把所有业务Pod全部删除,只保留声明配置。
- $\overline{R}_{\Delta t}$ 表示窗口内平均并发横杠表示取平均,Δ t是稳定窗口(默认60秒)。只有窗口内请求一直极少,才会认为“确实没生意了”。
- ε 表示低流量阈值ε是一个趋近于0的极小值,代表“几乎没有任何进行中的请求”。数学上常用ε表示任意小的正数。
- ⟺ 表示充要条件左边成立当且仅当右边成立。只有当低流量条件持续满足时,系统才会缩容到零,避免误伤突然的短流量。
流量切分与灰度发布
餐厅研发了一道新菜:把宫保鸡丁的花生换成夏威夷果。老板不敢直接全员换菜单,万一客人不爱吃呢?于是他想了个办法:新菜先小规模试吃——今天每10桌客人里,有2桌能点到新菜,剩下8桌还是老味道。观察几天,如果好评如潮,就把比例逐步调高,最终全量换新;如果差评一片,立刻把比例调回0。这套玩法在Knative里叫流量切分,由Route对象按权重把请求分发给不同的Revision。
权重的数学表示非常直观:
其中n是参与流量的Revision数量,w_i是第i个Revision获得的流量权重。
基于这套权重机制,Knative支持两种经典发布模式。金丝雀发布(Canary):新版本先获得5%~10%的流量,像一个“试验田”,监控它的错误率和延迟,确认稳定后再逐步提高权重到50%、100%。蓝绿发布(Blue/Green):更简单粗暴——旧版本(蓝)和新版本(绿)同时部署好,Route的权重一次性从“蓝100%绿0%”切到“蓝0%绿100%”,切换干净利落,出问题时一键切回,回滚时间以秒计。
回滚策略也因此变得无比简单:不必重新修改代码、重新构建镜像,只要把Route的流量权重改回旧Revision即可。这就像老板发现新菜被吐槽“这是什么鬼”,立刻通知门迎“别带客去试吃桌了,全带回老座位”。Knative的Revision不可变特性,保证了被回滚的旧版本“老菜单”始终还在那里,随时候命。
- n 表示参与分流的Revision数量可以是1个(全量流量给一个版本),也可以是2个或更多(多版本并行)。一般灰度发布时是两个。
- w_i 表示第i个Revision的流量权重权重是0到1之间的小数,0表示不分配流量,1表示承接全部流量。比如新版本w=0.2,就是放20%的客流给它。
- 求和符号∑把所有参与分流的Revision权重加起来。权重的总和必须等于1,代表100%的流量都被有序分配,不会丢失也不会重复。
K8s生态集成
一家再聪明的餐厅,也不可能自己造商场。Knative同样如此——它站在K8s的肩膀上,大量复用K8s的公共设施。K8s提供的容器编排、节点调度、资源限制、健康探针、日志采集,Knative全部照单全收,自己只新增了“按需营业”这层智慧。双方的分工,就像商场负责中央空调、消防、安保,餐厅专心琢磨菜品和客流。
Knative与K8s生态的集成点,首先体现在API扩展上。Knative利用K8s的CRD(CustomResourceDefinition,自定义资源定义)机制,把Service、Route这些概念注册成K8s的“新物种”。你写的Knative YAML文件,本质上就是在向K8s申请“我要开一家新型智慧餐厅”。K8s收到申请后,由Knative的Controller接管后续的所有编排动作。其次,Knative的网络层是可插拔的——服务网格Istio是经典搭档,它负责商场内部的“客流传送带”(南北向入口网关)和“房间之间的小推车”(东西向Sidecar代理);如果你不想上Istio这么重的方案,也可以选择Kourier、Contour等轻量网络层,就像小店用不起商场中央物流,自己蹬个三轮车也能送菜。
一次请求从商场入口到后厨,链路延迟可以拆解为:
集成Istio还有一个额外收获:零信任安全。通过Istio的mTLS双向认证机制,餐厅内部服务员之间(Pod之间)的通信全部加密,即使有人混进商场也偷听不到传菜内容。Knative还支持从K8s生态里借用HPA(水平自动伸缩)来做CPU维度的兜底扩容,借用K8s的调度器帮Pod找到最合适的节点——就像借用商场的保洁、维修、安保团队。Knative没有重造轮子,它只是给K8s这栋大楼装了一套“全自动智慧经营系统”。
- T_ingress 表示入口网关处理时间请求先经过商场大门(K8s Ingress或Istio Gateway),由网关完成TLS终止、路由匹配等操作。
- T_mesh 表示服务网格转发时间如果启用了Istio等服务网格,请求还要经过Sidecar代理转发一次。这相当于商场传送带交接的耗时。
- T_pod 表示应用容器处理时间最终请求进入业务Pod,由你的代码真正处理。这部分是应用自身逻辑的耗时。
性能调优
餐厅经营一段时间后,老板开始琢磨:怎么让翻台率更高?服务员一次服务几桌客人最合适?Knative的性能调优,本质上就是回答这类问题。第一个旋钮是containerConcurrency(单Pod并发上限)。设得太小,比如10,每个Pod还没忙起来就喊加人,Pod数量虚高浪费资源;设得太大,比如500,单个Pod被请求压得喘不过气,延迟飙升甚至OOM。一般建议20~100之间,具体数值要靠压测对比“平均延迟”和“错误率”来定。
第二个旋钮是扩缩容窗口。stable window(稳定窗口)决定缩容的冷静期,默认60秒;如果你对波动很敏感,可以调小到30秒让缩容响应更快,但也要接受副本数抖动的风险。panic window(恐慌窗口)决定扩容的速度上限——流量突增时,KPA是否立刻全线出击。期望的Pod数量可以用目标利用率来衡量:
第三个大方向是冷启动优化。餐厅打烊后重新开灶,最快的方式是什么?答案是“半成品备菜”。对应到技术层面:缩小容器镜像体积(少装无用依赖,启动更快)、使用镜像预热和缓存(把镜像提前分发到节点上,省去拉取时间)、减少启动时的初始化工作(把耗时操作异步化)、以及设置合理的就绪探针(让Knative在Pod真正能接客后才放流量进来)。资源预留则是给重要客人留包间——用minReplicas保住最低副本数,用节点亲和性让Pod优先调度到内存充裕的机器上。负载预热也很关键:对冷门AI模型推理服务,可以定时发一些请求把模型权重“焐热”,避免第一个真实用户承受漫长的模型加载延迟。调优不是玄学,而是一步步测量、调整、再测量的工程循环。
- R_avg 表示平均请求数观测窗口内的平均并发请求量,是业务压力的真实体现。
- C 表示单Pod并发上限每个Pod允许同时处理的请求数,来自
containerConcurrency配置。 - P_target 表示目标副本数你期望保持的Pod数量,是调优时要设定的目标值。
- U_target 表示副本利用率用平均请求数除以“单Pod上限×目标副本数”,得到副本的使用率。调优的终极目标就是让U_target接近1——既不满载压垮Pod,也不闲置浪费。
监控与告警
再精明的老板也不能24小时站在大堂盯客流量。他需要一块仪表盘:翻台率多少、排队时长多少、差评率有没有超标。Knative的监控体系,就是给餐厅装上一整套数据仪表。第一个数据来源是每个Pod里的Queue Proxy——它不仅负责流量代理,还会暴露Prometheus格式的指标:当前并发数、每秒请求数(RPS)、请求延迟分布等。第二个来源是业务日志——Pod的标准输出被K8s收集后,可以汇入ElasticSearch或Loki等日志系统统一查询。
告警逻辑可以用一个简洁的阈值公式描述:
E_window是最近时间窗口内错误请求的数量,N_window是窗口内总请求数,θ是错误率阈值(比如0.05,即5%)。
实际落地时,团队通常会制定SLO(服务等级目标):比如“99.9%的请求在500ms内返回”。围绕SLO配置四个黄金指标:错误率、延迟(P50/P95分位数)、流量(QPS)和饱和度(Pod/并发利用率)。当SLO面临被打破的风险时,告警必须在客户感知之前发出。这就像餐厅老板给自己立下军令状:翻台率跌破红线前,我要先知道是哪道菜出了问题。有了这套监控告警体系,缩容到零、灰度发布、性能调优才有了判断依据——数据不会说谎。
- E_window 表示窗口内错误请求数5xx响应码、超时请求都属于错误请求。相当于统计这小时有几桌客人吃出了头发。
- N_window 表示窗口内总请求数窗口内进入餐厅的全部客流,无论体验好坏都算在内。
- θ 表示错误率阈值你定义的可接受上限。金融业务可能定0.01%,内部工具可以放宽到1%。它对应餐厅承诺的“食品安全合格率”。
- alert 表示触发告警当实际错误率超过阈值时,AlertManager就会向值班人员推送告警——相当于后厨的烟雾报警器响了。
AI 应用场景
AI模型在线推理的弹性服务
阶段:模型部署与在线推理
解决的问题:AI推理服务(如图像识别、文本生成)的调用量往往随时间剧烈波动——上班高峰拥挤,深夜几乎没流量。传统做法是常驻一批GPU Pod,低谷期大量空闲却照付费用。Knative Serving为推理服务加上“请求驱动”能力:高峰期自动扩容到几十个Pod扛住并发,低谷期缩容到零,费用随流量走。
具体案例:某内容平台部署了图像审核模型,平时调用量集中在每天20点到23点。使用Knative Serving后,白天几乎零Pod运行,晚高峰自动拉起30个副本,GPU成本下降约60%,单次冷启动约2~4秒,在可接受范围内。
事件驱动的AI批量推理任务
阶段:数据处理与批量推理
解决的问题:AI团队每天要对新产生的日志做情感分析,使用CronJob定时跑会固定占用资源。Knative Eventing的事件驱动能力,让数据到达事件触发推理Pod的启动,任务执行完自动缩容到零。
具体案例:某电商平台的评论数据通过消息队列不断到达,Knative Eventing订阅到新消息后触发Serving服务启动一个批处理Pod,对最近一批评论做情感分类,结果写回数据仓库,处理完Pod自动消失。整个系统只在有数据时才消耗算力。
新模型灰度验证与A/B实验
阶段:模型实验与上线
解决的问题:新模型的离线指标(如准确率)不能完全代表线上效果,直接全量上线风险高。Knative的流量切分能力让新老模型同时在线,新模型只接收5%的真实流量,验证线上指标后再逐步放量。
具体案例:某推荐系统团队上线新的排序模型,通过Route将5%流量切给新模型的Revision,对比新旧版本的点击率与延迟指标。观察2天确认新模型稳定后,将流量权重逐步提升到100%,旧模型保留随时回滚。
Python 演示
"""Knative Autoscaler 扩缩容决策模拟 本程序模拟 Knative Serving 中 Autoscaler 的核心逻辑:观察每秒并发请求数,按公式计算期望 Pod 副本数,并展示从"满载运行"到"缩容到零"的完整过程。"""import math class KnativeAutoscaler: def __init__(self, concurrency, min_replicas=0, max_replicas=10): self.concurrency = concurrency # 单 Pod 并发上限(C) self.min_replicas = min_replicas # 最低副本数下限 self.max_replicas = max_replicas # 最高副本数上限 self.replicas = min_replicas # 当前实际副本数 self.req_history = [] # 最近窗口的请求记录 self.scale_events = [] # 扩缩容事件列表 def observe(self, requests): # 记录最近 10 秒的请求数据,作为决策窗口 self.req_history.append(requests) if len(self.req_history) > 10: self.req_history.pop(0) def desired_replicas(self): # 期望副本数 = ceil(平均并发 / 单Pod并发上限) avg = sum(self.req_history) / len(self.req_history) desired = math.ceil(avg / self.concurrency) if avg > 0 else 0 return max(self.min_replicas, min(self.max_replicas, desired)) def reconcile(self): # 对比期望和当前,若不一致则执行扩缩容 target = self.desired_replicas() if target == self.replicas: return False self.scale_events.append((len(self.req_history), self.replicas, target)) self.replicas = target return True def simulate(): scaler = KnativeAutoscaler(concurrency=20) # 模拟一段真实流量:空闲 -> 高峰 -> 低谷 -> 归零 traffic = [0, 0, 0, 5, 18, 42, 90, 130, 160, 150, 80, 30, 12, 3, 0, 0, 0, 0] print("时间 请求数 期望Pod 动作") print("---- ------ ------- ----") for t, req in enumerate(traffic): scaler.observe(req) changed = scaler.reconcile() action = "扩缩容!" if changed else "保持" print(f"{t:>3}s {req:>5} {scaler.replicas:>5} {action}") if __name__ == "__main__": simulate()
self.concurrency = concurrency设置单Pod并发上限C,对应YAML中的containerConcurrency配置。self.req_history.append(requests)把每秒请求数存入滑动窗口,保留最近10秒的观测数据。desired = math.ceil(avg / self.concurrency)核心公式:期望副本数 = 平均并发 ÷ 单Pod并发上限,向上取整。traffic = [0, 0, 0, 5, 18, 42, 90, ...]模拟真实业务的流量曲线:先从零开始爬升到高峰,再回落到零。if target == self.replicas: return False只有当期望与当前不一致时才触发扩缩容,避免无意义的副本抖动。
常见误区
误区我以为缩容到零之后,服务就彻底下线了,下次访问需要重新部署一套配置,跟没部署过一样。
正解缩容到零只是把运行中的Pod副本全部回收,但Service、Route、Configuration这些“招牌、门迎路线、菜谱”仍然保存在K8s集群里。客人(请求)一来,Activator门铃响,Knative会按留存配置自动拉起新Pod。餐厅打烊了,但店铺和配方都在。
为何常见:从视觉上看“没有Pod了”和“服务消失了”很像,容易把“运行实例”和“声明配置”混为一谈。
误区网上教程清一色先装Istio,我以为没有Istio,Knative就完全跑不起来。
正解Knative早期版本的网络层确实依赖Istio,但现在已经支持多种可插拔网络层:Kourier轻量极简,Contour中规中矩,Gateway API面向未来。小型集群用Kourier几分钟就能跑起来,Istio只是功能最全的选项之一,适合已经上了服务网格的大集群。
为何常见:早期学习资料以Istio为主流,形成了"Knative = Istio"的刻板印象。
误区我把单Pod并发上限调到300,觉得一个Pod能扛这么多请求,Pod数量少了,应该更省钱。
正解单Pod并发过高,请求会在容器内排队,延迟飙升;CPU、内存被争抢,还可能触发OOM。通常建议设置在20~100之间,并通过压测观察P95延迟与错误率来确定最优值——就像服务员一次能服务的桌数是有限的,硬塞太多桌只会每桌都招呼不周。
为何常见:直觉上“并发上限”代表“能力上限”,忽略了单个Pod的物理资源瓶颈。
误区缩容到零这么省钱,我把在线支付网关、实时通信服务也全配上minReplicas=0。
正解对延迟极度敏感、需要7×24小时响应的服务,冷启动的几秒延迟会直接违反SLA。这类服务应设置minReplicas>0保活,或用多副本冗余来保证高可用。缩容到零适合低频、弹性、可容忍冷启动的场景,比如AI推理、批处理任务、内部工具。
为何常见:只看到“省资源”的好处,忽略了冷启动延迟对线上体验的影响。
误区Kubernetes的HPA是看CPU使用率的,我以为Knative的Autoscaler应该也看CPU和内存。
正解默认的KPA(Knative Pod Autoscaler)看的是并发请求数(in-flight requests)和每秒请求数(RPS),由Queue Proxy采集上报。K8s HPA的CPU指标是通过另一个机制接入的。你可以把KPA理解成“按客流量排班”,而HPA是“按员工疲劳度排班”——两者视角完全不同。
为何常见:先学了K8s的HPA,惯性思维直接迁移到了Knative上。
面试题
Q1. 下列哪一项是Knative Serving的四个核心对象?
- A.Service/Route/Configuration/Revision← 正确答案
- B.Deployment/Service/ConfigMap/Secret
- C.Pod/ReplicaSet/Ingress/Gateway
- D.Namespace/Node/Volume/NetworkPolicy
答案:A。Knative Serving的四个核心CRD是Service、Route、Configuration和Revision。B项是K8s原生对象,C项混入了Istio的Gateway,D项是K8s基础设施对象。就像餐厅的招牌、门迎、菜谱和菜品快照,这四个角色才是Knative自己的。
Q2. Knative缩容到零之后,新请求到来时由哪个组件负责接住并拉起新Pod?
- A.Activator 激活器← 正确答案
- B.Ingress 控制器
- C.Istio 控制面
- D.Kubelet 节点代理
答案:A。缩容到零后,流量会全部切到Activator。它像门口的门铃,先把请求挂起,同时触发Revision扩容,等新Pod就绪后再把请求转发过去。Ingress只负责入口路由,Kubelet负责节点上的容器管理,Istio控制面负责网格配置。
Q3. 某Knative服务设containerConcurrency=20,当前窗口平均并发为85,期望副本数应为多少?
- A.4个
- B.5个← 正确答案
- C.6个
- D.8个
答案:B。期望副本数 = ⌈85÷20⌉ = ⌈4.25⌉ = 5。相当于一个服务员最多服务20桌客人,现在有85桌在排队,大堂经理需要安排5个服务员。
Q4. 金丝雀发布时希望新版本承担20%流量,Route的权重应如何配置?
- A.旧版80%新版放出20%流量← 正确答案
- B.新旧两版各自承担一半流量
- C.新版80%旧版仅留20%流量
- D.旧版下线新版承接全部流量
答案:A。金丝雀发布的定义就是让新版本先接收小比例流量,A项“旧版80%、新版20%”正是标准的金丝雀配置。全部流量权重之和必须等于100%,B项是平均分配,C项是新版占大头,D项是全量切换,都不是金丝雀。
Q5. 关于Revision的特性,下列哪项描述正确?
- A.修改配置后所有实例原地升级
- B.每次变更产生不可变快照← 正确答案
- C.Revision内容可随时在线编辑
- D.单个服务只允许存在一个版本
答案:B。Revision是Knative中最核心的不可变对象——每次Configuration变更都会生成新Revision,旧版本永远保留且不可修改。原地升级是传统Deployment的行为;Revision不可编辑;一个Service可以有多个Revision共存做流量切分。
Q6. Knative Autoscaler(KPA)做扩缩容决策时,主要参考哪些指标?
- A.队列代理采集的并发指标← 正确答案
- B.每秒请求数的实时统计← 正确答案
- C.CPU与内存的资源用量
- D.GPU显存实时占用情况
答案:AB。KPA默认基于并发请求数(in-flight requests)和RPS(每秒请求数)做决策,这两个指标由Queue Proxy采集。CPU/内存是K8s HPA的指标,GPU显存则完全不在KPA的考量范围内。就像大堂经理看的是排队人数,而不是服务员流了多少汗。
Q7. 以下哪些场景更适合使用Knative的缩容到零特性?
- A.低频调用的模型推理接口← 正确答案
- B.每日定时的批量训练任务← 正确答案
- C.全天候在线的交易网关服务
- D.事件触发的数据处理函数← 正确答案
答案:ABD。低频推理接口、定时批处理任务、事件触发的数据处理都是“偶发性负载”,空闲期长,缩容到零能显著节省成本。而全天候在线的交易网关对延迟极度敏感,冷启动的几秒会造成交易超时,必须保持常驻副本。
Q8. Knative Serving中“稳定窗口”(stable window)的主要作用是什么?
- A.决定副本数调整的执行节奏← 正确答案
- B.控制请求进入的排队时长
- C.限定流量切换的最短间隔
- D.约束日志上报的数据频率
答案:A。稳定窗口是Autoscaler的“冷静期”,默认60秒。窗口期内系统会持续观察流量,只有窗口期满后才执行缩容决策,避免因瞬时波动导致副本数频繁抖动。就像大堂经理不会因为某1分钟没客人就立刻让所有服务员回家。
Q9. 下列哪些手段可以有效降低Knative服务的冷启动时间?
- A.缩小容器镜像的整体体积← 正确答案
- B.开启镜像预热与缓存加速← 正确答案
- C.增加更多初始化容器数量
- D.配置最小副本数保持热备← 正确答案
答案:ABD。镜像越小拉取越快,预热缓存省去网络传输时间,minReplicas>0则让Pod常驻完全避免冷启动。增加initContainer反而会让启动链路更长、冷启动更慢,是典型的错误做法。这就像备菜越充分、上菜越快,但“多派几个洗菜工”并不会加速。
Q10. 当Knative服务在稳定窗口内持续低并发(如平均并发<1),Autoscaler最终会执行什么操作?
- A.窗口期满后一次性缩容到零← 正确答案
- B.立即删除所有运行中的副本
- C.保持当前副本永远不变化
- D.先扩容再执行缩容操作
答案:A。KPA的缩容到零有严格的冷静机制:必须等稳定窗口(默认60秒)期满,且期间并发持续低于阈值,才会一次性把副本缩到0。B错在“立即”,系统不会因瞬时低流量就立刻回收;C违背了Autoscaler的职责;D毫无意义。这就像餐厅要确认“确实一整晚没客人”才会打烊,而不是看到几分钟没人就关门。