如何在k8s集群内部前后连接(连接被拒绝)

Posted

技术标签:

【中文标题】如何在k8s集群内部前后连接(连接被拒绝)【英文标题】:How to connect front to back in k8s cluster internal (connection refused) 【发布时间】:2020-07-14 03:04:09 【问题描述】:

尝试将 React 前端 web 连接到 nodejs express api 服务器到 kubernetes 集群时出错。

可以在浏览器中导航到http:localhost:3000,并且网站正常。

但无法按预期导航到http:localhost:3008(不应暴露)

我的目标是将 REACT_APP_API_URL 环境变量传递给前端,以便设置 axios baseURL 并能够在前端和它的 api 服务器之间建立通信。

部署-front.yml

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: gbpd-front
spec:
  selector:
    matchLabels:
      app: gbpd-api
      tier: frontend
      track: stable
  replicas: 2
  template:
    metadata:
      labels:
        app: gbpd-api
        tier: frontend
        track: stable
    spec:
      containers:
        - name: react
          image: binomio/gbpd-front:k8s-3
          ports:
            - containerPort: 3000
          resources:
            limits:
              memory: "150Mi"
            requests:
              memory: "100Mi"
          imagePullPolicy: Always

service-front.yaml

apiVersion: v1
kind: Service
metadata:
  name: gbpd-front
spec:
  selector:
    app: gbpd-api
    tier: frontend
  ports:
  - protocol: "TCP"
    port: 3000
    targetPort: 3000
  type: LoadBalancer

Deploy-back.yaml

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: gbpd-api
spec:
  selector:
    matchLabels:
      app: gbpd-api
      tier: backend
      track: stable
  replicas: 3 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: gbpd-api
        tier: backend
        track: stable
    spec:
      containers:
        - name: gbpd-api
          image: binomio/gbpd-back:dev
          ports:
            - name: http
              containerPort: 3008

service-back.yaml

apiVersion: v1
kind: Service
metadata:
  name: gbpd-api
spec:
  selector:
    app: gbpd-api
    tier: backend
  ports:
  - protocol: "TCP"
    port: 3008
    targetPort: http

我尝试了很多组合,也尝试将“LoadBalancer”添加到后台服务但没有...

我可以将完美连接到 localhost:3000 并使用前端,但前端无法连接到后端服务。

问题 1:为了正确传递 REACT_APP_API_URL 到前端,使用什么 ip/名称? 问题2:为什么 curl localhost:3008 没有响应?

在尝试了 k8s 官方文档中的几乎所有内容 2 天后...无法弄清楚这里发生了什么,因此非常感谢任何帮助。

kubectl 描述 svc gbpd-api 回应:

