如何在没有转发规则的情况下将 kubernetes pod 连接到外部世界(谷歌容器引擎)

问题描述 投票:0回答:3

我正在使用 Google 的容器引擎服务,并且有一个 pod 运行在端口 3000 上侦听的服务器。我设置了该服务以将端口 80 连接到该 pod 的端口 3000。我能够使用其本地和公共 IP 来卷曲该服务来自节点内部,但不是来自外部。我设置了防火墙规则以允许端口 80 并将其发送到节点,但我不断收到来自网络外部的“连接被拒绝”。我尝试在没有转发规则的情况下执行此操作,因为只有一个 Pod,而且转发规则看起来需要花钱并进行负载平衡。我认为防火墙规则有效,因为当我将

createExternalLoadBalancer: true
添加到服务规范时,转发规则创建的外部 IP 将按预期工作。我还需要做其他事情吗?设置路线什么的?

控制器.yaml

kind: ReplicationController
apiVersion: v1beta3
metadata:
    name: app-frontend
    labels:
        name: app-frontend
        app: app
        role: frontend
spec:
    replicas: 1
    selector:
        name: app-frontend
    template:
        metadata:
            labels:
                name: app-frontend
                app: app
                role: frontend
        spec:
            containers:
                - name: node-frontend
                  image: gcr.io/project_id/app-frontend
                  ports:
                    - name: app-frontend-port
                      containerPort: 3000
                      targetPort: 3000
                      protocol: TCP

服务.yaml

kind: Service
apiVersion: v1beta3
metadata:
  name: app-frontend-service
  labels:
    name: app-frontend-service
    app: app
    role: frontend
spec:
  ports:
    - port: 80
      targetPort: app-frontend-port
      protocol: TCP
  externalIPs: #previously publicIPs
   - 123.45.67.89
  selector:
    name: app-frontend

编辑(其他详细信息): 创建此服务会添加这些附加规则,这些规则是我运行时发现的

iptables -L -t nat

Chain KUBE-PORTALS-CONTAINER (1 references)
target     prot opt source               destination         
REDIRECT   tcp  --  anywhere             10.247.247.206       /* default/app-frontend-service: */ tcp dpt:http redir ports 56859
REDIRECT   tcp  --  anywhere             89.67.45.123.bc.googleusercontent.com  /* default/app-frontend-service: */ tcp dpt:http redir ports 56859
Chain KUBE-PORTALS-HOST (1 references)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             10.247.247.206       /* default/app-frontend-service: */ tcp dpt:http to:10.241.69.28:56859
DNAT       tcp  --  anywhere             89.67.45.123.bc.googleusercontent.com  /* default/app-frontend-service: */ tcp dpt:http to:10.241.69.28:56859

我不太了解 iptables,所以我不确定目标端口如何与我的服务匹配。我发现

89.67.45.123.bc.googleusercontent.com
的 DNS 解析为
123.45.67.89

kubectl get services 显示我指定的 IP 地址和端口:

NAME                             IP(S)               PORT(S)
app-frontend-service             10.247.243.151      80/TCP
                                 123.45.67.89

/var/log/kube-proxy.log 中没有显示任何来自外部 IP 的最新信息

firewall kubernetes google-kubernetes-engine
3个回答
6
投票

TL;DR:使用节点的内部 IP 作为服务定义中的公共 IP。


如果您在 kube-proxy 上启用详细日志记录,您将看到它似乎正在创建适当的 IP 表规则:

I0602 04:07:32.046823   24360 roundrobin.go:98] LoadBalancerRR service "default/app-frontend-service:" did not exist, created
I0602 04:07:32.047153   24360 iptables.go:186] running iptables -A [KUBE-PORTALS-HOST -t nat -m comment --comment default/app-frontend-service: -p tcp -m tcp -d 10.119.244.130/32 --dport 80 -j DNAT --to-destination 10.240.121.42:36970]
I0602 04:07:32.048446   24360 proxier.go:606] Opened iptables from-host portal for service "default/app-frontend-service:" on TCP 10.119.244.130:80
I0602 04:07:32.049525   24360 iptables.go:186] running iptables -C [KUBE-PORTALS-CONTAINER -t nat -m comment --comment default/app-frontend-service: -p tcp -m tcp -d 23.251.156.36/32 --dport 80 -j REDIRECT --to-ports 36970]
I0602 04:07:32.050872   24360 iptables.go:186] running iptables -A [KUBE-PORTALS-CONTAINER -t nat -m comment --comment default/app-frontend-service: -p tcp -m tcp -d 23.251.156.36/32 --dport 80 -j REDIRECT --to-ports 36970]
I0602 04:07:32.052247   24360 proxier.go:595] Opened iptables from-containers portal for service "default/app-frontend-service:" on TCP 23.251.156.36:80
I0602 04:07:32.053222   24360 iptables.go:186] running iptables -C [KUBE-PORTALS-HOST -t nat -m comment --comment default/app-frontend-service: -p tcp -m tcp -d 23.251.156.36/32 --dport 80 -j DNAT --to-destination 10.240.121.42:36970]
I0602 04:07:32.054491   24360 iptables.go:186] running iptables -A [KUBE-PORTALS-HOST -t nat -m comment --comment default/app-frontend-service: -p tcp -m tcp -d 23.251.156.36/32 --dport 80 -j DNAT --to-destination 10.240.121.42:36970]
I0602 04:07:32.055848   24360 proxier.go:606] Opened iptables from-host portal for service "default/app-frontend-service:" on TCP 23.251.156.36:80

