使用Next.js getInitialProps调用ingress-nginx服务时遇ECONNREFUSED错误
问题描述
在Next.js的getInitialProps中调用API时抛出错误:error connect ECONNREFUSED 127.0.0.1:443,使用的请求URL为:http://ingress-nginx-controller.ingress-nginx.svc.cluster.local/api/users/currentuser。但直接在浏览器中调用https://ticketing.dev/api/users/currentuser可正常返回预期响应。
相关环境信息
Kubernetes资源查询结果:
PS C:\Users\sajee> kubectl get namespace NAME STATUS AGE default Active 3d16h ingress-nginx Active 3d15h kube-node-lease Active 3d16h kube-public Active 3d16h kube-system Active 3d16h PS C:\Users\sajee> kubectl get services -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-controller LoadBalancer 10.96.242.223 localhost 80:31220/TCP,443:30164/TCP 3d15h ingress-nginx-controller-admission ClusterIP 10.109.183.213 <none> 443/TCP 3d15h
原因分析
- 域名解析限制:
ingress-nginx-controller.ingress-nginx.svc.cluster.local是Kubernetes集群内部专属的Service域名,仅能在集群内的Pod中正常解析。如果Next.js在本地开发环境运行(而非部署在K8S集群内),本地DNS无法识别该域名,会默认将其解析到127.0.0.1,导致尝试连接本地443端口失败(本地无对应服务监听)。 - 协议与Ingress配置不匹配:你使用HTTP协议请求内部Service,但Ingress控制器可能配置了强制HTTPS重定向,导致请求被跳转至443端口,但请求环境未正确处理HTTPS连接逻辑。
解决步骤
场景1:本地开发环境下的Next.js
直接替换为浏览器使用的外部访问URL:https://ticketing.dev/api/users/currentuser。本地开发时,getInitialProps运行在本地Node.js进程中,只能访问外部可路由的地址,无法直接调用K8S内部Service。
场景2:Next.js部署在K8S集群内的Pod中
验证域名解析:在Next.js的Pod中执行以下命令,确认内部Service域名能正确解析到ClusterIP:
nslookup ingress-nginx-controller.ingress-nginx.svc.cluster.local预期返回结果应包含
10.96.242.223(对应Service的ClusterIP)。改用HTTPS协议并指定Host:如果Ingress配置了强制HTTPS重定向,修改请求URL为HTTPS协议,同时指定Ingress配置中的Host(否则Ingress无法路由到正确服务),并忽略自签名证书(集群内Ingress证书通常为自签名):
// 在getInitialProps中调整请求代码 const res = await fetch('https://ingress-nginx-controller.ingress-nginx.svc.cluster.local/api/users/currentuser', { headers: { 'Host': 'ticketing.dev' }, rejectUnauthorized: false // 仅集群内部使用时忽略证书错误 });测试端口连通性:在Pod中执行curl命令验证连接:
curl -v https://ingress-nginx-controller.ingress-nginx.svc.cluster.local/api/users/currentuser --insecure -H "Host: ticketing.dev"若能正常返回响应,说明配置正确,只需在Next.js代码中对应调整即可。
内容的提问来源于stack exchange,提问作者Sajeeb M Ahamed

