Kubernetes中外部客户端访问Pod的几种方式
kubernetes集群上运行的pod,在集群内访问是很容易的,最简单的,可以通过pod的ip来访问,也可以通过对应的svc来访问,但在集群外,由于kubernetes集群的pod ip地址是内部网络地址,因此从集群外是访问不到的。
为了解决这个问题,kubernetes提供了如下几个方法。
- hostNetwork
- hostPort
- service NodePort
hostNetwork: true
hostNetwork为true时,容器将使用宿主机node的网络,因此,只要知道容器在哪个node上运行,从集群外以 node-ip + port 的方式就可以访问容器的服务。
apiVersion: v1 kind: Pod metadata: name: nginx spec: hostNetwork: true containers: - name: nginx image: nginx
pod启动后,如下,可以看到pod的ip地址与node节点的地址是一致的
[root@localhost ~]# kubectl get pods -o wide nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE nginx 1/1 Running 0 8m2s 192.168.10.10 minikube <none> [root@localhost ~]# kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME minikube Ready master 11d v1.12.1 192.168.10.10 <none> CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://17.12.1-ce
可以通过curl或者浏览器直接访问node节点的地址,即可以访问到nginx的服务
[root@localhost ~]# curl http://192.168.10.10 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...... </html> [root@localhost ~]#
hostNetwork的优点是直接使用宿主机的网络,只要宿主机能访问,Pod就可以访问;但缺点也是很明显的:
- 易用性:Pod漂移到其他node上,访问时需要更换ip地址。解决方法是将Pod绑定在某几个node上,并在这几个node上运行keepalived以漂移vip,从而客户端可以使用vip+port的方式来访问。
- 易用性:Pod间可能出现端口冲突,造成Pod无法调度成功。
- 安全性:Pod可以直接观察到宿主机的网络。
hostPort
hostPort的效果与hostNetwork类似,hostPort
是直接将容器的端口与所调度的节点上的端口进行映射,这样用户就可以通过宿主机的IP加上映射到绑定主机的端口来访问Pod了
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 #pod容器指定的端口 hostPort: 9090 #映射到node主机的端口
pod启动后如下,可以看到,pod的ip地址是内部网络ip,与宿主机node的ip不同;与hostNetwork一样,也可以通过node ip + pod port访问,此处的访问port地址为,pod容器端口映射到node主机的端口地址
[root@localhost ~]# kubectl get pods -o wide nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE nginx 1/1 Running 0 57s 172.17.0.2 minikube <none> [root@localhost ~]#
可以curl访问,也可以浏览器访问
[root@localhost ~]# curl -I http://192.168.10.10:9090 HTTP/1.1 200 OK Server: nginx/1.19.2 Date: Tue, 01 Sep 2020 09:56:16 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 11 Aug 2020 14:50:35 GMT Connection: keep-alive ETag: "5f32b03b-264" Accept-Ranges: bytes [root@localhost ~]#
hostPort的优缺点与hostNetwork类似,因为它们都是使用了宿主机的网络资源。hostPort相对hostNetwork的一个优点是,hostPort不需要提供宿主机的网络信息,但其性能不如hostNetwork,因为需要经过iptables的转发才能到达Pod。
service NodePort
与hostPort、hostNetwork只是Pod的配置不同,NodePort是一种service,其使用的是宿主机node上的端口号,从集群外以 任意node的ip + nodePort 来访问Pod的服务。
NodePort 在 kubenretes 里是一个广泛应用的服务暴露方式。Kubernetes中的service默认情况下都是使用的ClusterIP这种类型,这样的service会产生一个ClusterIP,这个IP只能在集群内部访问,要想让外部能够直接访问service,需要将service type修改为 nodePort。
apiVersion: v1 kind: Pod metadata: name: nginx labels: name: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 --- kind: Service apiVersion: v1 metadata: name: nginx spec: type: NodePort ports: - name: nginx port: 80 nodePort: 30000 selector: name: nginx
svc 配置中的nodePort,即为访问服务时,宿主机的端口号。可以在配置文件中指定(当然不能与其他nodePort类型的svc冲突),也可以不配置,由k8s来分配。
创建上述Pod和service后,如下,查看pod和svc的相关信息,我们可以通过宿主机的ip地址+noePort来访问pod的服务
[root@localhost ~]# kubectl get pods -o wide nginx NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE nginx 1/1 Running 0 5m47s 172.17.0.2 minikube <none> [root@localhost ~]# [root@localhost ~]# kubectl get svc -o wide nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR nginx NodePort 10.96.116.150 <none> 80:30000/TCP 5m58s name=nginx [root@localhost ~]# [root@localhost ~]# kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME minikube Ready master 11d v1.12.1 192.168.10.10 <none> CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://17.12.1-ce [root@localhost ~]# [root@localhost ~]# curl -I http://192.168.10.10:30000 HTTP/1.1 200 OK Server: nginx/1.19.2 Date: Tue, 01 Sep 2020 10:14:12 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 11 Aug 2020 14:50:35 GMT Connection: keep-alive ETag: "5f32b03b-264" Accept-Ranges: bytes [root@localhost ~]#
集群外就可以使用kubernetes任意一个节点的IP加上30000端口访问该服务了。kube-proxy会自动将流量以round-robin的方式转发给该service的每一个pod。
这种服务暴露方式,无法让你指定自己想要的应用常用端口,不过可以在集群上再部署一个反向代理作为流量入口
service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制,对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。但是,单独用service暴露服务的方式,在实际生产环境中不太合适:
ClusterIP的方式只能在集群内部访问。
NodePort方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理是灾难。
LoadBalance方式受限于云平台,且通常在云平台部署ELB还需要额外的费用。
————————————————
LoadBalancer、Ingress可以实现pod的外网访问,后续在做整理...
参考文档:https://ieevee.com/tech/2020/01/06/access-pods.html