当前位置:   article > 正文

Kubernetes Service NodePort 外网访问、LoadBalancer

nodeport

Service类型


NodePort(集群外部访问)

Service 通过Cluster节点的静态端口对外提供服务,Cluster 外部可以通过 <NodeIP>:<NodePort> 访问Service。

在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。 访问地址:<任意NodeIP>:<NodePort>    端口范围:30000-32767

除了 Cluster 内部可以访问 Service,很多情况我们也希望应用的 Service 能够暴露给 Cluster 外部。Kubernetes 提供了多种类型的 Service,默认是 ClusterIP。

ClusterIP(集群内部访问) 
Service 通过 Cluster 内部的 IP 对外提供服务,只有 Cluster 内的节点和 Pod 可访问,这是默认的 Service 类型。

LoadBalancer:与NodePort类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node ([NodeIP]:[NodePort])作为后端添加进去

创建测试pod


  1. [root@k8s-master service]# cat pod-nodeport.yml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: pod-nodeport
  6. namespace: default
  7. spec:
  8. replicas: 2
  9. selector:
  10. matchLabels:
  11. app: myapp
  12. template:
  13. metadata:
  14. labels:
  15. app: myapp
  16. spec:
  17. containers:
  18. - name: myapp
  19. image: luksa/kubia
  20. ports:
  21. - containerPort: 8080
  22. [root@k8s-master service]# kubectl get pod -n default -l app=myapp -o wide
  23. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
  24. pod-nodeport-6cc49c7999-5fjdh 1/1 Running 0 13m 10.244.2.14 k8s-node2 <none> <none>
  25. pod-nodeport-6cc49c7999-gdqbg 1/1 Running 0 13m 10.244.0.23 k8s-master <none> <none>

添加 type: NodePort。 

  1. [root@k8s-master service]# cat service.yml
  2. apiVersion: v1
  3. kind: Service
  4. metadata:
  5. name: nodeport-svc
  6. spec:
  7. type: NodePort
  8. selector:
  9. app: myapp
  10. ports:
  11. - protocol: TCP
  12. port: 3000
  13. targetPort: 8080
  14. nodePort: 30090

现在配置文件中就有三个 Port 了:(NodePort默认是的随机选择,不过我们可以用nodePort指定某个特定端口)

  • nodePort 是节点上监听的端口
  • port 是 ClusterIP 上监听的端口
  • targetPort 是 Pod 监听的端口 
  1. [root@k8s-master ~]# kubectl get svc
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40d
  4. nodeport-svc NodePort 10.105.182.209 <none> 3000:30090/TCP 27m

PORT(S) 为 3000:30090。3000是 ClusterIP 监听的端口,30090 则是节点上监听的端口。Kubernetes 会从 30000-32767 中分配一个可用的端口,每个节点都会监听此端口并将请求转发给 Service。

  1. [root@k8s-master service]# netstat -tpln | grep 30090
  2. tcp 0 0 0.0.0.0:30090 0.0.0.0:* LISTEN 34081/kube-proxy
  3. [root@k8s-node1 ~]# netstat -tpln | grep 30090
  4. tcp 0 0 0.0.0.0:30090 0.0.0.0:* LISTEN 32625/kube-proxy
  5. [root@k8s-node2 ~]# netstat -tpln | grep 30090
  6. tcp 0 0 0.0.0.0:30090 0.0.0.0:* LISTEN 14369/kube-proxy

 下面测试 NodePort 是否正常工作。

  1. [root@k8s-master service]# curl 192.168.179.99:30090
  2. You've hit pod-nodeport-6cc49c7999-gdqbg
  3. [root@k8s-master service]# curl 192.168.179.100:30090
  4. You've hit pod-nodeport-6cc49c7999-gdqbg
  5. [root@k8s-master service]# curl 192.168.179.101:30090
  6. You've hit pod-service-7f68854988-5fjdh

通过三个节点 IP + 30090 端口都能够访问 nodeport-svc

底层实现原理


接下来我们深入探讨一个问题:Kubernetes 是如何将 <NodeIP>:<NodePort> 映射到 Pod 的呢?

与 ClusterIP 一样,也是借助了 iptables。与 ClusterIP 相比,每个节点的 iptables 中都增加了下面两条规则:

  1. [root@k8s-master service]# iptables-save | grep 30090
  2. -A KUBE-NODEPORTS -p tcp -m comment --comment "default/nodeport-svc:" -m tcp --dport 30090 -j KUBE-MARK-MASQ
  3. -A KUBE-NODEPORTS -p tcp -m comment --comment "default/nodeport-svc:" -m tcp --dport 30090 -j KUBE-SVC-GFPAJ7EGCNM4QF4H

规则的含义是:访问当前节点 30090 端口的请求会应用规则KUBE-SVC-GFPAJ7EGCNM4QF4H,内容为:

  1. [root@k8s-master service]# iptables-save | grep KUBE-SVC-GFPAJ7EGCNM4QF4H
  2. -A KUBE-SVC-GFPAJ7EGCNM4QF4H -m comment --comment "default/nodeport-svc:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-TWG53VPX4RADGFC6
  3. -A KUBE-SVC-GFPAJ7EGCNM4QF4H -m comment --comment "default/nodeport-svc:" -j KUBE-SEP-YUA4WPOUSEKJIAM2

其作用就是负载均衡到每一个 Pod。 最终,Node 和 ClusterIP 在各自端口上接收到的请求都会通过 iptables 转发到 Pod 的 targetPort

CoreDns解析


  1. [root@k8s-master ~]# kubectl exec -it dns-test -- sh
  2. / # nslookup nodeport-svc
  3. Server: 10.96.0.10
  4. Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
  5. Name: nodeport-svc
  6. Address 1: 10.105.182.209 nodeport-svc.default.svc.cluster.local
  7. / #

NodePort前端负载均衡器


NodePort:会在每台Node上监听端口接收用户流量,在实际情况下,对用户暴露的只会有一个IP和端口,那这么多台Node该使用哪台让用户访问呢?这时就需要前面加一个公网负载均衡器为项目提供统一访问入口了。

一般在搭建k8s集群都是放在内网当中,也就是不暴露在公网上,即使你使用了nodeport暴露了端口,但是在公网上还是访问不到的。所以必须提供公网的ip。

一般在前面加上负载均衡器来为负载均衡器提供统一的访问入口,使用负载均衡器反向代理到后面指定的端口。

一个项目对应一个service,一个service与nodeport对应。通过nginx的虚拟主机基于域名进行分流,转发到不同的端口

  1. upstream demo {
  2. server 192.168.179.103:31964;
  3. server 192.168.179.104:31964;
  4. }
  5. upstream demo2 {
  6. server 192.168.179.103:31965;
  7. server 192.168.179.104:31965;
  8. }
  9. upstream demo3 {
  10. server 192.168.179.103:31966;
  11. server 192.168.179.104:31966;
  12. }
  13. server {
  14. server_name a.xxx.com;
  15. location / {
  16. proxy_pass http://demo;
  17. }
  18. }
  19. server {
  20. server_name b.xxx.com;
  21. location / {
  22. proxy_pass http://demo2;
  23. }
  24. }
  25. server {
  26. server_name c.xxx.com;
  27. location / {
  28. proxy_pass http://demo3;
  29. }
  30. }

如果你还要加项目就是加上面配置就行,基于域名进行分流转发到不同的pod上面

LoadBalancer


在公有云会更加方便一些

LoadBalancer:与NodePort类似,在每个节点上启用一个端口来暴露服务。

除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去。

也即是你在集群里面创建service类型为loadblance,并且部署了支持云上的控制器,就会自动的获取端口和所有节点的IP,并且自动的加入后端。相当于上面nginx操作一样。这样就省事了,不需要手动添加了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/982022
推荐阅读
相关标签
  

闽ICP备14008679号