首页 文章

Kubernetes - 如何使用NodePort服务从集群外部访问nginx负载 balancer

提问于
浏览
1

我有一个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,它可以 balancer 来自外部的节点请求 . 什么是IP?

1 回答

  • 2

    但是,我认为K8s提供了某种外部集群ip,可以 balancer 来自外部的节点请求 . 什么是IP?

    • 群集IP是群集内部的 . 不暴露于外部,它用于跨群集的相互通信 .

    • 实际上,您有LoadBanacer类型的服务可以执行您需要的这种技巧,只有它依赖于 Cloud 提供商或minikube / docker边缘才能正常工作 .

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

    NodePort Illustration

    • 作为旁注,为了在裸机上执行此操作并执行ssl等,您需要提供自己的入口 . 比如说,在特定节点上放置一个nginx,然后引用你想要暴露的所有适当的服务(请注意服务的fqdn)作为可以在多个节点上运行的上游,并且根据需要使用自己的nginx - 你不需要处理确切的细节,因为k8s运行节目 . 这样,您就有了一个节点(入口nginx),该节点具有已知的IP地址,可处理传入流量并将其重定向到可在任何节点上运行的k8内的服务 . 我厌倦了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上运行)和my-second-service(单个pod)作为上游 . 您只需在服务上公开FQDN即可使用,而无需担心特定节点的IP细节 . 您可以在文档中找到更多信息:https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/

    也比我的ansi-art更好的方式是来自前一点的相同链接的表示,说明了入口背后的想法:
    Ingress Illustration

    已更新评论

    为什么服务负载不能 balancer 服务中使用过的pod?

    • 出现这种情况有几个原因 . 根据您的实时和准备探针的配置方式,可能服务仍然不会将pod视为停止服务 . 由于分布式系统(例如k8s)中的这种异步性质,我们会遇到暂停丢失请求,例如滚动更新等等 . 其次,根据您的kube-proxy的配置方式,您可以选择限制它 . 通过使用 --nodeport-addresses 的官方文档(https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport),您可以更改节点代理行为 . 事实证明,循环法是旧的kube-proxy行为,显然新的应该是随机的 . 最后,要从浏览器中排除连接和会话问题,您是否也尝试过匿名会话?你有本地缓存的dns吗?

    别的,我从node1中删除了pod,当调用node1时,它没有使用节点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进行负载 balancer

    • 绝对是的 . 还有一件事,您可以使用此行为在“标准”端口范围内公开“负载 balancer ”行为,而不是从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中进行负载均衡) .

相关问题