kubernetes Service(SVC)

service 概念

​ SVC 通过 Label Selector 标签选择的方式,匹配一组 Pod,对外访问服务。每一个 SVC可以理解成为一个微服务。
在这里插入图片描述

​ service 能够提供负载均衡的能力,但是在使用上有以下限制:

  • 只提供4层负载均衡能力(只有 RR 轮询算法),而没有7层功能,如果需要更多的匹配规则来转发请求,4层上的负载均衡是不支持的。

service 类型

Clusterip:默认类型,自动分配一个仅 Cluster 内部可以访问的 虚拟IP,一般用作集群内部负载均衡。

NodePort(service向外暴露):在ClusterIP 基础上为 Service 在每台机器上绑定一个映射端口,外网客户端可以通过 NodeIP,Nodeport访问。

LoadBalancer(service向外暴露):在 NodePort 基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到 NodeIP 和 NodePort

ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,只有1.7之后版本的 kube-dns支持。


SVC 访问流程组件

在这里插入图片描述

  1. 首先 apiserver 监听 kube-proxy 去进行服务和端口的发现。
  2. 通过kube-proxy监控,kube-proxy监控所有 Pod 节点信息,标签、IP、port 等,并负责把它们写入到 iptables 规则当中。
  3. client 访问 SVC,其实访问的是 iptables规则。再由 iptables 导向后端 Pod 节点。
  4. ipvs,图片上没有,现在的ClusterIP,NodePort 都是采取 ipvs 调度算法对后端 Pod 节点进行调度访问。

VIP 和 Service 代理

​ 在kubernetes集群中,每个 Node 运行一个 Kube-porxy 进程。kube-proxy负责为 service 实现了一种 VIP (虚拟IP) 的形式,而不是 ExternaName 的形式。

  • ​ 1.0版本,代理完全在 userspace

  • ​ 1.1版本,新增 iptables 代理,但并不是默认的运行模式

  • ​ 1.2版本,默认采用 iptables 代理

  • ​ 1.4版本,默认采用 ipvs 代理

service 是 “4层(TCP/UDP over IP)概念”,在1.1版本 新增了 Ingress API(beat 版),用来表示“7层代理”。

代理模式分类

Ⅰ、userspace 代理模式

在这里插入图片描述
client Pod 想要访问 Server Pod

  1. ​ 首先经过 Service IP(iptables),由 iptables
    转发至kube-proxy,kube-proxy根据访问的地址,端口进行转发,需要 kube-proxy 充当代理功能。
  2. ​ 其次 kube-apiserver 也会去监听 kube-proxy,kube-proxy 是否进行所有 Pod 信息的写入。
  3. ​ 导致 kube-proxy 的工作负载量过大,压力过大。


Ⅱ、Iptables 代理模式

在这里插入图片描述
client Pod 访问 Server Pod

​ 所有的请求,代理全部由 iptables 来完成,不再需要 kube-proxy 充当代理角色。

​ 提高了 稳定性和访问效率,压力减少


Ⅲ、ipvs 代理模式

ipvs (IP Virtual Server) 实现了传输层负载均衡,也就是我们常说的4层LAN交换,作为 Linux 内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。ipvs可以将基于TCPUDP的服务请求转发到真实服务器上,并使真实服务器的服务在单个 IP 地址上显示为虚拟服务。

ipvs 对比 iptables

我们知道kube-proxy支持 iptables 和 ipvs 两种模式, 在kubernetes v1.8 中引入了 ipvs 模式,在 v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。iptables 模式在 v1.1 中就添加支持了,从 v1.2 版本开始 iptables 就是 kube-proxy 默认的操作模式,ipvs 和 iptables 都是基于netfilter的,那么 ipvs 模式和 iptables 模式之间有哪些差异呢?

  • ipvs 为大型集群提供了更好的可扩展性和性能
  • ipvs 支持比 iptables 更复杂的复制均衡算法(最小负载、最少连接、加权等等)
  • ipvs 支持服务器健康检查和连接重试等功能

ipvs为负载均衡提供算法:

  • rr:轮询带哦都
  • lc:最小连接数
  • dh:目标地址哈希
  • sh:源地址哈希
  • sed:最短期望延迟
  • nq:不排队调度

注意:ipvs 模式假定在运行 kube-proxy 之前在节点上都已经安装了 IPVS 内核模块。当 kube-proxy 以 ipvs 代理模式启动时,kube-proxy 将验证节点上是否安装了 IPVS 模块,如果未安装,则 kube-proxy 将回退到 iptables 代理模式
在这里插入图片描述

