NodePort:在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。
除了 Cluster 内部可以访问 Service,很多情况我们也希望应用的 Service 能够暴露给 Cluster 外部。Kubernetes 提供了多种类型的 Service,默认是 ClusterIP。
ClusterIP
Service 通过 Cluster 内部的 IP 对外提供服务,只有 Cluster 内的节点和 Pod 可访问,这是默认的 Service 类型。
NodePort
Service 通过 Cluster 节点的静态端口对外提供服务。Cluster 外部可以通过
访问 Service。
LoadBalancer:与NodePort类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node ([NodeIP]:[NodePort])作为后端添加进去
[root@k8s-master service]# cat pod-nodeport.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-nodeport
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: luksa/kubia
ports:
- containerPort: 8080
[root@k8s-master service]# kubectl get pod -n default -l app=myapp -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-nodeport-6cc49c7999-5fjdh 1/1 Running 0 13m 10.244.2.14 k8s-node2
pod-nodeport-6cc49c7999-gdqbg 1/1 Running 0 13m 10.244.0.23 k8s-master
添加 type: NodePort
。
[root@k8s-master service]# cat service.yml
apiVersion: v1
kind: Service
metadata:
name: nodeport-svc
spec:
type: NodePort
selector:
app: myapp
ports:
- protocol: TCP
port: 3000
targetPort: 8080
nodePort: 30090
现在配置文件中就有三个 Port 了:(NodePort默认是的随机选择,不过我们可以用nodePort指定某个特定端口)
- nodePort 是节点上监听的端口
- port 是 ClusterIP 上监听的端口
- targetPort 是 Pod 监听的端口
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 40d
nodeport-svc NodePort 10.105.182.209 3000:30090/TCP 27m
PORT(S)
为 3000:30090
。3000是 ClusterIP 监听的端口,30090
则是节点上监听的端口。Kubernetes 会从 30000-32767 中分配一个可用的端口,每个节点都会监听此端口并将请求转发给 Service。
[root@k8s-master service]# netstat -tpln | grep 30090
tcp 0 0 0.0.0.0:30090 0.0.0.0:* LISTEN 34081/kube-proxy
[root@k8s-node1 ~]# netstat -tpln | grep 30090
tcp 0 0 0.0.0.0:30090 0.0.0.0:* LISTEN 32625/kube-proxy
[root@k8s-node2 ~]# netstat -tpln | grep 30090
tcp 0 0 0.0.0.0:30090 0.0.0.0:* LISTEN 14369/kube-proxy
下面测试 NodePort 是否正常工作。
[root@k8s-master service]# curl 192.168.179.99:30090
You've hit pod-nodeport-6cc49c7999-gdqbg
[root@k8s-master service]# curl 192.168.179.100:30090
You've hit pod-nodeport-6cc49c7999-gdqbg
[root@k8s-master service]# curl 192.168.179.101:30090
You've hit pod-service-7f68854988-5fjdh
通过三个节点 IP + 30090 端口都能够访问 nodeport-svc
。
接下来我们深入探讨一个问题:Kubernetes 是如何将
映射到 Pod 的呢?
与 ClusterIP 一样,也是借助了 iptables。与 ClusterIP 相比,每个节点的 iptables 中都增加了下面两条规则:
[root@k8s-master service]# iptables-save | grep 30090
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/nodeport-svc:" -m tcp --dport 30090 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/nodeport-svc:" -m tcp --dport 30090 -j KUBE-SVC-GFPAJ7EGCNM4QF4H
规则的含义是:访问当前节点 30090
端口的请求会应用规则KUBE-SVC-GFPAJ7EGCNM4QF4H,内容为:
[root@k8s-master service]# iptables-save | grep KUBE-SVC-GFPAJ7EGCNM4QF4H
-A KUBE-SVC-GFPAJ7EGCNM4QF4H -m comment --comment "default/nodeport-svc:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-TWG53VPX4RADGFC6
-A KUBE-SVC-GFPAJ7EGCNM4QF4H -m comment --comment "default/nodeport-svc:" -j KUBE-SEP-YUA4WPOUSEKJIAM2
其作用就是负载均衡到每一个 Pod。 最终,Node 和 ClusterIP 在各自端口上接收到的请求都会通过 iptables 转发到 Pod 的 targetPort
。
[root@k8s-master ~]# kubectl exec -it dns-test -- sh
/ # nslookup nodeport-svc
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: nodeport-svc
Address 1: 10.105.182.209 nodeport-svc.default.svc.cluster.local
/ #
NodePort:会在每台Node上监听端口接收用户流量,在实际情况下,对用户暴露的只会有一个IP和端口,那这么多台Node该使用哪台让用户访问呢?这时就需要前面加一个公网负载均衡器为项目提供统一访问入口了。
一般在搭建k8s集群都是放在内网当中,也就是不暴露在公网上,即使你使用了nodeport暴露了端口,但是在公网上还是访问不到的。所以必须提供公网的ip。
一般在前面加上负载均衡器来为负载均衡器提供统一的访问入口,使用负载均衡器反向代理到后面指定的端口。
一个项目对应一个service,一个service与nodeport对应。通过nginx的虚拟主机基于域名进行分流,转发到不同的端口
upstream demo {
server 192.168.179.103:31964;
server 192.168.179.104:31964;
}
upstream demo2 {
server 192.168.179.103:31965;
server 192.168.179.104:31965;
}
upstream demo3 {
server 192.168.179.103:31966;
server 192.168.179.104:31966;
}
server {
server_name a.xxx.com;
location / {
proxy_pass http://demo;
}
}
server {
server_name b.xxx.com;
location / {
proxy_pass http://demo2;
}
}
server {
server_name c.xxx.com;
location / {
proxy_pass http://demo3;
}
}
如果你还要加项目就是加上面配置就行,基于域名进行分流转发到不同的pod上面
在公有云会更加方便一些
LoadBalancer:与NodePort类似,在每个节点上启用一个端口来暴露服务。
除此之外,Kubernetes会请求底层云平台(例如阿里云、腾讯云、AWS等)上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去。
也即是你在集群里面创建service类型为loadblance,并且部署了支持云上的控制器,就会自动的获取端口和所有节点的IP,并且自动的加入后端。相当于上面nginx操作一样。这样就省事了,不需要手动添加了。