OpenShift服务发现返回非预期值,调用REST API报未知tcp协议错误
问题根本原因
1. Kubernetes/OpenShift 默认服务发现环境变量机制
OpenShift 基于Kubernetes构建,完全继承Kubernetes的Pod环境变量注入规则:当Pod启动时,Kubernetes会自动为其注入当前命名空间下所有已存在Service的相关环境变量,变量命名规则为将Service名称转为大写、横杠替换为下划线作为前缀,相关变量格式固定:
<SERVICE_PREFIX>_SERVICE_HOST:Service的ClusterIP纯地址,无协议、无端口<SERVICE_PREFIX>_SERVICE_PORT:Service的默认端口号,纯数字<SERVICE_PREFIX>_PORT:固定格式为tcp://<ClusterIP>:<端口>,Kubernetes的Service默认工作在四层,不感知上层七层协议类型,所以不管你跑的是HTTP还是其他业务协议,该变量的协议前缀统一为tcp- 其他
<SERVICE_PREFIX>_PORT_<端口号>_TCP_*系列变量为分端口的详细信息,协议部分同样固定为tcp
你看到的tcp://172.30.245.8:8080就是Kubernetes自动注入的MICROSERVICE_2_PORT变量的值,该值和Service类型无关,不管是ClusterIP还是NodePort,这个变量的格式都不会变化,所以你修改Service类型无法解决问题。
2. 自定义环境变量未生效的常见原因
你手动配置的MICROSERVICE_2_SERVICE_HOST变量没有生效,大概率是两类问题:
- 代码中实际读取的变量名拼写错误,比如误把
MICROSERVICE_2_PORT当成了你配置的Host变量来使用,直接用该变量作为URL前缀就会出现tcp协议错误 - 部署第一个微服务时,配置的环境变量没有正确提交到Deployment,你可以执行
oc exec <第一个微服务Pod名> -- printenv MICROSERVICE_2_SERVICE_HOST验证变量实际值
推荐解决方案
- 方案1:优先使用集群内置DNS做服务发现。OpenShift默认部署CoreDNS提供服务域名解析能力,同一命名空间下的服务直接通过
http://<Service名>:<端口>即可调用,跨命名空间可以用http://<Service名>.<命名空间>.svc.cluster.local:<端口>的格式,不需要配置任何环境变量,也不需要硬编码IP地址 - 方案2:如果需要用自定义环境变量,避免使用和Kubernetes自动注入重名的变量名,比如定义
MICROSERVICE2_BASE_URL,值设置为http://microservice-2:8080,代码直接用该变量拼接接口路径即可 - 方案3:如果要直接使用Kubernetes自动注入的变量,手动拼接协议、地址和端口即可:
// 示例代码 String serviceHost = System.getenv("MICROSERVICE_2_SERVICE_HOST"); String servicePort = System.getenv("MICROSERVICE_2_SERVICE_PORT"); String apiUrl = "http://" + serviceHost + ":" + servicePort + "/你的接口路径";
内容的提问来源于stack exchange,提问作者jmann
相关产品推荐
相关产品推荐