client Pod 访问 Server Pod​

  1. 首先,service IP 的 iptables代理变成了 ipvs 模块,实现负载均衡和流量导向。
  2. ​ client 访问到 IPvs 服务,将流量分发到不同的 Pod 上运行。


Cluster IP( service 的暴露IP,提供内部负载均衡 )

​ clusterIP 主要在每个 node 节点使用 ipvs,将发向 Cluster IP对应端口的数据,转发到 Service-ipvs,ipvs通过调度算法将请求进行负载均衡,发送至后端 Pod节点。

1、先创建 Deployment 控制器 3个Nginx 应用

apiVersion: apps/v1
kind: Deployment			#创建Deployment控制器
metadata: 
 name: myapp-deploy
 namespace: default
spec:
 replicas: 3				#创建三个副本
 selector: 
   matchLabels:
     app: myapp				#副本标签
     release: stabel			#副本标签
 template: 
   metadata:
     labels:
       app: myapp			#副本标签
       release: stabel			#副本标签
       env: test
   spec:
   	containers: 
   	  - name: myapp
   	    image: nginx:1.9.1
   	    imagePullPolicy: IfNotPresent   
        ports: 
         - name: http
           containerPort: 80

kubectl apply -f nginx.yaml --record

kubectl get pod -o wide

在这里插入图片描述

2、为这三个 Nginx 应用创建 Service 暴露IP、Port

apiVersion: v1
kind: Service
metadata:
 name: myapp
 namespace: default
spec:
 type: ClusterIP		#Cluster IP
 selector:				#选择器
  app: myapp            #service匹配标签
  release: stabel       #service匹配标签
  ports:
    - name: http		#匹配Deployment.spec.ports名称
      port: 80          #暴露端口
      targetPort: 80    #后端真是服务器端口

kubectl apply -f myapp-service.yaml

kubectl get svc
在这里插入图片描述

kubectl describe service myapp 查看集群虚拟IP 和 后端 Pod地址

在这里插入图片描述

访问这个 10.98.227.26 Cluster IP地址,轮询调度三个 nginx 副本的页面

在这里插入图片描述


Headless Service(DNS解析)

​ Headless Service 属于 Cluster IP的一种,Pod 通过 service_name 方式直接解析到后端 Pod IP。

​ 有时不需要或者不想要负载均衡的 Service,遇到这种情况,可以通过指定 Cluster IP的值为 None,来创建 Headless Service。这类Service 并不会分配 ClusterIP,kube-proxy 不会处理他们,而且平台也不会为他们进行负载均衡和路由。

apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
  labels: 
  	app: myapp
spec:
  selector:
   app: myapp
  clusterIP: "None"
  ports:
   - protocol: TCP
   	 port: 80
     targetPort: 80

1、查看 headless service详细信息

kubectl describe service myapp-headless

在这里插入图片描述

2、解析 该 headless 域名

nslookup myapp-headless.default.svc.cluster.local 10.244.0.2

10.244.0.2 是集群的DNS解析地址

在这里插入图片描述


NodePort (将内部暴露外部)

​ nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由kube-proxy 进一步给到对应的 Pod。

apiVersion: v1
kind: Service
metadata:
 name: myapp-nodeport
 namespace: default
spec:
 type: NodePort         #NodePort
 selector:              #选择器
  app: myapp            #service匹配标签
  release: stabel       #service匹配标签
 ports:
   - name: http        #匹配Deployment.spec.ports名称
     port: 80          #暴露端口
     targetPort: 80    #后端真是服务器端口

kubectl get svc 查看 NodePort IP地址

在这里插入图片描述

kubectl describe svc myapp-nodeport 查看详细 svc 后端 Pod 节点IP地址
在这里插入图片描述


LoadBalancer(从内部暴露外部)

​ loadBalancer 和 nodePort 其实是同一种方法。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用 cloud provider 去创建 LB 来向节点导流。
在这里插入图片描述

每一个 Node 节点同样会暴露 一个 NodePort,只不过在外网存在一个 LB 供应商的调度层。
客户端访问的是 LB 供应商的 IP & PORT ,由 LB 提供负载均衡。


ExternalName (将外部流量引入集群内部)

对外部服务设定别名,通过别名直接访问

​ 这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如自定义域名:hub.shmguigu.com) 引入外部服务到内部流量。

​ ExternalName service 是 Service 的特例,它没有selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。

Kind: Service
apiVersion: v1
metadata: 
  name: my-service-1
  namespace: default
spec:
  type: ExternalName
  externalName: hub.shmguigu.com

kubectl get svc
my-service-1 ExternalName <none> hub.shmguigu.com <none> 9s

Logo

开源、云原生的融合云平台

更多推荐