连接到 Kubernetes 服务导致连接被拒绝
Connecting to a Kubernetes service resulted in connection refused
我正在尝试使用 Kubernetes 部署我的 Web 应用程序。我使用 Minikube 创建集群并使用入口成功公开了我的前端 React 应用程序。然而,当我在前端 deployment.yaml 的“env”字段中附加后端服务的 URL 时,它不起作用。当我尝试通过前端 pod 连接到后端服务时,连接被拒绝。
前端部署 yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: <image_name>
imagePullPolicy: Never
ports:
- containerPort: 80
env:
- name: REACT_APP_API_V1_ENDPOINT
value: http://backend-svc
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: frontend
前端入口
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: front-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-read-timeout: "12h"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: front-testk.info
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
后端部署yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: backend
labels:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: <image_name>
ports:
- containerPort: 80
imagePullPolicy: Never
restartPolicy: Always
---
kind: Service
apiVersion: v1
metadata:
name: backend-svc
labels:
app: backend
spec:
selector:
app: backend
ports:
- name: http
port: 80
targetPort: 80
% kubectl get svc backend-svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
backend-svc ClusterIP 10.109.107.145 <none> 80/TCP 21h app=backend
已在前端 pod 内连接并尝试使用部署期间创建的 ENV 连接到后端:
❯ kubectl exec frontend-75579c8499-x766s -it sh
/app # apk update && apk add curl
OK: 10 MiB in 20 packages
/app # env
REACT_APP_API_V1_ENDPOINT=http://backend-svc
/app # curl $REACT_APP_API_V1_ENDPOINT
curl: (7) Failed to connect to backend-svc port 80: Connection refused
/app # nslookup backend-svc
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: backend-svc.default.svc.cluster.local
Address: 10.109.107.145
** server can't find backend-svc.cluster.local: NXDOMAIN
执行到我的后端 pod
# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1/node
# netstat -lnturp
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
我怀疑您的应用程序在端口 8080 上侦听。如果您仔细查看 netstat
的输出,您会注意到 Local Address
是 0.0.0.0:8080
:
# netstat -tulpn
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1/node
为了解决这个问题,您必须在您的服务中更正您的 targetPort
:
kind: Service
apiVersion: v1
metadata:
name: backend-svc
labels:
app: backend
spec:
selector:
app: backend
ports:
- name: http
port: 80
targetPort: 8080 # change this to 8080
不需要更改部署端的端口,因为 containerPort
主要是信息性的。不在那里指定端口不会阻止该端口被公开。任何监听容器内默认 "0.0.0.0"
地址的端口都可以访问。
我正在尝试使用 Kubernetes 部署我的 Web 应用程序。我使用 Minikube 创建集群并使用入口成功公开了我的前端 React 应用程序。然而,当我在前端 deployment.yaml 的“env”字段中附加后端服务的 URL 时,它不起作用。当我尝试通过前端 pod 连接到后端服务时,连接被拒绝。
前端部署 yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: <image_name>
imagePullPolicy: Never
ports:
- containerPort: 80
env:
- name: REACT_APP_API_V1_ENDPOINT
value: http://backend-svc
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: frontend
前端入口
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: front-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-read-timeout: "12h"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: front-testk.info
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
后端部署yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: backend
labels:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: <image_name>
ports:
- containerPort: 80
imagePullPolicy: Never
restartPolicy: Always
---
kind: Service
apiVersion: v1
metadata:
name: backend-svc
labels:
app: backend
spec:
selector:
app: backend
ports:
- name: http
port: 80
targetPort: 80
% kubectl get svc backend-svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
backend-svc ClusterIP 10.109.107.145 <none> 80/TCP 21h app=backend
已在前端 pod 内连接并尝试使用部署期间创建的 ENV 连接到后端:
❯ kubectl exec frontend-75579c8499-x766s -it sh
/app # apk update && apk add curl
OK: 10 MiB in 20 packages
/app # env
REACT_APP_API_V1_ENDPOINT=http://backend-svc
/app # curl $REACT_APP_API_V1_ENDPOINT
curl: (7) Failed to connect to backend-svc port 80: Connection refused
/app # nslookup backend-svc
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: backend-svc.default.svc.cluster.local
Address: 10.109.107.145
** server can't find backend-svc.cluster.local: NXDOMAIN
执行到我的后端 pod
# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1/node
# netstat -lnturp
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
我怀疑您的应用程序在端口 8080 上侦听。如果您仔细查看 netstat
的输出,您会注意到 Local Address
是 0.0.0.0:8080
:
# netstat -tulpn
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1/node
为了解决这个问题,您必须在您的服务中更正您的 targetPort
:
kind: Service
apiVersion: v1
metadata:
name: backend-svc
labels:
app: backend
spec:
selector:
app: backend
ports:
- name: http
port: 80
targetPort: 8080 # change this to 8080
不需要更改部署端的端口,因为 containerPort
主要是信息性的。不在那里指定端口不会阻止该端口被公开。任何监听容器内默认 "0.0.0.0"
地址的端口都可以访问。