五、Service详解

Service存在的意义

如果有好几组pod,前端要怎么正确的找到对应的pod呢?

  防止Pod失联(服务发现)

  定义一组Pod的访问策略(负载均衡)

  通常应用前端都需要访问后端,那么后端同时有好几个Pod IP,前端无法通过某个ip去访问,这个时候就通过LB(负载均衡器)提供一个统一的入口IP,供前端访问,现在Service提供了这个功能

 
理解负载均衡四层和七层区别
  四层就是基于IP+端口的负载均衡;即在OSI第4层(TCP层)工作。此种Load Balance不理解应用协议(如HTTP/FTP/MySQL等等)。例子:LVS,F5。
  七层就是基于URL等应用层信息的负载均衡;OSI的最高层,应用层。此时,该Load Balancer能理解应用协议。例子: haproxy,MySQL Proxy。
  也就是四层通过虚拟IP+端口接收请求,然后再分配到真实的服务器;七层通过虚拟的URL或主机名接收请求,然后再分配到真实的服务器。
 
Pod与Service的关系
  通过label-selector(标签)相关联
    通过Service实现Pod的负载均衡(TCP/UDP 4层)
    查看service与pod的对应关系
比如当前端对应多个后端容器的时候,service提供了统一的IP(通过kubectl get svc查看)供前端访问,然后service找到对应IP(通过kubectl get endpoints查看对应IP)将请求负载均衡到每个后端
 
service转发流程
通过ClusterIP访问
  用户->ClusterIP->iptables/ipvs->pod
通过NodePort访问
  用户->nodeport->iptables/ipvs->pod
 
# api版本
apiVersion: v1
# 访问的资源类型
kind: Service
# 元数据信息
metadata:
  # 一般与delpoyment中的名称一样
  name: java-demo2
spec:
  selector:
    # 标签选择器,与delpoyment中的一致
    project: blog
    app: java-demo
  ports:
  - protocol: TCP
    # 设置Service对集群内部提供服务的端口
    port: 80
    # 指定容器中的端口
    targetPort: 8080
    # 指定集群外部访问的端口
    nodePort:30001
  # NodePort类型 
  type: NodePort

 

 
 
Service三种常用类型
ClusterIP:集群内部使用
  默认类型,分配一个稳定的IP地址(虚拟IP,无法ping通),即VIP,只能在集群内部访问(同Namespace内的Pod)
 
NodePort:对外暴露应用 ,端口范围可以在api-server配置文件中更改
  在每个node上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址
  NodePort存在的问题?
  1、端口需要规划,否则应用之间容器互相占用端口
  2、提供LB对外暴露
  通过LoadBalancer可解决上述问题
 
LoadBalancer:对外暴露应用,适用公有云
  与NodePort类似,在每个节点上启用一个随机端口来 暴露服务。除此之外,Kubernetes会请求底层云平台上的负载均衡 器,将每个Node([NodeIP]:[NodePort])作为后端添加进去
 
service代理模式
service主要通过kube-proxy实现的
用户请求通过k8s中的iptables负载均衡规则转发到具体的pod上
k8s默认使用iptables代理模式
如果是kubeadeam部署的,要改成IPVS,就需要修改kube-proxy,kubectl edit cm kube-proxy -n kube-system,里面有一个mode,将值改成ipvs
如果是二进制部署的,直接修改yaml文件,然后删除pod:kubectl delete pods {kube-proxy名称} -n kube-system,会自动重建,最后可以安装:yum install ipvsadm -y,通过ipvsadm -Ln查看负载均衡规则
Iptables和IPVS对比
  Iptables:
    灵活,功能强大
    规则遍历匹配和更新,呈线性时延 ,pod较多时规则太多,导致性能下降
  IPVS:
    工作在内核态,有更好的性能 ,一般都是用ipvs
    调度算法丰富:rr,wrr,lc,wlc,ip hash
 
service转发原理
第一种:iptebles
当我们创建完一条service的时候,kube-proxy 就可以通过 Service 的 Informer 感知到,从而会在宿主机上创建这样一条 iptables
可以通过iptables-save查询
例如:
会看到这样的一条记录-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3,意思是凡是目的地址是 10.0.1.175、目的端口是 80 的 IP 包,都应该跳转到另外一条名叫 KUBE-SVC-NWV5X2332I4OT4T3 的 iptables 链进行处理。
即将跳转到的 KUBE-SVC-NWV5X2332I4OT4T3 规则是一组随机模式iptables链,而这几条链指向的最终目的地,其实就是这个 Service 代理的 Pod
所以在有大量的pod时候,会就导致大量iptables规则,而且会不断刷新,会大量占用该宿主机的 CPU 资源

第二种:ipvs
当我们创建了前面的 Service 之后,kube-proxy 首先会在宿主机上创建一个虚拟网卡(kube-ipvs0),并为它分配 Service VIP 作为 IP 地址
接下来,kube-proxy 就会通过 Linux 的 IPVS 模块,为这个 IP 地址设置三个 IPVS 虚拟主机,并设置这三个虚拟主机之间使用轮询模式 (rr) 来作为负载均衡策略(可通过ipvsadm -ln查看)
任何发往 service 的请求,就都会
 
如何访问service
以 Service 的 VIP(Virtual IP,即:虚拟 IP)方式,比如:当我访问 10.0.23.1 这个 Service 的 IP 地址时,10.0.23.1 其实就是一个 VIP,它会把请求转发到该 Service 所代理的某一个 Pod 上
以 Service 的 DNS 方式,比如:这时候,只要我访问“my-svc.my-namespace.svc.cluster.local”这条 DNS 记录,就可以访问到名叫 my-svc 的 Service 所代理的某一个 Pod。
以 Service 的 DNS 方式还分为两种:
  第一种,是 Normal Service。这种情况访问“my-svc.my-namespace.svc.cluster.local”解析到的是 my-svc 这个 Service 的 VIP,后面的流程就跟 VIP 方式一致了
  第二种,是 Headless Service。这种情况访问“my-svc.my-namespace.svc.cluster.local”解析到是 my-svc 代理的某一个 Pod 的 IP 地址
 
Service DNS名称
CoreDNS:
是一个DNS服务器,Kubernetes默认采用,以Pod部署在集群中,CoreDNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析
如果解析的是集群外部的DNS,还是会走宿主机的DNS进行解析
提供的功能有: 配置完之后,前端链接后端接口时可以通过名称去链接
CoreDNS YAML文件: https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/dns/coredns
ClusterIP A记录格式:
..svc.cluster.local 示例:my-svc.my-namespace.svc.cluster.local
 
 
 
 

 

posted @ 2020-10-22 21:37  SoleMemory  阅读(391)  评论(0)    收藏  举报