上一篇博客总结的项目怎么部署到k8s上运行,但是运行pod ip是docker网桥的IP地址段进行分配的,通常是一个虚拟的二层网络,外部网络并没有办法访问,并且,pod ip是随时会变的,不是固定的,k8s引入了Service的概念,通过Service管理这些pod,Service创建后的Service IP是固定的。但是Service IP(Cluster IP)是一个虚拟的IP,由Kubernetes管理和分配P地址,外部网络无法访问。k8s有三种方式暴露Service给外部网络访问。
注:为什么Pod的IP会变化?Kubernetes 具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,所以说,这个 Pod 可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着 Pod 的创建和销毁,Pod IP 肯定会动态变化
暴露服务的三种方式
- NodePort
将服务的类型设置成NodePort-每个集群节点都会在节点上打 开 一
个端口, 对于NodePort服务, 每个集群节点在节点本身(因此得名叫
NodePort)上打开一个端口,并将在该端口上接收到的流量重定向到基础服务。
该服务仅在内部集群 IP 和端口上才可访间, 但也可通过所有节点上的专用端
口访问。 - LoadBalane
将服务的类型设置成LoadBalance, NodePort类型的一 种扩展,这使得
服务可以通过一个专用的负载均衡器来访问, 这是由Kubernetes中正在运行
的云基础设施提供的。 负载均衡器将流量重定向到跨所有节点的节点端口。
客户端通过负载均衡器的 IP 连接到服务。 - Ingress
创建一 个Ingress资源, 这是一 个完全不同的机制, 通过一 个IP地址公开多
个服务,就是一个网关入口,和springcloud的网关zuul、gateway类似。后面详细总结这个
一、NodePort
在k8s上可以给Service设置成NodePort类型,这样的话可以让Kubernetes在其所有节点上开放一
个端口给外部访问(所有节点上都使用相同的端口号), 并将传入的连接转发给作为Service服务对象的
pod。这样我们的pod就可以被外部请求访问到
步骤1,创建Service的YAML描述文件
注:
spec.ports.nodePort这个参数是指Node节点对外开放访问的端口号,如果不指定,则Kubernetes会随机选择一个端口号
使用kubectl expose命令创建了 一个service的yaml文件
kubectl expose deployment countgame --port=8082 --target-port=8082 --type=NodePort -o yaml --dry-run > svc.yaml
注:
1.countgame 为指定的service对象名称
2.- -port指定集群内部访问的端口
3.- -target-port指定容器内跑服务的端口
4.- -type=NodePort 指定类型 集群外部访问
5.–dry-run表示测试不在k8s运行(不会具体执行该命令)
6.-o yaml 生成yaml格式
7.最后面的 “> deploy.yaml” 表示将生成yaml内容输出到deploy.yaml文件
yaml的spec.selector是指定标签下的pod被这个创建的Service对象关联,通过spec.selector字段来指定这个Service关联哪些Pod
步骤2,创建Service对象
运行yaml文件
kubectl apply -f svc.yaml
查看service
kubectl get svc
查看service关联的pod
可以看到service名称为countgame的service的对外端口为11413,会把通过这个端口访问的请求转发到service对象关联的pod对象的8082端口上
步骤3,外部请求访问
在浏览器通过Node+端口的来访问我们的这个项目url
可以看到,在我们的master、node01、node02三个服务器的都可以访问,所有节点上都监听同一个端口号,这样就通过NodePort暴露端口给外部访问进来
注:正常这一步在生产环境应该还要防火墙开启这个端口,但是测试环境我们把防火墙关闭了,所以没有这一步
总结
简单,但是服务一旦多起来,NodePort 在每个节点上开启的端口会及其庞大,而且难以维护,所以生产环境不建议这么使用
二、LoadBalane
LoadBalane是上面通过NodePort暴露外部访问的一个优化,增加了一个负载均衡器,上面的NodePort是所有节点都开放一个端口,直接给外部访问,并没有Node节点的负载均衡。LoadBalane则是在上面的基础上增加了一层,只提供一个公网ip给外部访问,外部访问这个ip再负载均衡分发给Node节点的Pod
注:
在云提供商上运行的Kubernetes集群通常支持从云基础架构自动提供负载平衡器。 所有需要做的就是设置服务的类型为Load Badancer而不是NodePort。 负载均衡器拥有自己独一无二的可公开访问的 IP 地址, 并将所有连接重定向到服务。可以通过负载均衡器的 IP 地址访问服务。如果Kubemetes在不支持Load Badancer服务的环境中运行, 则不会调配负载平衡器, 但该服务仍将表现得像 一 个NodePort服 务。 这是因为LoadBadancer服务是NodePo江服务的扩展。
总结
最大缺点是每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址和端口,不能做到一个ip地址就可以访问所有服务。
三、Ingress
采用 NodePort 方式暴露服务面临问题是,服务一旦多起来,NodePort 在每个节点上开启的端口会及其庞大,而且难以维护;如果采用LoadBalane,每个服务都得开放一个公网IP,也会很庞大。这时候Ingress暴露服务就是一种很合适的方案。可以通过一个Ingress暴露多个服务。
如何实现?我们先想想有没有只开放一个IP就能访问所有服务呢?类似于网关的那种?我们可以能否使用一个Nginx直接对内进行转发呢?众所周知的是,Pod与Pod之间是可以互相通信的,而Pod是可以共享宿主机的网络名称空间的,也就是说当在共享网络名称空间时,Pod上所监听的就是Node上的端口。那么这又该如何实现呢?简单的实现就是在每个 Node 上监听 80,然后写好规则,因为 Nginx 外面绑定了宿主机 80 端口(就像 NodePort),本身又在集群内,那么向后直接转发到相应 Service IP 就行了,如下图所示:
即每个Node节点通过NodePort类型的Service绑定80端口,转发请求给我们一个Nginx的Pod,然后在Nginx里面再转发给我们其他的Service的Pod,这样我们就可以只提供一个端口给外部网络,我们的Service都在Nginx里面配置一个转发规则不就可以了吗?
从上面的方法,采用 Nginx-Pod 似乎已经解决了问题,但是其实这里面有一个很大缺陷:当每次有新服务加入又该如何修改 Nginx 配置呢??我们知道使用Nginx可以通过虚拟主机域名进行区分不同的服务,而每个服务通过upstream进行定义不同的负载均衡池,再加上location进行负载均衡的反向代理,在日常使用中只需要修改nginx.conf即可实现,那在K8S中又该如何实现这种方式的调度呢???
此时 Ingress 出现了,如果不算上面的Nginx,Ingress 包含两大组件:Ingress Controller 和 Ingress。
Ingress 简单的理解就是你原来需要改 Nginx 配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改 Nginx 了,直接改 yaml 然后创建/更新就行了;那么问题来了:”Nginx 怎么才能动态处理配置?”
注:Ingress资源时基于HTTP虚拟主机或URL的转发规则,需要强调的是,这是一条转发规则,没有任何功能,创建了Ingress对象,Ingress Controller会去动态感知和更新Ingress对象的转发规则
Ingress Controller 这东西就是解决 “Nginx 怎么才能动态处理配置” 的程序(可以简单理解成Ngixn程序,实际不一定,实现方案有很多种);Ingress Controoler 通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,然后读取他,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下,工作流程如下图:
注:
1.简单的来说,就是每个Node节点通过NodePort类型的Service绑定80端口,转发请求给我们的Ingress-Controller的Pod(类似于Nginx), Ingress-Controller再根据域名规则转发给我们其他的Service的Pod,Ingress-Controller可以动态感知Ingress对象,读取Ingress对象的规则,生成一段Ngixn的转发规则配置
2.Ingress这段是参考网友博客的,感觉描述的很好就搬过来了,下面有原文地址
3.Ingress的使用还有挺多东西,写在了下一篇博客 k8s-(八)通过Ingress-nginx暴露service给外部网络访问
总结:
K8S Ingress = 微服务网关, 本质:七层反向代理,微服务集中出入口;
参考
《Kubernetes in Action中文版》
烟雨浮华的《Kubernetes学习之路(十五)之Ingress和Ingress Controller》