# 使用Knative Serving构建Serverless应用平台
本文介绍如何在CCE集群上部署Knative Serving v1.19，构建具备按需弹性伸缩、灰度发布、Scale to Zero等能力的Serverless应用平台。内容涵盖从安装、配置域名、部署服务、验证Scale to Zero到灰度发布的完整上线流程，并给出KPA调优、资源配额、SWR镜像迁移等生产环境配置建议。
#### 概述
Knative是一款基于Kubernetes的Serverless框架，旨在提供跨平台的Serverless编排标准。它通过整合容器构建（或函数）、工作负载管理及事件驱动能力，在Kubernetes之上提供"声明式 API + 自动编排 + 流量控制"的Serverless体验。
Knative的核心价值：
- **请求驱动的自动扩缩容（KPA）**：不同于HPA基于容器指标（CPU/内存），Knative Pod Autoscaler（KPA）基于请求并发数或QPS动态调整Pod数量，支持缩容到0，无流量时不占用计算资源。
- **零冷启动兜底**：Pod缩容到0后，Activator组件拦截请求、触发扩容、排队等待，Pod就绪后转发，保证请求不丢失。
- **版本管理与灰度发布**：Revision不可变，Route通过流量权重实现蓝绿发布与金丝雀发布，无需额外工具链。
- **标准化**：基于Kubernetes CRD，与云原生生态无缝集成。
 
#### 前提条件
- 已创建1.28及以上版本（推荐1.30+）的CCE Standard或Turbo集群，至少2个节点，节点规格不低于4核8GB。Turbo集群（独享节点池）适合对隔离性有要求的AI推理场景。
- 已创建弹性负载均衡实例，用于Kourier网关对外暴露服务。
- 已开通容器镜像服务。
- 节点可访问公网，或已将Knative组件镜像迁移至SWR。
 
#### 约束与限制
- 本实践仅部署Knative Serving（请求驱动的工作负载管理），暂不涉及Knative Eventing（事件驱动模型）。若需事件驱动模型（如IoT、消息队列），可在Serving之上叠加Knative Eventing组件。
- CCE不会为type: LoadBalancer的Service自动创建和绑定ELB，需手动创建并通过kubernetes.io/elb.id注解关联。
- 网络插件需支持NetworkPolicy，CCE默认容器网络（Cilium/Tunnel）均支持。
- Scale to Zero冷启动耗时取决于镜像拉取速度与应用启动时长（通常1\~3秒），对冷启动敏感的业务建议设置min-scale≥1。
- Knative Service的services.serving.knative.dev与core Service的services名称冲突，在部分CCE版本下需调整service-webhook的apiGroups配置，详见[创建Knative Service时报错Forbidden？]。
 
#### 资源规划
- 节点规划
  
  | 节点池      | 规格                       | 数量    | 用途                                                     |
  |:---|:---|:---|:---|
  | 系统节点池    | 4C8G                     | 2   | 运行Knative控制面（knative-serving命名空间）+ Kourier网关。         |
  | 业务节点池   | 按业务峰值估算（如8C16G）           | ≥ 2 | 运行Knative Service业务Pod；启用Scale to Zero后，节点资源可被其他工作负载复用。 |
  | GPU节点池（可选） | Ascend 910 / NVIDIA GPU | ≥ 1 | AI推理场景（如vLLM部署大模型），需安装对应设备插件。                         |
     
  
- 网络规划
  
  | 资源        | 规划                                  | 说明                                                            |
  |:---|:---|:---|
  | ELB（公网型） | 1 个                                   | Kourier Gateway的LoadBalancer服务将绑定此ELB，对外提供Knative Service访问入口。 |
  | 域名     | 1 个（生产环境）                           | 如"\*.knative.example.com"，泛域名解析至ELB绑定的EIP；测试环境可用sslip.io自动解析。   |
  | 命名空间     | knative-serving（控制面）、default或业务命名空间 | 控制面命名空间由安装YAML自动创建。                                           |
     
  
