Kubernetes升级1.21后Scala Akka服务发现失效问题
问题根因
Kubernetes 1.18升级到1.21后Akka K8s API服务发现失效,核心是版本适配问题,常见触发原因有4类:
- Akka Discovery/K8s Management组件版本过低:1.1.0之前的版本默认只调用核心组的Endpoints接口做服务发现,K8s 1.21开始默认将EndpointSlice作为服务发现的首选数据源,部分发行版甚至默认关闭了旧Endpoints接口的全量同步,旧版组件读不到端点数据就会抛出服务不存在的错误。
- RBAC权限缺失:1.21版本后读取EndpointSlice资源需要
discovery.k8s.ioAPI组的对应权限,旧集群的RBAC规则通常只授权了核心组endpoints、pods的读取权限,Akka请求EndpointSlice接口时会被403拦截,无法获取实例列表。 - 配置占位符未替换:当前配置里的
${serviceName}属于Hocon配置占位符,如果没有通过环境变量、外部配置源正确注入实际Service名称,服务发现模块会直接拿${serviceName}这个字面量去K8s查询,必然返回找不到服务。 - Service端点未正确生成:K8s 1.21收紧了标签选择器的校验规则,如果Pod标签和Service的selector存在大小写、字符不匹配的问题,Endpoints/EndpointSlice资源不会写入对应Pod IP,服务发现自然查不到可用实例。
排查解决步骤
按从易到难的顺序排查:
- 首先确认配置占位符是否正常替换
给应用启动参数加-Dakka.loglevel=DEBUG,启动后搜索日志中服务发现模块打印的目标服务名,如果打印的是字面量${serviceName},说明配置注入失败,检查环境变量是否正确传入、配置文件的引入路径是否正确,确保service-name配置项的值和K8s中部署的Service名称完全一致。 - 升级Akka相关依赖
将akka-management-cluster-bootstrap、akka-discovery-kubernetes-api两个依赖升级到1.1.0及以上稳定版本,新版本默认自动适配K8s 1.20+的EndpointSlice API,同时兼容旧版Endpoints API,不需要修改业务配置即可适配新集群。 - 更新RBAC授权规则
给应用绑定的ServiceAccount补充EndpointSlice资源的读取权限,参考规则如下:
权限配置生效后重启所有应用实例,观察错误是否消失。apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: akka-cluster-discovery rules: - apiGroups: [""] resources: ["pods", "endpoints"] verbs: ["get", "list"] # 补充K8s 1.21+需要的EndpointSlice权限 - apiGroups: ["discovery.k8s.io"] resources: ["endpointslices"] verbs: ["get", "list"] - 校验K8s服务端点状态
执行命令kubectl get endpoints <你的实际服务名> -n <应用所在命名空间>,检查返回的地址列表是否包含所有Akka集群的Pod IP。如果列表为空,核对Service的spec.selector和Pod的metadata标签是否完全匹配,修正标签后等待K8s自动同步端点数据,再验证服务发现功能。 - 临时兜底方案(不推荐长期使用)
如果短期内无法升级Akka依赖版本,可以在配置中强制关闭EndpointSlice查询逻辑,回退到旧版Endpoints接口查询:akka.discovery.kubernetes-api { endpoint-slice-enabled = false api-version = "v1" }
内容的提问来源于stack exchange,提问作者Bhanu
相关产品推荐
相关产品推荐

