【k8s系列十二】k8s 之 Service的类型

svc的类型

  • ClusterIp:默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP
  • NodePort:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 : NodePort 来访问该服务
  • LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到: NodePort
  • ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持

1. ClusterIP

ClusterIP 主要是在集群内部访问使用.

在没有service的时候, 我们有一个nginx做负载均衡, 还有12个应用服务器, 这12个应用服务器是有控制器管理的. 当一个请求请求到nginx的时候, nginx要想正确请求的应用服务器, 就要维护一份应用服务器的ip地址. 在容器时代, 死亡一个pod或者新增一个pod都是常事, 而如果nginx要维护pod的服务列表, 那就要频繁的修改服务列表, 这样很不方便. 因此, 我们引入了service.

从上图中可以看出, service通过标签和pod进行匹配, nginx请求的时候, 不用直接去请求pod, 而是请求service, service在去请求pod. 这样就算pod增加了或者减少了, 通过标签都会自动匹配. 而我们需要给service一个固定的ip, 这个固定的ip就是ClusterIP方式了.

这就是ClusterIP的作用了, 在集群内部, 给集群一个负载均衡的方案

那有些服务是内部的, 有些服务是外部的, 如果是内部的就可以基于ClusterIP的方式, 如果是外部的就要基于第二种方式了.

2.NodePort

有些服务是要提供给集群外部去访问的, 这种情况就要用NodePort了.

上面的模式是nginx去请求tomcat, 那谁请求nginx呢? 肯定是外部服务或者浏览器请求nginx, 这个时候就是外部请求集群了, 使用clusterIP方式不行了, 要使用NodePort的方式.

如上图所示,当外部服务, 或者外部用户,或者其他网络需要访问集群的时候,应该怎么办呢?总不能让人家ssh登录到集群内部访问吧. 这时候可以使用nodePort类型的svc。nginx是集群内部的pod, 我们在集群中创建一个svc, 类型是nodePort类型, svc同样会通过标签匹配到pod. 这个svc会绑定到当前的物理网卡, 比如ENS 33 的网卡, 他会把当前物理网卡的地址以及端口映射称成自己的调度器地址, 或者vip地址. 比如 物理网卡上提供了一个端口30009, 为什么要30009呢?因为要大于30000以上. 那么,这时只要客户端访问30009端口, 就可以基于svc-nginx调度器负载到nginx, nginx接收到请求以后, 在反向代理到svc-tomcat调度器, svc-tomcat再将请求分配给tomcat-pod

所以, 如果是集群内部组件相互访问, 我们通过clusterIP将其关联起来. 如果是集群外部想访问集群内部, 我们就通过nodePort将端口暴露出去.

但这样是不是就可以了呢? 显然不是, 让用户访问30009端口, 这基本不可能, 用户请求的一般都是80端口或者334端口. 那怎么办呢? 有路由器啊, 我们可以吧路由器的dail net 端口映射到30009端口. 还有一种方案, 负载均衡, 我们来看看负载均衡的方案.

假设现在集群中有两个节点node1和node2, deployment控制器在两个节点上创建了8个tomcat, 然后创建了一个svc, 专门用来管理tomcat. 在node1节点上有一个nginx的pod, 为了能够和外部进行通讯, 我们还创建了一个nodePort类型的svc, 重点来了, 当我们创建了这个svc以后, 它会绑定到物理机的网卡上, 他不仅是绑定到node1物理机的网卡, 同时他还会绑定到node2物理机的网卡.物理网卡的地址以及端口映射成自己的调度器地址. 比如我们还是创建了30009端口, 不仅在node1节点上会映射一个30009端口, 而且在node2节点上也会映射一个30009端口. 当外部访问node1的30009端口是, 可以反向代理到node1节点的svc-nginx调度器, 进而负载到nginx. 当外部访问node2的30009端口时, 一样可以反向代理到node1节点的svc-nginx调度器. 进而负载到nginx上.

在外面还有负载均衡slb, 这是一个高可用的slb, 有多台. 然后将slb的80端口或者443端口映射到node1或者node2的30009端口, 这样用户在访问80端口或者443端口的时候, 就可以请求到svc-nginx调度器了.

这种情况就完美的解决了80端口和443端口了.

3.loadBalance

