【问题标题】:Kubernetes - How to access nginx load balancing from outside the cluster using a NodePort serviceKubernetes - 如何使用 NodePort 服务从集群外部访问 nginx 负载平衡
【发布时间】:2018-10-27 20:05:07
【问题描述】:

我有一个 Kubernetes 集群,其中包含一个主节点和两个其他节点:

sudo kubectl get nodes
NAME                STATUS    ROLES     AGE       VERSION
kubernetes-master   Ready     master    4h        v1.10.2
kubernetes-node1    Ready     <none>    4h        v1.10.2
kubernetes-node2    Ready     <none>    34m       v1.10.2

它们每个都在 VirtualBox Ubuntu VM 上运行,可从来宾计算机访问:

kubernetes-master (192.168.56.3)
kubernetes-node1  (192.168.56.4)
kubernetes-node2 (192.168.56.6)

我部署了一个有两个副本的 nginx 服务器,每个 kubernetes-node-x 有一个 pod:

sudo kubectl get pods -o wide
NAME                                READY     STATUS    RESTARTS   AGE       IP               NODE
nginx-deployment-64ff85b579-5k5zh   1/1       Running   0          8s        192.168.129.71   kubernetes-node1
nginx-deployment-64ff85b579-b9zcz   1/1       Running   0          8s        192.168.22.66    kubernetes-node2

接下来,我将 nginx-deployment 的服务公开为 NodePort,以便从集群外部访问它:

sudo kubectl expose deployment/nginx-deployment --type=NodePort

sudo kubectl get services 
NAME               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes         ClusterIP   10.96.0.1      <none>        443/TCP        4h
nginx-deployment   NodePort    10.96.194.15   <none>        80:32446/TCP   2m

sudo kubectl describe service nginx-deployment
Name:                     nginx-deployment
Namespace:                default
Labels:                   app=nginx
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.96.194.15
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  32446/TCP
Endpoints:                192.168.129.72:80,192.168.22.67:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

我可以使用节点 IP 直接访问节点中的每个 pod

kubernetes-node1 http://192.168.56.4:32446/
kubernetes-node2 http://192.168.56.6:32446/

但是,我认为 K8s 提供了某种外部集群 ip 来平衡从外部对节点的请求。那个IP是什么??

