Kubernetes 服务连接被拒绝

时间:2021-07-07 07:16:18

标签: kubernetes minikube kubernetes-pod docker-image kubernetes-service

我正在尝试在 Kubernetes (Minikube) 中创建一个应用程序,并将其服务公开给同一集群中的其他应用程序,但如果我尝试在 Kubernetes 节点中访问此服务,我的连接被拒绝。

此应用程序仅侦听 HTTP 127.0.0.1:9897 地址并发送响应。

以下是我的 yaml 文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: exporter-test
  namespace: datenlord-monitoring
  labels:
    app: exporter-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: exporter-test
  template:
    metadata:
      labels:
        app: exporter-test
    spec:
      containers:
        - name: prometheus
          image: 34342/hello_world
          ports:
            - containerPort: 9897

---
apiVersion: v1
kind: Service
metadata:
  name: exporter-test-service
  namespace: datenlord-monitoring
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/port:   '9897'
spec:
  selector: 
    app: exporter-test
  type: NodePort  
  ports:
    - port: 8080
      targetPort: 9897
      nodePort: 30001

在我应用这个 yaml 文件后,pod 和服务部署正确,我确信这个 pod 工作正常,因为当我登录 pod 时 kubectl exec -it exporter-test-* -- sh,然后运行curl 127.0.0.1:9897,我可以得到正确的响应。

另外,如果我运行 kubectl port-forward exporter-test-* -n datenlord-monitoring 8080:9897,我可以从 localhost:8080 得到正确的响应。所以这个应用程序应该运行良好。

但是,当我尝试通过 exporter-test-service.datenlord-monitoring.svc:30001 从同一 K8s 集群中的其他应用程序访问此服务或仅在 k8s 节点中运行 curl nodeIp:30001 或在 k8s 节点中运行 curl clusterIp:8080 时,我得到了 { {1}}

有人遇到过同样的问题吗?感谢您的帮助!谢谢!

2 个答案:

答案 0 :(得分:0)

你在这里混合了两件事。 NodePort 是应用程序可从集群外部使用的端口。在集群内部,您需要通过服务端口而不是 NodePort 访问您的服务。

尝试将 exporter-test-service.datenlord-monitoring.svc:30001 更改为 exporter-test-service.datenlord-monitoring.svc:8080

答案 1 :(得分:0)

欢迎来到社区!

您观察到的行为没有问题。 简而言之,kubernetes 集群(在本例中为 minikube)有自己的隔离网络,内部 DNS。

在节点上访问您的服务的一种方式:您为您的服务指定了 nodePort,这使得该服务可以在 localhost:30001 上访问。您可以通过在您的主机上运行来检查它:

$ kubectl get svc -n datenlord-monitoring

NAME                    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
exporter-test-service   NodePort   10.111.191.159   <none>        8080:30001/TCP   2m45s

# Test:

curl -I localhost:30001
HTTP/1.1 200 OK

另一种向主机网络公开服务的方法是使用 minikube tunnel(在另一个控制台中运行)。您需要将服务类型从 NodePort 更改为 LoadBalancer

$ kubectl get svc -n datenlord-monitoring

NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)          AGE
exporter-test-service   LoadBalancer   10.111.191.159   10.111.191.159   8080:30001/TCP   18m

# Test:

$ curl -I 10.111.191.159:8080
HTTP/1.1 200 OK

为什么有些选项不起作用。

通过服务的 DNS + NodePort 连接到服务。 NodePort 用于将主机 IP 和 NodePort 链接到 kubernetes 集群内的服务端口。在 kubernetes 集群之外无法访问内部 DNS(除非您不在主机上向 /etc/hosts 添加 IP)

在集群内部,您应该使用内部 DNS 和内部服务端口,在您的情况下为 8080。您可以使用同一命名空间中的单独容器(例如图像 curlimages/curl)检查它是如何工作的,并获得以下信息:

$ kubectl exec -it curl -n datenlord-monitoring -- curl -I exporter-test-service:8080
HTTP/1.1 200 OK

或者来自不同命名空间中的 pod:

$ kubectl exec -it curl-default-ns -- curl -I exporter-test-service.datenlord-monitoring.svc:8080
HTTP/1.1 200 OK

我附上了有用的链接,可以帮助您了解这种差异。

编辑:部署的 pod 内的 DNS

$ kubectl exec -it exporter-test-xxxxxxxx-yyyyy -n datenlord-monitoring -- bash

root@exporter-test-74cf9f94ff-fmcqp:/# cat /etc/resolv.conf 
nameserver 10.96.0.10
search datenlord-monitoring.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

有用的链接: