代码之家  ›  专栏  ›  技术社区  ›  codependent

Kubernetes——如何使用节点端口服务从集群外部访问nginx负载平衡

  •  3
  • codependent  · 技术社区  · 6 年前

    我有一个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部署的服务公开为节点端口,以便从集群外部访问它:

    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是什么??

    1 回复  |  直到 6 年前
        1
  •  6
  •   Const    6 年前

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

    • 群集IP位于群集内部。它不暴露于外部,用于集群内的相互通信。

    • 事实上,你有LoadBanacer类型的服务,可以实现你所需要的技巧,只是它依赖于云提供商或minikube/docker edge才能正常工作。

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

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

    NodePort Illustration

    • 作为旁注,为了在裸机上实现这一点,以及进行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?
                                   ...
      

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

      与我的ansi艺术相比,这一点也更好,因为这一点与前一点相同,说明了入口背后的想法: Ingress Illustration

    更新以供评论

    为什么服务的负载不能平衡服务中使用的pod?

    • 发生这种情况有几个原因。根据你们的活跃度和准备度探测器是如何配置的,也许服务部门仍然不认为pod已经停止服务。由于在k8s等分布式系统中的这种异步性质,当POD在滚动更新等过程中被移除时,我们会遇到暂时的请求丢失。其次,根据kube代理的配置方式,有一些选项可以限制它。通过官方文件( https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport )使用 --nodeport-addresses 可以更改节点代理行为。事实证明,循环是旧的库贝代理行为,显然新的应该是随机的。最后,为了从浏览器中排除连接和会话问题,您是否也从匿名会话中尝试了此操作?你有本地缓存的dns吗?

    还有一件事,我杀死了节点1的pod,当呼叫节点1时,它没有使用节点2的pod。

    • 这有点奇怪。可能与上述探针有关。根据官方文件,情况不应如此。我们的NodePort行为与上述官方文件一致: and each Node will proxy that port (the same port number on every Node) into your Service 但是如果你是这样的话,那么可能LB或Ingress,甚至可能是带有外部地址的ClusterIP(见下文)都可以帮你解决这个问题。

    如果服务是内部的(ClusterIP)。。。它对节点中的任何吊舱都有负载平衡吗

    • 绝对是的。还有一件事,您还可以使用此行为公开“标准”端口范围内的“负载平衡”行为,而不是来自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
      

      注意,在上面的示例中,假设123.123.123.123是用 externalIPs 表示一个工作节点的ip地址。飞来飞去的豆荚 svc-nginx-ingress-example 服务根本不需要在这个节点上,但当ip在指定的端口上被点击时,它们仍然可以获得路由到它们的流量(以及POD之间的负载平衡)。