【问题讨论】:

    标签: nginx kubernetes virtualbox kubernetes-service


    【解决方案1】:

    但是,我认为 K8s 提供了某种外部集群 ip 来平衡从外部对节点的请求。那个IP是什么??

    • 集群 IP 在集群内部。不暴露在外面,是为了跨集群互通。

    • 确实,您拥有 LoadBanacer 类型的服务,可以完成您需要的这种技巧,只是它依赖于云提供商或 minikube/docker edge 才能正常工作。

    我可以使用节点 IP 直接访问节点中的每个 pod

    • 实际上,您不会以这种方式单独访问它们。 NodePort 做了一些不同的技巧,因为它本质上是在任何公开的节点 IP 上对来自外部的请求进行负载平衡。简而言之,如果您使用暴露的 NodePort 访问任何节点的 IP,kube-proxy 将确保所需的服务获取它,然后服务通过活动 pod 进行循环,因此尽管您访问了特定的节点 IP,但您不会必须让 pod 在该特定节点上运行。您可以在此处找到更多详细信息:https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0,正如那里的作者所说,这在技术上不是最准确的表示,而是尝试在逻辑层面上显示 NodePort 暴露发生了什么:

    • 作为旁注,为了在裸机上执行此操作并执行 ssl 等,您需要提供自己的入口。比如说,将一个 nginx 放在特定节点上,然后将所有您想要公开的适当服务(请注意 fqdn 服务)作为上游引用,这些服务可以在多个节点上运行,并且可以根据需要使用尽可能多的 nginx - 您不需要处理这方面的确切细节,因为 k8s 运行这个节目。这样一来,您就拥有一个具有已知 IP 地址的节点点(入口 nginx),该地址正在处理传入流量并将其重定向到 k8s 内可以跨任何节点运行的服务。我对 ascii 艺术很烂,但会试一试:

      (outside) -> ingress (nginx) +--> my-service FQDN (running accross nodes):
                   [node-0]        |      [node-1]: my-service-pod-01 with nginx-01
                                   |      [node 2]: my-service-pod-02 with nginx-02
                                   |      ...
                                   +--> my-second-service FQDN
                                   |      [node-1]: my-second-service-pod with apache?
                                   ...
      

      在上面的草图中,您在 node-0(已知 IP)上有 nginx 入口,它接收外部流量,然后处理 my-service(在两个节点上的两个 pod 上运行)和 my-second-service(单个 pod)作为上游。您只需在服务上公开 FQDN 即可使其正常工作,而无需担心特定节点 IP 的详细信息。您可以在文档中找到更多信息:https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/

      也比我的 ansi-art 更好的是这个表示来自与前一点相同的链接,它说明了 ingress 背后的想法:

    为 cmets 更新

    为什么服务不对服务中使用的 pod 进行负载均衡?

    • 这可能有几个原因。根据您的 Liveness 和 Readiness Probes 的配置方式,也许 service 仍然没有看到 pod 停止服务。由于分布式系统(例如 k8s)中的这种异步特性,当 Pod 被移除时,我们会遇到暂时丢失请求的情况,例如滚动更新等。其次,根据你的 kube-proxy 的配置方式,有一些选项可以限制它。通过使用 --nodeport-addresses 的官方文档 (https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport),您可以更改节点代理行为。原来循环是旧的 kube-proxy 行为,显然新的应该是随机的。最后,为了从浏览器中排除连接和会话问题,您是否也从匿名会话中尝试过这个?您是否在本地缓存了 dns?

    另外,我杀死了 node1 的 pod,当调用 node1 时它没有使用 node 2 的 pod。

    • 这有点奇怪。可能与上述探针有关。根据官方文件,情况不应该如此。我们让 NodePort 的行为符合上面提到的官方文档:and each Node will proxy that port (the same port number on every Node) into your Service。但如果这是您的情况,那么可能是 LB 或 Ingress,甚至是具有外部地址的 ClusterIP(见下文)也可以为您解决问题。

    如果服务是内部的 (ClusterIP) ... 它是否对节点中的任何 pod 进行负载平衡

    • 绝对是的。还有一件事,您可以使用此行为来公开“标准”端口范围中的“负载平衡”行为,而不是来自 NodePort 的 30k+。这是我们用于入口控制器的服务清单的摘录。

      apiVersion: v1
      kind: Service
      metadata:
          namespace: ns-my-namespace
          name: svc-nginx-ingress-example
          labels:
              name: nginx-ingress-example
              role: frontend-example
              application: nginx-example
      spec:
          selector:
              name: nginx-ingress-example
              role: frontend-example
              application: nginx-example
          ports:
          - protocol: TCP
            name: http-port
            port: 80
            targetPort: 80
          - protocol: TCP
            name: ssl-port
            port: 443
            targetPort: 443
          externalIPs:
          - 123.123.123.123
      

      请注意,在上面的示例中,以externalIPs 公开的虚构 123.123.123.123 表示我们的工作节点之一的 IP 地址。在svc-nginx-ingress-example 服务中运行的 Pod 根本不需要在此节点上,但是当该 ip 在指定端口上命中时,它们仍会将流量路由到它们(并在 Pod 之间进行负载平衡)。

    【讨论】:

    • 感谢您的详尽解释!关于 NodePort 的使用,我仍然有一些不明白的地方。根据提供的链接,当我通过一个节点访问时,假设192.168.56.4:32446,该服务有时应该将请求从node1发送到nginx pod,而其他请求则从node2发送到nginx pod。但是,在两个 pod 上使用 kubectl 日志,我发现它始终使用同一节点(node1)中的 pod。为什么服务不对服务中使用的 pod 进行负载均衡?
    • 别的,我杀死了 node1 的 pod,当调用 node1 时它没有使用 node 2 的 pod。总而言之,唯一的方法(使用 nodeport)通过所有负载平衡服务和 pod y 每个节点都在使用外部负载均衡器 (aws elb) 还是入口控制器?我说的对吗?
    • 最后一个问题 :-) :如果服务是内部的(ClusterIP),则有一个 clusterIP IP 地址。想象一下,每个节点都有 3 个带有 nginx 的节点。使用node1中的集群ip访问nginx应用,是否负载均衡到节点1、2、3中的任意一个pod?
    • 感谢您的反馈,我已更新答案以尝试解决 cmets 中的问题。
    • 感谢您抽出宝贵时间回答,您确实帮助我理清了这些概念。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多