使用

-L -t
列出 iptables 条目显示公共 IP 变成了反向 DNS 名称,就像您看到的那样:

Chain KUBE-PORTALS-CONTAINER (1 references)
target     prot opt source               destination         
REDIRECT   tcp  --  anywhere             10.119.240.2         /* default/kubernetes: */ tcp dpt:https redir ports 50353
REDIRECT   tcp  --  anywhere             10.119.240.1         /* default/kubernetes-ro: */ tcp dpt:http redir ports 54605
REDIRECT   udp  --  anywhere             10.119.240.10        /* default/kube-dns:dns */ udp dpt:domain redir ports 37723
REDIRECT   tcp  --  anywhere             10.119.240.10        /* default/kube-dns:dns-tcp */ tcp dpt:domain redir ports 50126
REDIRECT   tcp  --  anywhere             10.119.244.130       /* default/app-frontend-service: */ tcp dpt:http redir ports 36970
REDIRECT   tcp  --  anywhere             36.156.251.23.bc.googleusercontent.com  /* default/app-frontend-service: */ tcp dpt:http redir ports 36970

但是添加

-n
选项会显示 IP 地址(默认情况下,
-L
对 IP 地址进行反向查找,这就是您看到 DNS 名称的原因):

Chain KUBE-PORTALS-CONTAINER (1 references)
target     prot opt source               destination         
REDIRECT   tcp  --  0.0.0.0/0            10.119.240.2         /* default/kubernetes: */ tcp dpt:443 redir ports 50353
REDIRECT   tcp  --  0.0.0.0/0            10.119.240.1         /* default/kubernetes-ro: */ tcp dpt:80 redir ports 54605
REDIRECT   udp  --  0.0.0.0/0            10.119.240.10        /* default/kube-dns:dns */ udp dpt:53 redir ports 37723
REDIRECT   tcp  --  0.0.0.0/0            10.119.240.10        /* default/kube-dns:dns-tcp */ tcp dpt:53 redir ports 50126
REDIRECT   tcp  --  0.0.0.0/0            10.119.244.130       /* default/app-frontend-service: */ tcp dpt:80 redir ports 36970
REDIRECT   tcp  --  0.0.0.0/0            23.251.156.36        /* default/app-frontend-service: */ tcp dpt:80 redir ports 36970

此时,您可以使用内部和外部IP从集群内部访问服务:

$ curl 10.119.244.130:80
app-frontend-5pl5s
$ curl 23.251.156.36:80
app-frontend-5pl5s

在不添加防火墙规则的情况下,尝试远程连接公网IP会超时。如果您添加防火墙规则,那么您将可靠地拒绝连接:

$ curl 23.251.156.36
curl: (7) Failed to connect to 23.251.156.36 port 80: Connection refused

如果您启用某些 iptables 日志记录:

sudo iptables -t nat -I KUBE-PORTALS-CONTAINER -m tcp -p tcp --dport 
80 -j LOG --log-prefix "WTF: "

然后 grep

dmesg
的输出,发现
WTF
很明显,数据包到达虚拟机的 10. IP 地址,而不是已在服务上设置为公共 IP 的临时外部 IP 地址。

事实证明,问题在于GCE有两种类型的外部IP:ForwardingRules(将DSTIP完好无损地转发)和1对1 NAT(实际上将DSTIP重写为内部IP)。 VM 的外部 IP 是后者类型,因此当节点收到数据包时,IP 表规则不匹配。

修复实际上非常简单(但不直观):使用节点的内部 IP 作为服务定义中的公共 IP。更新您的 service.yaml 文件以将 publicIPs 设置为内部 IP(例如

10.240.121.42
)后,您将能够从 GCE 网络外部访问您的应用程序。


0
投票

如果将节点的外部 IP 地址添加到服务的

publicIPs
字段,则您应该能够通过节点的 IP 地址访问它。如果您的集群有多个节点,并且您想允许访问其中任何一个节点上的 pod,则可以将多个节点的 IP 地址放入该字段中。

在即将发布的版本中,将有一个更简单的内置选项,用于在没有负载均衡器的情况下设置外部服务。如果您好奇或将来某个时候阅读本文,请查看此文档的更新的“外部服务”部分,了解如何使用

NodePort
更轻松地完成相同的事情。


0
投票

@Robert Bailey 的回答绝对正确。 publicIPs 在 kubernetes 1.5.1 中已被弃用,您可以使用 externalIPs 代替。

  • 获取节点内部ip,
    kubectl describe node | grep Address

    Addresses:     10.119.244.130,101.192.150.200,gke-...
  • 或者您可以在节点终端内运行

    ifconfig eth0
    来获取内部ip

  • 在service.yaml中设置ip

    
    spec:
      type: NodePort
      externalIPs:
        - 10.119.244.130
    

  • 可以卷曲并决心测试
    curl --resolve 'example.com:443:23.251.156.36' https://example.com -k
© www.soinside.com 2019 - 2024. All rights reserved.