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

Kubernetes-如何使用节点端口服务从集群外部访问nginx负载平衡,nginx,kubernetes,virtualbox,kubernetes-service,Nginx,Kubernetes,Virtualbox,Kubernetes Service,我有一个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-nod

我有一个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
我部署了一台带有两个副本的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>
但是,我认为K8s提供了某种外部集群ip,可以平衡从外部到节点的请求。那是什么IP

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

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

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

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

kubernetes-node1 http://192.168.56.4:32446/
kubernetes-node2 http://192.168.56.6:32446/
  • 事实上,你不能单独访问它们。NodePort的做法有点不同,因为它本质上是在任何公开的节点IP上对来自外部的请求进行负载平衡。简而言之,如果您使用暴露的NodePort访问任何节点的IP,kube proxy将确保所需的服务获得它,然后服务通过活动的pod进行循环,所以尽管您访问了特定的节点IP,但您不必在该特定节点上运行pod。关于这方面的更多细节,您可以在这里找到:,正如作者所说,这并不是技术上最准确的表示,而是试图在逻辑级别上显示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?
                                 ...
    
    在上面的草图中,节点0(已知IP)上有nginx入口,它接收外部流量,然后将我的服务(在两个节点上的两个pod上运行)和我的第二个服务(单个pod)作为上游处理。您只需在服务上公开FQDN即可使其工作,而无需担心特定节点的IP的详细信息。您可以在文档中找到更多信息:

    同样比我的ansi艺术更好的是,这一点与前一点相同,说明了入口背后的想法:

更新以征求意见 为什么服务负载不能平衡服务中使用的POD

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

另外,我杀死了节点1的pod,当调用节点1时,它没有使用节点2的pod

  • 这有点奇怪。可能与上述探针有关。根据官方文件,情况不应如此。我们的NodePort行为与上面定义的官方文档一致:
    ,每个节点将代理该端口(每个节点上的端口号相同)到您的服务中
    。但如果是这样的话,那么可能是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
    
    请注意,在上面的示例中,使用
    externalIPs
    公开的123.123.123.123表示我们的一个工作节点的ip地址。运行在svc nginx ingress example服务中的POD根本不需要位于该节点上,但当该ip在指定端口上被命中时,它们仍然可以获得路由到它们的流量(以及POD之间的负载平衡)


非常感谢您的详细解释!不过,关于NodePort的使用,我还是有一些不明白的地方。根据提供的链接,当我通过一个节点进行访问时,我们假设服务有时应该从node1向nginx pod发送请求,从node2向nginx pod发送请求。但是,在两个pod上使用kubectl日志时,我发现它总是在同一个节点(node1)中使用pod。为什么服务负载不平衡服务中使用的pod?另外,我杀死了node1中的pod,当调用node1时,它没有使用Node2中的pod。总之,通过所有服务和POD实现负载平衡的唯一方法(使用nodeport)是使用外部负载平衡器(aws elb)还是入口控制器?我说的对吗?最后一个问题:-):如果服务是内部的(ClusterIP),那么就有一个ClusterIP地址。伊玛
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