kubectl describe svc gbpd-api
Name:                     gbpd-api
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            "apiVersion":"v1","kind":"Service","metadata":"annotations":,"name":"gbpd-api","namespace":"default","spec":"ports":["port":3008,"p...
Selector:                 app=gbpd-api,tier=backend
Type:                     LoadBalancer
IP:                       10.107.145.227
LoadBalancer Ingress:     localhost
Port:                     <unset>  3008/TCP
TargetPort:               http/TCP
NodePort:                 <unset>  31464/TCP
Endpoints:                10.1.1.48:3008,10.1.1.49:3008,10.1.1.50:3008
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

【问题讨论】:

容器是否在监听 3008 端口? 是的,在本地工作,也在 docker-compse kubectl describe svc gbpd-api 的输出是什么?前端和后端部署在同一个命名空间中? 答案已更新,是的,都在同一个命名空间中 如果你 curl 到 10.1.1.50:3008 是否有效? 【参考方案1】:

我测试了你的环境,并且在使用 nginx 镜像时可以正常工作,让我们回顾一下环境:

前端部署描述正确。 前端服务将其公开为loadbalancer,这意味着您的前端可以从外部访问,非常完美。 也正确描述了后部部署。 后端服务保留为 ClusterIP,以便只能从集群内部访问,非常棒。

下面我将演示前端和后端之间的通信。

我使用的是您提供的相同 yaml,只是出于示例目的将映像更改为 Nginx,并且由于它是一个 http 服务器,因此我将 containerport 更改为 80。

问题 1:为了正确传递 REACT_APP_API_URL 到前端,使用什么 IP/名称?

我按照要求将 ENV 变量添加到了前端部署中,我也将使用它来演示。您必须使用服务名称来 curl,我使用的是短版本,因为我们在同一个命名空间中工作。也可以使用全名:http://gbpd-api.default.svc.cluster.local:3008

复制:

创建 yaml 并应用它们:
$ cat deploy-front.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gbpd-front
spec:
  selector:
    matchLabels:
      app: gbpd-api
      tier: frontend
      track: stable
  replicas: 2
  template:
    metadata:
      labels:
        app: gbpd-api
        tier: frontend
        track: stable
    spec:
      containers:
        - name: react
          image: nginx
          env:
            - name: REACT_APP_API_URL
              value: http://gbpd-api:3008
          ports:
            - containerPort: 80
          resources:
            limits:
              memory: "150Mi"
            requests:
              memory: "100Mi"
          imagePullPolicy: Always

$ cat service-front.yaml 
cat: cat: No such file or directory
apiVersion: v1
kind: Service
metadata:
  name: gbpd-front
spec:
  selector:
    app: gbpd-api
    tier: frontend
  ports:
  - protocol: "TCP"
    port: 3000
    targetPort: 80
  type: LoadBalancer

$ cat deploy-back.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gbpd-api
spec:
  selector:
    matchLabels:
      app: gbpd-api
      tier: backend
      track: stable
  replicas: 3
  template:
    metadata:
      labels:
        app: gbpd-api
        tier: backend
        track: stable
    spec:
      containers:
        - name: gbpd-api
          image: nginx
          ports:
            - name: http
              containerPort: 80

$ cat service-back.yaml 
apiVersion: v1
kind: Service
metadata:
  name: gbpd-api
spec:
  selector:
    app: gbpd-api
    tier: backend
  ports:
  - protocol: "TCP"
    port: 3008
    targetPort: http

$ kubectl apply -f deploy-front.yaml 
deployment.apps/gbpd-front created
$ kubectl apply -f service-front.yaml 
service/gbpd-front created
$ kubectl apply -f deploy-back.yaml 
deployment.apps/gbpd-api created
$ kubectl apply -f service-back.yaml 
service/gbpd-api created
请记住,在 Kubernetes 中,通信是 designed to be made between services,因为当部署发生变化或 pod 失败时,总会重新创建 pod。
$ kubectl get all
NAME                              READY   STATUS    RESTARTS   AGE
pod/gbpd-api-dc5b4b74b-kktb9      1/1     Running   0          41m
pod/gbpd-api-dc5b4b74b-mzpbg      1/1     Running   0          41m
pod/gbpd-api-dc5b4b74b-t6qxh      1/1     Running   0          41m
pod/gbpd-front-66b48f8b7c-4zstv   1/1     Running   0          30m
pod/gbpd-front-66b48f8b7c-h58ds   1/1     Running   0          31m

NAME                 TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)          AGE
service/gbpd-api     ClusterIP      10.0.10.166   <none>         3008/TCP         40m
service/gbpd-front   LoadBalancer   10.0.11.78    35.223.4.218   3000:32411/TCP   42m
Pod 是工作人员,由于它们本质上是可替换的,因此我们将连接到前端 Pod 以模拟他的行为并尝试连接到后端服务(该网络层将流量引导到其中一个后端 pod)。 nginx 镜像没有预装curl,所以我必须安装它以进行演示:
$ kubectl exec -it pod/gbpd-front-66b48f8b7c-4zstv -- /bin/bash
root@gbpd-front-66b48f8b7c-4zstv:/# apt update && apt install curl -y
done.

root@gbpd-front-66b48f8b7c-4zstv:/# curl gbpd-api:3008
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
现在让我们尝试使用已定义的环境变量:
root@gbpd-front-66b48f8b7c-4zstv:/# printenv | grep REACT
REACT_APP_API_URL=http://gbpd-api:3008
root@gbpd-front-66b48f8b7c-4zstv:/# curl $REACT_APP_API_URL
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

注意事项:

问题二:为什么 curl localhost:3008 没有响应?

由于正确描述了所有 yaml,您必须检查 image: binomio/gbpd-back:dev 是否按预期在端口 3008 上正确服务。 由于不是公共镜像,我无法测试,所以我给你排查步骤: 就像我们在前端 pod 中登录一样,您必须登录到这个后端 pod 并测试 curl localhost:3008。 如果它基于带有 apt-get 的 linux 发行版,您可以像我在演示中那样运行命令: 从后端部署获取 pod 名称(例如:gbpd-api-6676c7695c-6bs5n) 运行kubectl exec -it pod/&lt;POD_NAME&gt; -- /bin/bash 然后运行apt update &amp;&amp; apt install curl -y 并测试curl localhost:3008 如果没有答案运行 `apt update && apt install net-tools 并测试netstat -nlpt,它必须向您显示正在运行的服务的输出和相应的端口,例如:
root@gbpd-api-585df9cb4d-xr6nk:/# netstat -nlpt
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:80              0.0.0.0:*               LISTEN      1/nginx: master pro 
如果 pod 即使采用这种方法也没有返回任何内容,则必须检查图像中的代码。

之后如果您需要帮助,请告诉我!

【讨论】:

哇,非常感谢您的回答, 我已经得到了一个 .env 文件,其中 docker-compose.yml 是,并且在 Dockerfile ARG 和 ENV 匹配项中,我是否应该删除这些文件以便仅在部署 yaml 中设置它? @AdolfoOnrubia 加入chat.***.com/rooms/210803/… 这样我们可以更好地交谈。

以上是关于如何在k8s集群内部前后连接(连接被拒绝)的主要内容,如果未能解决你的问题,请参考以下文章

如何快速查看当前连接的k8s集群?

15分钟连接Jetson Nano与K8S,轻松搭建机器学习集群

Hadoop 集群设置:连接被拒绝错误

Hadoop 集群环境中 Mapreduce 作业的连接被拒绝

连接被拒绝,如何解决?

Debezium 如何使用 Kafka Connect 正确注册 SqlServer 连接器 - 连接被拒绝