K8s集群Kubeless排错实战:从Pod异常到函数调用失败的完整排查路径
Kubeless 是运行在 Kubernetes 上的 Serverless 框架,排错的第一步不是翻源码,而是确认三个核心组件是否正常:kubeless-controller-manager Pod 是否 Running、CRD 是否注册成功、函数 Pod 是否能被调度。
下面按从外到内的顺序逐步排查。
先确认故障现象属于哪一层
Kubeless 的问题通常表现为三类:kubeless function call 返回超时或连接拒绝、函数 Pod 一直 Pending 或 CrashLoopBackOff、kubectl get functions 无响应或报 CRD 不存在。
先执行以下命令确认控制器状态:
kubectl get pods -n kubeless
kubectl get crd | grep kubeless
预期结果是 kubeless-controller-manager-xxx 处于 Running 且 READY 为 1/1,CRD 列表中能看到 functions.kubeless.io、httptriggers.kubeless.io 等条目。
如果控制器 Pod 不是 Running,先看它的日志:
kubectl logs -n kubeless -l kubeless=controller --tail=100
常见报错 no matches for kind "Function" 说明 CRD 未注册或注册失败,需要重新 apply CRD 清单。
控制器正常但函数调用失败怎么查
控制器 Running 后,函数调用失败通常出在函数 Pod 本身。
先用 kubeless function list 确认函数状态,再查函数 Pod:
kubectl get pods -n default -l function=<函数名>
kubectl describe pod <函数Pod名> -n default
如果 Pod 处于 ImagePullBackOff,检查镜像地址是否可拉取,私有仓库需要确认 imagePullSecrets 已配置在函数部署中。
如果 Pod 处于 CrashLoopBackOff,查看容器日志:
kubectl logs <函数Pod名> -n default --previous
运行时依赖缺失、入口文件路径错误或端口未监听都会导致容器启动后立即退出。
Kubeless 默认期望函数在 8080 端口提供服务,如果函数代码监听了其他端口,需要显式指定:
kubeless function deploy myfunc --runtime python3.9 \
--handler test.handler --from-file test.py --port 8080
权限和网络问题容易被忽略
函数 Pod 正常 Running 但调用超时,优先检查 Service 和 Ingress 是否匹配:
kubectl get svc -n default | grep <函数名>
kubectl get ingress -n default
Kubeless 会为每个函数创建 Service,
如果集群没有可用的 Ingress Controller 或 API Gateway,kubeless function call 走的是端口转发方式,
需要确认本地 kubectl port-forward 没有被防火墙拦截。
RBAC 权限不足也会导致控制器无法创建函数 Pod,典型报错是 functions.kubeless.io is forbidden。
检查控制器使用的 ServiceAccount 是否绑定了足够的 ClusterRole:
kubectl get clusterrolebinding | grep kubeless
kubectl describe clusterrole kubeless-controller-deployer
如果用的是自定义 namespace 部署,确保 RoleBinding 覆盖了函数所在的 namespace。
修复后如何验证排错生效
每修完一项,不要急着继续下一步,先做最小验证。
控制器恢复后重新部署一个测试函数:
kubeless function deploy test-ok --runtime python3.9 \
--handler test.hello --from-file test.py
kubeless function call test-ok --data '{"name":"k8s"}'
预期返回函数处理结果。
如果调用成功但延迟很高,检查函数 Pod 的 resources requests 是否过低导致调度等待。
验证通过后,再用 kubectl get events -n default --sort-by=.lastTimestamp 看最近事件,确认没有反复出现的 Warning。
排错过程中有几个容易踩的坑:修改 CRD 后没有重启控制器导致旧缓存生效;
函数镜像用了 latest 标签但节点上已有旧缓存;
namespace 和函数名大小写不一致导致查不到资源。
建议每次变更后都用 kubectl get all -n 完整看一遍资源状态,不要只盯着单个 Pod。