具有externalIP的ClusterIP-无法从集群外部访问

时间:2020-07-29 06:10:08

标签: kubernetes google-kubernetes-engine

过去,我曾尝试过NodePort服务,如果我将防火墙规则添加到相应的节点,则它的工作原理就像一种魅力:

  type: NodePort
  ports:
    - nodePort: 30000
      port: 80
      targetPort: 5000

我可以从外部访问我的服务,只要该节点具有外部IP(GKE默认情况下就可以这样做)即可。 但是,只能将服务分配给30000+个范围端口,这不是很方便。 顺便说一下,该服务如下所示:

 kubectl get service -o=wide
NAME                     TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE   SELECTOR
web-engine-service   NodePort   10.43.244.110   <none>        80:30000/TCP   11m   app=web-engine-pod

最近,我遇到了here中记录的另一个配置选项。 我已经尝试过,因为它似乎很有前途,应该允许在我想要的任何端口上公开我的服务。
配置如下:

  ports:
    - name: web-port
      port: 80
      targetPort: 5000
  externalIPs:
    - 35.198.163.215

服务更新后,我可以看到确实为它分配了外部IP:

$ kubectl get service -o=wide
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP      PORT(S)   AGE   SELECTOR
web-engine-service   ClusterIP   10.43.244.110   35.198.163.215   80/TCP    19m   app=web-engine-pod

(其中35.198.163.215-GKE中节点的外部IP)

但是,与第一种情况不同,我的应用程序无法在节点的IP上使用(我确实为正在使用的所有端口(包括805000,{{ 1}})。

那么30000配置的意义何在?它实际上是做什么的?

注意:我正在创建一个演示项目,所以请不要告诉我有关externalIPs类型的信息,我对此非常清楚,稍后会介绍到此。

2 个答案:

答案 0 :(得分:1)

API documentation中,externalIPs被记录为(强调我的):

externalIPs是IP地址的列表,群集中的节点也将为其接受此服务的通信的IP地址。 这些IP不受Kubernetes管理。用户负责确保流量通过此IP到达节点。一个常见的例子是外部负载均衡器,它不是Kubernetes系统的一部分。

因此您可以在其中放置任何IP地址,它将显示在kubectl get service输出中,但这并不意味着集群实际上将在此处接受流量。

要接受来自群集外部的入站流量,您至少需要一个NodePort服务;在云环境中,LoadBalancer服务或Ingress是更常见的设置。您不能真正捷径这些。相反,LoadBalancer并不是特别高级或困难,只需更改已经显示的配置中的type: LoadBalancer,GKE就会为您创建端点。 GKE documentation有一个更完整的示例。

(“群集内”和“群集外”是不同的网络,和其他NAT设置一样,pod通常可以发出出站呼叫,但是您需要特定的设置才能接受入站呼叫。这就是NodePort服务所做的,并且标准设置,LoadBalancer服务将基于此设置。)

答案 1 :(得分:1)

我想为您提供更多信息:

  • 您如何设法使其正常工作。
  • 为什么在您的示例中它不起作用。
  • 有关在GKE上公开流量的更多信息。

您如何设法使其正常工作?

您需要在externalIP所在的服务定义中输入节点的内部IP

示例:

apiVersion: v1
kind: Service
metadata:
  name: hello-external
spec:
  selector:
    app: hello
    version: 2.0.0
  ports:
    - name: http
      protocol: TCP
      port: 80 # port to send the traffic to
      targetPort: 50001 # port that pod responds to 
  externalIPs:
    - 10.156.0.47
    - 10.156.0.48
    - 10.156.0.49

为什么在您的示例中它不起作用?

我准备了一个示例,向您展示为什么它不起作用。

假设您拥有:

    GCP中的
  • VM,具有:
    • 允许运行tcpdump的任何操作系统
    • 10.156.0.51的内部IP
    • 35.246.207.189的外部IP
    • 允许流量进入此虚拟机的端口:1111

您可以在虚拟机上的命令(在VM上)下运行,以捕获进入端口的流量:1111

  • $ tcpdump port 1111 -nnvvS
  • -nnvvS-不解析DNS或端口名称,在打印信息时更为冗长,打印绝对序列号

您将需要通过以下端口向虚拟机的外部IP:35.246.207.189发送请求:1111

  • $ curl 35.246.207.189:1111

您将收到一条连接被拒绝的消息,但该数据包将被捕获。您将获得类似于以下的输出:

tcpdump: listening on ens4, link-type EN10MB (Ethernet), capture size 262144 bytes
12:04:25.704299 IP OMMITED 
    YOUR_IP > 10.156.0.51.1111: Flags [S], cksum 0xd9a8 (correct), seq 585328262, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 1282380791 ecr 0,sackOK,eol], length 0
12:04:25.704337 IP OMMITED
    10.156.0.51.1111 > YOUR_IP: Flags [R.], cksum 0x32e3 (correct), seq 0, ack 585328263, win 0, length 0

通过该示例,您可以看到数据包到达虚拟机的目标IP地址。如上所示,它是VM的内部IP ,而不是外部的。这就是为什么在您的YAML定义中添加外部IP无法正常工作的原因。

此示例也适用于GKE。为简单起见,您可以创建一个以Ubuntu为基础映像的GKE集群,并按上面所示进行操作。

您可以通过以下链接了解有关IP地址的更多信息:


有关在GKE上公开流量的更多信息

那么externalIPs配置的意义何在?它实际上是做什么的?

简单来说,它将允许流量进入您的集群。发送到集群的请求将具有与服务定义中的externalIP参数相同的目标IP,才能路由到相应的服务。

此方法要求您跟踪节点的IP地址,并且当节点的IP地址不可用(例如,节点自动缩放)时,可能会出现问题。

我建议您通过遵循官方GKE文档公开服务/应用程序:

如前所述,LoadBalancer服务类型将自动考虑对集群所做的更改。诸如自动缩放之类的事情会增加/减少节点数。使用上面显示的服务(带有externalIP),这将需要手动更改。

如果您对此有任何疑问,请告诉我。