- ELB规划
  ![](https://support.huaweicloud.com/bestpractice-cce/public_sys-resources/caution_3.0-zh-cn.png)
  CCE的hws-cloudprovider不会为type: LoadBalancer的Service自动创建和绑定ELB，必须手动创建ELB实例，然后通过Service注解显式关联。
  - ELB类型选择
    
    | 类型        | elb.class  | 适用场景      | 配额                                                               |
    |:---|:---|:---|:---|
    | 共享型 ELB   | union       | 测试环境、低流量场景 | 监听器/后端服务器组配额较小，多个Service共享时易触发Quota exceeded for resources: pool。 |
    | 独享型 ELB | performance | 生产环境、高流量场景 | 独立资源配额，性能隔离，推荐Knative生产部署使用。                                      |
       
    
  
  - 创建ELB。
    - 类型选择：测试环境用共享型，生产环境用独享型。
    
    - 网络配置：选择与当前CCE集群相同的VPC。
    
    - 记录ELB ID。
      ![](https://support.huaweicloud.com/bestpractice-cce/public_sys-resources/caution_3.0-zh-cn.png)
      无需手动配置监听器与后端服务器组，hws-cloudprovider会根据Service的spec.ports自动创建。若之前apply失败导致ELB残留了监听器或Pool，需在ELB控制台手动清理后重新 apply。
      
     
  
  - 绑定ELB到Kourier Service
    - 在Kourier Gateway Service（kourier-system命名空间下的kourier Service）上添加注解：
      ```
      apiVersion: v1
      kind: Service
      metadata:
        name: kourier
        namespace: kourier-system
        annotations:
          kubernetes.io/elb.id: <your-elb-id>        # 替换为实际ELB ID
          kubernetes.io/elb.class: union              # 共享型填union，独享型填performance
      spec:
        type: LoadBalancer
        # ... 其余字段保持不变
      ```
      
    
    - 通过kubectl命令：
      ```
      kubectl annotate svc kourier -n kourier-system \
        kubernetes.io/elb.id=<your-elb-id> \
        kubernetes.io/elb.class=union                 # 独享型改为performance
      ```
      **注意**：若绑定失败，请检查以下常见报错：
      - "listener is empty"或"elb.id is not defined, skip"：Service缺少elb.id注解，hws-cloudprovider无法创建监听器。
      
      - "Quota exceeded for resources: pool（ELB.8905）"：共享型ELB的后端服务器组配额已满，需清理或更换独享型ELB。
       
     
   
- 镜像仓库规划 Knative组件镜像默认来自gcr.io/knative-releases与ghcr.io/knative，CCE节点若无法直接拉取公网镜像，需将镜像迁移至SWR。镜像迁移详情请参见[上传镜像](https://support.huaweicloud.com/qs-swr/index.html)。
  
  | 组件                                           | 默认镜像                | SWR 目标                    |
  |:---|:---|:---|
  | activator / autoscaler / controller / webhook | ``` gcr.io/knative-releases/knative.dev/serving/cmd/* ```     | ``` swr.<region>.myhuaweicloud.com/<project>/knative-*:v1.19.6 ``` |
  | net-kourier-controller / kourier-gateway      | ``` gcr.io/knative-releases/knative.dev/net-kourier/cmd/* ``` | ``` swr.<region>.myhuaweicloud.com/<project>/kourier-*:v1.19.0 ``` |
     
  
 
#### 操作流程
#### 步骤一：安装kn CLI客户端
kn是Knative的命令行客户端，用于创建、更新、删除Knative Service与管理Revision。
1. 使用kubectl连接集群，详情请参见[通过kubectl连接集群](https://support.huaweicloud.com/usermanual-cce/cce_10_0107.html)。
2. 执行以下命令，安装kn CLI客户端。本文以knative-v1.19.0为例。
   ```
   # Linux amd64
   curl -Lo ./kn https://github.com/knative/client/releases/download/knative-v1.19.0/kn-linux-amd64
   chmod +x ./kn
   sudo mv ./kn /usr/local/bin/
   ```
   
3. 验证安装：
   ```
   kn version
   ```
   预期输出：
   ```
   Version:      v1.19.0
   Build Date:   2026-xx-xx
   Git Revision: xxxxxxx
   Supported APIs:
   * Serving v1 (knative-serving v1.19.x)
   ```
   
 
#### 步骤二：安装Knative Serving CRD与核心组件
![](https://support.huaweicloud.com/bestpractice-cce/public_sys-resources/caution_3.0-zh-cn.png)
若节点无法拉取公网镜像，请先完成SWR镜像迁移，并将下方YAML中的镜像地址替换为SWR地址。
1. 安装CRD。
   ```
   kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.19.6/serving-crds.yaml
   kubectl wait --for=condition=Established --all crd --timeout=120s
   ```
   预期输出信息包含以下内容。
   ```
   customresourcedefinition.apiextensions.k8s.io/services.serving.knative.dev created
   customresourcedefinition.apiextensions.k8s.io/configurations.serving.knative.dev created
   customresourcedefinition.apiextensions.k8s.io/revisions.serving.knative.dev created
   customresourcedefinition.apiextensions.k8s.io/routes.serving.knative.dev created
   ...
   ```
   
2. 安装核心组件。
   ```
   kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.19.6/serving-core.yaml
   ```
   该YAML部署以下组件到knative-serving命名空间：
   
   | 组件         | 说明                                                       |
   |:---|:---|
   | controller | 监听Service/Configuration CRD变化，协调生成Revision与Deployment。 |
   | webhook      | 校验CRD合法性，注入默认值。                                           |
   | autoscaler  | 收集Pod并发指标，调整Deployment的replicas，支持缩容到0。                  |
   | activator  | Pod缩容到0时拦截请求，触发扩容并排队转发。                                 |
      
   
3. 执行以下命令，确认knative-serving命名空间下所有Pod状态均为Running。
   ```
   kubectl get pods -n knative-serving
   ```
   预期输出：
   ```
   NAME                                READY   STATUS    RESTARTS   AGE
   activator-xxxxx-xxxxx               1/1     Running   0          60s
   autoscaler-xxxxx-xxxxx              1/1     Running   0          60s
   controller-xxxxx-xxxxx              1/1     Running   0          60s
   webhook-xxxxx-xxxxx                 1/1     Running   0          60s
   ```
   若webhook处于CrashLoopBackOff，多为TLS证书未就绪，等待1\~2分钟后自动恢复。Knative v1.19自带证书签发，无需额外部署cert-manager。
   
 
#### 步骤三：部署Kourier网关并配置Ingress
Knative支持多种Ingres网关（Kourier/Istio/Contour）。Kourier是基于Envoy的轻量级网关，依赖少、启动快，推荐作为入门与生产默认选型。
1. 部署Kourier。
   ```
   kubectl apply -f https://github.com/knative/net-kourier/releases/download/knative-v1.19.0/kourier.yaml
   ```
   Kourier部署到kourier-system命名空间，包含3scale-kourier-gateway（数据面Envoy）。其中Gateway通过"type: LoadBalancer"暴露，CCE不会自动绑定ELB并分配外部IP，需要在Kourier Service上通过注解手动关联已创建的ELB实例。未配置ELB注解时，hws-cloudprovider会报"listener is empty"或"elb.id is not defined, skip"错误。
   
2. 配置Kourier为默认Ingress。
   ```
   kubectl patch configmap/config-network \
     --namespace knative-serving \
     --type merge \
     --patch '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}'
   ```
   
3. 验证网关就绪并获取入口IP地址。
   ```
   kubectl get pods -n kourier-system
   kubectl get svc kourier -n kourier-system
   ```
   预期输出：
   ```
   NAME                             READY   STATUS    RESTARTS   AGE
   3scale-kourier-control-xxxxx    1/1     Running   0          60s
   3scale-kourier-gateway-xxxxx     1/1     Running   0          60s
   NAME      TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)                      AGE
   kourier   LoadBalancer   10.x.x.x      121.xxx.xxx.xxx   80:3xx/TCP,443:3xx/TCP        90s
   ```
   EXTERNAL-IP为ELB绑定的公网/私网IP地址，需提前通过kubernetes.io/elb.id注解关联ELB。请记录该IP地址，后续配置域名解析时使用。
   
 
#### 步骤四：配置域名与DNS
Knative默认域名后缀由config-domain ConfigMap决定，所有Knative Service的访问地址为\<service-name\>.\<namespace\>.\<domain\>。
- 测试环境：使用sslip.io自动解析 sslip.io会将{ip}.sslip.io解析为{ip}，无需自建DNS。将上一步获取的ELB IP地址拼接为域名：
  ```
  INGRESS_IP=$(kubectl get svc kourier -n kourier-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  KNATIVE_DOMAIN="${INGRESS_IP}.sslip.io"
  kubectl patch configmap/config-domain \
    --namespace knative-serving \
    --type merge \
    --patch "{\"data\":{\"${KNATIVE_DOMAIN}\":\"\"}}"
  echo "Knative domain: ${KNATIVE_DOMAIN}"
  ```
  预期输出以下内容。
  ```
  Knative domain: 121.xxx.xxx.xxx.sslip.io
  ```
  
- 生产环境：使用自定义域名
  1. 将泛域名"\*.knative.\<your-domain\>"解析至ELB绑定的EIP。
  
  2. 配置config-domain：
     ```
     kubectl patch configmap/config-domain \
       --namespace knative-serving \
       --type merge \
       --patch '{"data":{"knative.example.com":""}}'
     ```
     
  
  3. （可选）为Kourier Gateway的443端口配置TLS证书，建议通过CCE的证书管理或Secret注入实现HTTPS访问。
   
 
#### 步骤五：部署首个Knative Service
1. 使用kn部署helloworld。
   ```
   kn service create helloworld \
     --image ghcr.io/knative/helloworld-go:latest \
     --port 8080 \
     --env TARGET=World
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/public_sys-resources/caution_3.0-zh-cn.png)
   若节点无法拉取ghcr.io镜像，请先迁移至SWR并替换为swr.\<region\>.myhuaweicloud.com/\<project\>/helloworld-go:latest。
   预期输出：
   ```
   Creating service 'helloworld' in namespace 'default':
     0.030s The Route is still working to reflect the latest desired specification.
     0.062s ...
     0.080s Configuration "helloworld" is waiting for a Revision to become ready.
     8.156s ...
     8.178s Ingress has not yet been reconciled.
     8.298s Ready to serve.
   Service 'helloworld' created with latest revision 'helloworld-00001' and URL:
   http://helloworld.default.121.xxx.xxx.xxx.sslip.io
   ```
   
2. 查看服务与底层资源。
   ```
   kn service list
   kubectl get configuration,revision,route,deployment -l serving.knative.dev/service=helloworld
   ```
   预期输出：
   ```
   NAME            URL                                                LATEST CREATED   LATEST READY   READY   REASON
   helloworld      http://helloworld.default.121.xxx.xxx.xxx.sslip.io  helloworld-00001 helloworld-00001 True
   NAME                                                  READY   STATUS
   configuration.serving.knative.dev/helloworld          True
   revision.serving.knative.dev/helloworld-00001         True
   route.serving.knative.dev/helloworld                  True
   deployment.apps/helloworld-00001-deployment           1/1
   ```
   根据Knative Serving的自动伸缩机制，当无流量进入时，Revision对应的Deployment副本数将自动缩容至0（即0/0）。
   Knative Service自动创建了Configuration、Revision、Route、Deployment四级资源，对应CRD层级关系：Service →Configuration → Revision → Deployment。
   
3. 访问服务。在任意能访问公网的节点或机器上测试helloworld服务。
   ```
   curl http://helloworld.default.${KNATIVE_DOMAIN}
   ```
   返回"Hello World!"即表示服务部署成功。
   
 
#### 步骤六：验证Scale to Zero
Scale to Zero是Knative的核心特性：无流量时Autoscaler将Deployment replicas缩为0，请求到达时由Activator拦截并触发扩容。
1. 观察缩容到0。 服务无请求一段时间后（默认30秒空闲窗口），Pod自动终止：
   ```
   # 持续观察Pod状态
   kubectl get pod -l serving.knative.dev/service=helloworld -w
   ```
   预期结果：约30\~60秒后，Pod数量变为0。
   ```
   NAME                                         READY   STATUS    RESTARTS   AGE
   helloworld-00001-deployment-xxxxx-xxxxx      2/2     Running   0          60s
   helloworld-00001-deployment-xxxxx-xxxxx      2/1     Terminating   0      90s
   helloworld-00001-deployment-xxxxx-xxxxx      0/1     Terminating   0      95s
   ```
   
2. 触发冷启动。 Pod数为0时发起请求，Activator拦截、触发扩容、转发：
   ```
   curl -w "\nTotal time: %{time_total}s\n" http://helloworld.default.${KNATIVE_DOMAIN}
   ```
   预期输出：
   ```
   Hello World!
   Total time: 1.2s
   ```
   首次冷启动耗时取决于镜像拉取与应用启动时长（通常1\~3秒）。再次请求会直接命中已运行的Pod，耗时降至毫秒级。
   
3. （可选）调整缩容窗口。 Knative默认在空闲30秒后将Pod缩容到 0，可通过Revision注解调整该窗口，例如延长至1分钟。
   ```
   kn service update helloworld \
     --annotation autoscaling.knative.dev/scale-to-zero-pod-retention-period=1m
   ```
   预期输出：
   ```
   Updating service 'helloworld' in namespace 'default':
     0.030s The Route is still working to reflect the latest desired specification.
     0.062s ...
     0.080s Configuration "helloworld" is waiting for a Revision to become ready.
     1.156s ...
     1.178s Ingress has not yet been reconciled.
     1.298s Ready to serve.
   Service 'helloworld' updated to latest revision 'helloworld-00003' and URL:
   http://helloworld.default.121.xxx.xxx.xxx.sslip.io
   ```
   修改注解会触发Knative创建新的Revision（如上例中的helloworld-00003），旧Revision将逐步停止流量，新Revision承接后续请求。
   
 
#### 步骤七：验证灰度发布（蓝绿/金丝雀）
Knative通过Revision不可变快照 + Route流量权重实现灰度发布，无需引入额外工具链。
1. 更新镜像（自动生成新Revision）。
   ```
   kn service update helloworld \
     --image ghcr.io/knative/helloworld-go:latest \
     --env TARGET=Knative
   ```
   该操作会自动创建新Revision（helloworld-00002），默认Route将100%流量切到新版本。旧Revision（helloworld-00001）保留但不接流量。
   
2. 金丝雀发布：按权重分流。 将流量拆分为旧版本90%、新版本10%，观察后再逐步放开：
   ```
   kn service update helloworld \
     --traffic helloworld-00001=90 \
     --traffic helloworld-00002=10
   ```
   --traffic参数格式为"Revision名称=百分比"，多个Revision的权重总和应为100。
   
3. 验证流量分配。多次请求服务，观察返回内容的比例分布。
   ```
   for i in $(seq 1 10); do
     curl -s http://helloworld.default.${KNATIVE_DOMAIN}
   done | sort | uniq -c
   ```
   预期输出（约9:1比例）：
   ```
   9 Hello World!
   1 Hello Knative!
   ```
   
4. 查看路由详情。
   ```
   kn route describe helloworld
   ```
   预期输出：
   ```
   Name:       helloworld
   Namespace:  default
   Age:        10m
   URL:        http://helloworld.default.121.xxx.xxx.xxx.sslip.io
   Traffic Targets:
     90%  @latest  (helloworld-00001) # still old
           URL:  http://helloworld.default.../helloworld-00001
     10%  helloworld-00002
           URL:  http://helloworld.default.../helloworld-00002
   ```
   
5. 版本回滚。 Revision为不可变快照，回滚操作即将流量权重重新指向旧Revision：
   ```
   kn service update helloworld --traffic helloworld-00001=100
   ```
   执行后流量立即切回helloworld-00001，无需重新部署。
   
 
#### 配置优化
#### KPA弹性伸缩调优
Knative Pod Autoscaler（KPA）默认基于并发数（concurrency）进行弹性伸缩。生产环境需根据业务特征调整关键参数。
关键参数通过Revision的template.metadata.annotations注解配置：
| 注解                       | 默认值                     | 说明         | 调优建议                             |
|:---|:---|:---|:---|
| ``` autoscaling.knative.dev/metric ```                             | concurrency               | 伸缩指标        | 高QPS短任务用rps；长连接或重计算任务用concurrency。 |
| ``` autoscaling.knative.dev/target ```                             | 100（concurrency）/ 200（rps） | 单Pod目标并发/速率 | 按单Pod承载能力设定，过低会过度扩容，过高会触发限流。       |
| ``` autoscaling.knative.dev/max-scale ```                          | 0（无上限）                     | 最大Pod数        | 生产环境必设，防止流量突增打满节点池资源。              |
| ``` autoscaling.knative.dev/min-scale ```                          | 0                         | 最小Pod数       | 对冷启动敏感的场景设为1\~2，保留温实例。              |
| ``` autoscaling.knative.dev/scale-to-zero-pod-retention-period ``` | 0s                      | 缩容到0前的保留时长  | 设30s\~1m，平滑应对间歇性流量。               |
| ``` autoscaling.knative.dev/window ```                             | 60s                       | 伸缩计算窗口      | 突发流量场景缩短至30s；平稳流量延长至120s减少抖动。       |
   
该表注解作用于单个Revision。如需为所有Service设置全局默认值，请编辑"config-autoscaler ConfigMap：kubectl edit configmap/config-autoscaler -n knative-serving"。注解优先级高于全局默认。
**示例：为高QPS Web服务配置KPA**
以下以helloworld服务为例，演示如何为高QPS场景配置KPA参数。
```
kn service create web-api \
  --image swr.cn-north-7.myhuaweicloud.com/<project>/web-api:latest \
  --port 8080 \
  --annotation autoscaling.knative.dev/metric=rps \
  --annotation autoscaling.knative.dev/target=200 \
  --annotation autoscaling.knative.dev/max-scale=20 \
  --annotation autoscaling.knative.dev/min-scale=2 \
  --annotation autoscaling.knative.dev/window=30s
```
#### 资源配额与限制
为避免控制面过载、Pod调度失败或集群资源耗尽，建议按以下策略配置资源配额。
| 配置项                         | 建议值                                               | 说明                                                    |
|:---|:---|:---|
| 控制面Pod resources requests | controller/autoscaler 500m/512Mi，webhook 100m/50Mi | 默认值偏低，在生产负载下建议适当上调。                                  |
| 业务Pod requests              | 按单实例承载能力设定                                       | 设置过低可能导致节点资源超卖；设置过高可能导致调度失败。Knative默认按requests计算并发数。 |
| 业务Pod limits               | requests的2\~4倍                                    | 预留突发流量的资源余量，避免突发流量OOM。在GPU场景下，limits应等于requests。     |
| namespace ResourceQuota     | 按业务命名空间实际需要进行设定                                     | 限制单个命名空间的资源配额，防止Knative Service无限扩容导致集群资源耗尽或服务不可用。     |
   
通过config-resource ConfigMap全局调整默认资源策略：
```
kubectl patch configmap/config-resource \
  --namespace knative-serving \
  --type merge \
  --patch '{"data":{"pod-container-default-requests":"{\"cpu\":\"500m\",\"memory\":\"512Mi\"}"}}'
```
#### 常见问题
#### 为什么webhook一直处于CrashLoopBackOff状态？
- 问题现象：执行"kubectl get pods -n knative-serving"命令，webhook Pod的显示状态为CrashLoopBackOff。查看Pod日志，报错"tls: failed to find certificate"。
- 可能原因：Knative自签发证书尚未完成，或CRD未Established就启动了webhook。
- 解决方案：执行以下命令，等待1\~2分钟，证书自动签发后webhook恢复Running。
  ```
  # 确认CRD已Established
  kubectl wait --for=condition=Established --all crd --timeout=120s
  # 重启webhook
  kubectl rollout restart deployment/webhook -n knative-serving
  ```
  
 
#### Kourier Gateway EXTERNAL-IP一直pending？
- 问题现象：执行"kubectl get svc kourier -n kourier-system"命令，EXTERNAL-IP显示为\<pending\>。hws-cloudprovider日志，报错"listener is empty"或"elb.id is not defined, skip"。
- 可能原因：CCE不会为"type: LoadBalancer"的Service自动创建/绑定ELB。必须手动创建ELB实例并通过kubernetes.io/elb.id注解显式关联，否则hws-cloudprovider跳过监听器创建，Service无法获取EXTERNAL-IP。
- 解决方案：
  1. 在CCE控制台购买ELB（测试用共享型，生产用独享型），记录ELB ID。
  
  2. 在Kourier Gateway Service上添加注解，或通过CCE控制台编辑Service注解。
     ```
     # 共享型ELB
     kubectl annotate svc kourier -n kourier-system \
       kubernetes.io/elb.id=<your-elb-id> \
       kubernetes.io/elb.class=union
     # 独享型ELB（将class改为performance）
     kubectl annotate svc kourier -n kourier-system \
       kubernetes.io/elb.id=<your-elb-id> \
       kubernetes.io/elb.class=performance
     ```
     
   
 
#### 访问Service返回503且Route状态显示为Ingress not configured？
- 问题现象：访问Service时返回 503 Service Unavailable：
- 可能原因：config-network的ingress-class未指向Kourier，或Kourier controller未就绪。
- 解决方案：
  1. 确认ingress-class配置。
     ```
     kubectl get configmap config-network -n knative-serving -o jsonpath='{.data.ingress-class}'
     ```
     预期输出：
     ```
     kourier.ingress.networking.knative.dev
     ```
     
  
  2. 若为空或配置错误，执行patch修正。
     ```
     kubectl patch configmap/config-network -n knative-serving --type merge \
       --patch '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}'
     ```
     
  
  3. 重启controller使配置生效。
     ```
     kubectl rollout restart deployment/controller -n knative-serving
     ```
     重启完成后等待片刻，Route的Ingress状态将更新为Ready，Service恢复正常访问。
     
   
 
#### 为什么Scale to Zero后冷启动耗时过长？
- 问题现象：Pod缩容至0后，首次请求端耗时超过5秒。
- 可能原因：镜像拉取慢、应用启动慢、Activator排队等待Pod Ready。
- 解决方案：
  - 镜像迁移至SWR并配置节点池缓存，减少拉取时间。
  
  - 应用优化启动逻辑（延迟初始化、预热）
  
  - 对冷启动敏感的业务，设置min-scale=1保留温实例。
   
 
#### 创建Knative Service时报错Forbidden？
- 问题现象：执行"kubectl apply -f helloworld-go.yaml" 命令创建Knative Service时报错。
  ```
  Error from server (Forbidden): error when creating "helloworld-go.yaml":
  services.serving.knative.dev "helloworld-go" is forbidden:
  expression 'object.spec.type == "LoadBalancer"' resulted in error: no such key: type
  ```
  
- 可能原因：CCE集群预安装了一个名为service-webhook的ValidatingWebhookConfiguration，用于校验core Service是否为LoadBalancer类型。该webhook的matchConditions使用了CEL表达式object.spec.type == "LoadBalancer"，但其rules中apiGroups设为\["\*"\]，导致匹配范围覆盖了Knative的services.serving.knative.dev。Knative Service的spec结构与core Service完全不同，没有spec.type字段，CEL表达式取不到key即报错；而failurePolicy: Fail使错误直接转化为拒绝。 问题webhook结构如下：
  ```
  apiVersion: admissionregistration.k8s.io/v1
  kind: ValidatingWebhookConfiguration
  metadata:
    name: service-webhook
  webhooks:
    - name: validate.crd.service
      matchConditions:
        - expression: object.spec.type == "LoadBalancer"   # CEL只对core Service有效
          name: cce-managed-service
      failurePolicy: Fail
      rules:
        - apiGroups: ["*"]       #匹配所有apiGroup，错误覆盖了serving.knative.dev
          apiVersions: ["v1"]
          operations: ["CREATE", "UPDATE"]
          resources: ["services"]
          scope: "*"
      clientConfig:
        url: https://127.0.0.1:9092/validate
  ```
  
- 解决方案：
  1. 编辑service-webhook。
     ```
     kubectl edit validatingwebhookconfiguration service-webhook
     ```
     
  
  2. 修改rules中的apiGroups，仅匹配core Service。
     ```
     # 修改前
     apiGroups: ["*"]
     # 修改后
     apiGroups: [""]
     ```
     ""表示core apiGroup，修改后该webhook仅匹配core Service（v1/Service），不再匹配services.serving.knative.dev。
     
  
  3. 保存退出后，重新执行以下命令即可。
     ```
     kubectl apply -f helloworld-go.yaml
     ```
     
   
 