可是, 这种方案如果在实体机搭建, 肯定没问题. 但如果在阿里云/百度云/腾讯云上搭建, 那就不行了, 为什么呢? 因为如果你买了一台centos服务器, 想要搭ipvs集群, 他不让你搭.原因是他们把云主机内核的ipvs模块给移除了, 为什么移除了呢?因为耽误他们赚钱. 阿里云/百度云/腾讯云/AWS都有一种服务, 叫LAAS服务, 也就是负载均衡器服务. 他们希望你去购买负载均衡器服务实现负载均衡, 而不是自己买一个非常便宜的云主机,在centos上搭建一个负载均衡.

于是, 我们自己搭建的SLB负载均衡的部分, 就没法实现了, 需要使用云厂商的LAAS服务才行, 如下图深红色模块. LAAS是通过在云供应商购买界面鼠标点击购买创建的, 挺费劲的. 那我们是不是希望, 如果我创建了一个NodePort类型的svc, 那么肯定需要创建负载均衡lvs, 他就自己帮我在nodePord当前的端口通过LAAS暴露出去. 也就是灰色框出的部分,变成自动化的了. 这就是第三类loadBalance. 基于云供应商提供的负载均衡的方式.

这种基于云供应商的模式是单独收费的, 那么他有什么优点呢? 基于云供应商提供的LAAS底层是ipvs或者F5, 所以可以用较低的价格获得更高的扩展性. 但如果用不上f5的话,相对来说价格是比较贵的. 毕竟如果用不到F5, 我卖一台普通的服务器就搞定了. 普通服务器相对应LAAS来说价格是便宜很多的.

第三种使用常用

  • 公有云环境, 私有云是不可以的, 纯物理环境也不行.

4. ExternalName

什么场景会使用 ExternalName 呢? 如上图, 我们来分析一下. 现在集群中有n个节点, 主要有两种类型的pod, 一种是tomcat, 假设有100个tomcat节点, 另一个是mysql, mysql的pod就有1个. 那么web应用想要访问mysql, 会怎么做呢? 在每一个web服务器的配置文件中直接配置mysql所在的ip地址. 假设值192.168.17.11. 现在有100个web服务, 就要配置100次. 我们都知道pod每次创建ip都会变, 如果mysql的pod死了然后重建了, 这时候ip地址就会发生变化, 那么我们就要去挨个修改100个web服务器中的mysql地址, 这要崩溃呀. 于是,就有了第四种svc类型--ExternalName. 将mysql的地址剥离开来, 不要直接写在没有web服务器里面, 怎么做呢?

ExternalName类型的svc会借助一个组件CoreDNS, 这是一个DNS服务器. 既然是DNS服务器就可以实现解析, 或者叫别名. 比如: 我们想要访问www.baidu.com, 通过dns解析的时候会解析baidu.sousuo.com. 把我想解析的域名替换去解析另一个.

在之前, 我们web服务器想访问mysql的时候, 需要把ip地址写到web服务器的配置里面, 现在不需要了. 我们创建一个svc, 类型是ExternalName类型. tomcat只需要将地址解析成svc的访问地址. 这里需要注意的是, ExternalName是没有调度器的, 这是4中类型中最特殊的一种.它的创建不会新建ipvs规则, 只会新建一个dns解析规则. dns怎么解析呢? 假设这个svc的名字叫做tomcatSvc, 我们要想访问外部的mysql, 还需要在svc中配置mysql的地址192.168.17.11, 那么在每一个web服务器配置里只需要写上tomcatSvc.default.svc.clusterlocal就可以访问到mysql了. 解析一下:

  • tomcatSvc是svc的名称
  • default: 是svc所在的名称空间
  • svc: 这是一个固定值
  • clusterLocal: 是我们在初始化集群时指定的域名.

所以, 只要svc的名字不变, 这个调用规则就不会变. 然后CoreDNS服务器会将svc中指定的ip解析到对应的地址上. 假设后面mysql的地址变成192.168.17.15了, 那我们只需要修改svc里面的地址, 改一次就可以了.

将外部的地址抽象成集群内部的域名被访问, 相对固定化. 这就是ExternalName类型的svc

总结

svc有4中方式, 什么时候使用什么方式呢? 看下面的图:

当一个需求来了, 要判断倒是是那种场景

  • 是内部请求还是外部请求? 如果是内部请求, 例如nginx想要请求tomcat, 使用clusterIP
  • 如果是外部请求, 需要判断是谁访问谁? 是我想访问外部的mysql么? 如果是, 我就要考虑是否要相对静态的ip给到内部, 如果需要使用ExternalName
  • 如果是外部请求我, 那么还有区分是公有云还是私有云. 如果是公有云, 比如阿里云/百度云/华为云, 他们都是公有云, 需要使用loadBalance方式
  • 如果是私有云或者物理主机, 使用loadPort方式.
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值