码迷,mamicode.com
首页 > 其他好文 > 详细

k8s Service详解(概念、原理、流量分析、代码)

时间:2021-05-24 01:03:14      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:ddr   缓存   balance   解析   访问   路由规则   app   不可   href   

1.相关概念解读

1.1 Service

在kubernetes中每个Pod都存在生命周期;当一个Pod出现故障,极有可能被Pod控制器销毁并新建一个同类Pod取代(Pod控制器对Pod进行扩容也会新建Pod)。因此每个新建的Pod的都会重新获取IP,因此可以说通过IP获取Pod的服务是不可靠的。

service是一个有固定域名作为访问入口的服务,接受用户的访问请求,通过算法代理至后端的Pods上。Pods创建和销毁都会及时关联至service上。

 

工作原理简介
各Node节点上的kubelet关注各自节点上的pod,如有变动会及时通知master上的kube-apiserver。
各节点上的kube-proxy又实时监测着kube-apiserver上关于pod的变动,获取变动信息后及时修改本地的iptables(或ipvs),生成新的代理规则。
技术图片

 

 

 

根据创建Service的type类型不同,可分成4种(externalname模式此处不做总结)模式:

 1.ClusterIP: 默认方式。根据是否生成ClusterIP又可分为普通Service和Headless Service两类:
  a.普通Service:通过为Kubernetes的Service分配一个集群内部可访问的固定虚拟IP(Cluster IP),实现集群内的访问。为最常见的方式。
  b.Headless Service:该服务不会分配Cluster IP,也不通过kube-proxy做反向代理和负载均衡。而是通过DNS提供稳定的网络ID来访问,DNS会将headless service的后端直接解析为podIP列表。主要供StatefulSet使用。

 


 2.NodePort:

NodePort服务是外部访问服务的最基本方式,顾名思义,NodePort就是在所有节点或者虚拟机上开放特点的端口,该端口的流量将被转发到对应的服务

我们来分析一下上图要表达的意思,当集群外部的客户想要访问ServiceA时,它可以访问Host1-10.10.1.2的31600端口,也可以访问Host2-10.10.1.3的31600端口。这两个访问地址最终都会连接到ServiceA上,并且集群内部的Pod还是可以通过访问192.168.1.22这个集群地址来访问到ServiceA

可总结如下:
在具有集群内部IP的基础上,在集群的每个节点上的端口(每个节点上的相同端口)上公开服务。用户可以在任何< Node IP >:NodePort地址上访问

NodePort方式的缺点主要有:
1)每个服务占用一个端口
2)可以使用的范围端口为30000~32767
3)如果节点/虚拟机IP地址发生更改,需要进行相关处理

技术图片

 

 

 


 3.LoadBalancer:和nodePort类似,不过除了使用一个Cluster IP和nodePort之外,还会向所使用的公有云申请一个负载均衡器(负载均衡器后端映射到各节点的nodePort),实现从集群外通过LB访问服务。

前3种模式,定义服务的时候通过selector指定服务对应的pods,根据pods的地址创建出endpoints作为服务后端;Endpoints Controller会watch Service以及pod的变化,维护对应的Endpoint信息。kube-proxy根据Service和Endpoint来维护本地的路由规则。当Endpoint发生变化,即Service以及关联的pod发生变化,kube-proxy都会在每个节点上更新iptables,实现一层负载均衡。

1.2 Port

Service中主要涉及三种Port: * `port` 这里的port表示service暴露在clusterIP上的端口,clusterIP:Port 是提供给集群内部访问kubernetes服务的入口。

targetPort

  containerPort,targetPort是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器。

nodePort

  nodeIP:nodePort 是提供给从集群外部访问kubernetes服务的入口。

总的来说,port和nodePort都是service的端口,前者暴露给从集群内访问服务,后者暴露给从集群外访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端具体pod的targetPort,从而进入到pod上的容器内。

1.3 IP

使用Service服务还会涉及到几种IP:

ClusterIP

Pod IP 地址是实际存在于某个网卡(可以是虚拟设备)上的,但clusterIP就不一样了,没有网络设备承载这个地址。它是一个虚拟地址,由kube-proxy使用iptables规则重新定向到其本地端口,再均衡到后端Pod。当kube-proxy发现一个新的service后,它会在本地节点打开一个任意端口,创建相应的iptables规则,重定向服务的clusterIP和port到这个新建的端口,开始接受到达这个服务的连接。

Pod IP

Pod的IP,每个Pod启动时,会自动创建一个镜像为gcr.io/google_containers/pause的容器,Pod内部其他容器的网络模式使用container模式,并指定为pause容器的ID,即:network_mode: "container:pause容器ID",使得Pod内所有容器共享pause容器的网络,与外部的通信经由此容器代理,pause容器的IP也可以称为Pod IP。

节点IP

Node-IP,service对象在Cluster IP range池中分配到的IP只能在内部访问,如果服务作为一个应用程序内部的层次,还是很合适的。如果这个service作为前端服务,准备为集群外的客户提供业务,我们就需要给这个服务提供公共IP了。指定service的spec.type=NodePort,这个类型的service,系统会给它在集群的各个代理节点上分配一个节点级别的端口,能访问到代理节点的客户端都能访问这个端口,从而访问到服务。

第二部分:kube-proxy

kube-proxy是一个简单的网络代理和负载均衡器,它的作用主要是负载Service的实现,实现从Pod到Service,以及从NodePort到Service的访问

一.kube-proxy实现方式

1.usersapce方式:通过kube-proxy实现LB的代理服务,是kube0proxy的最初版本,较为稳定,但是效率不高

2.iptables方式:采用iptables来实现LB,是当前kube-proxy的默认方式

kube-proxy监视Kubernetes主服务器对服务/端点对象的各种增,删,改等操作。对于每个服务,它配置iptables规则,捕获Service的ClusterIP和端口的流量,并将流量重定向到服务的后端之一。对于每个Endpoint对象,它选择后端Pod的iptables规则

默认情况下,后端的选择是随机的。可通过Service.spec.sessionAffinity设置为“ClientIP”来选择基于客户端IP的会话关联

第三部分:DNS服务发现机制

在Kubernetes系统中,当Pod需要访问其他Service时,可以通过两种方式来发现服务,即环境变量和DNS方式。前者有非常大的局限性,所以实际我们一般都选用第二种DNS方式来实现服务的注册和发现

kube-dns用来为Service分配子域名,以便集群中的Pod可通过域名获取Service的访问地址,通常kube-dns会为Service赋予一个名为“service_name.namespace_name.svc.cluster_domain”的记录,用来解析Service的Cluster_IP。Kubernetes v1.4版本之后,其主要由Kubedns,Dnsmasq,Exechealthz三个组件构成

Kubedns通过Kubernetes API监视Service资源变化并更新DNS记录,主要为Dnsmasq提供查询服务,服务端口是10053
Dnsmasq是一款小巧的DNS配置工具,其在kube-dns插件中的作用是:通过kube-dns容器获取DNS规则,在集群中提供DNS查询服务,提供DNS缓存,提高查询性能,降低kube-dns容器的压力
Exechealthz主要提供监控检查功能
技术图片

 

 

 Service应用

 Cluster类型的Service
目前k8s集群中已经有一组Pod

技术图片

 

 新建一个service作为他们的代理(通过label selector)
service的定义清单如下

kind: Service
apiVersion: v1
metadata:
   name: ngx-service
spec:
   selector:
     app: ngx  ##选择label为app:ngx的pod建立代理关系
   ports:
     - protocol: TCP  ##代理的协议,可选TCP或者UDP
       port: 80       ##service对外服务端口
       targetPort: 80  ##Pod上的服务端口

  

依据清单创建service并观察代理情况

[root@k8s-master k8s-yaml]# kubectl apply -f ngx-service.yaml 
service/ngx-service created
[root@k8s-master k8s-yaml]# kubectl get services
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP   7d
ngx-service   ClusterIP   10.105.184.128   <none>        80/TCP    43s
[root@k8s-master k8s-yaml]# curl 10.105.184.128/hostname.html
ngx-deployment-58d847f49c-9tbwh
[root@k8s-master k8s-yaml]# curl 10.105.184.128/hostname.html
ngx-deployment-58d847f49c-vvnrj

  

docker 镜像事先构建好,提供nginx服务并/hostname.html显示docker主机名。

代理多服务的cluster类型
定义清单如下

kind: Service
apiVersion: v1
metadata:
   name: ngx-service
spec:
   selector:
     app: ngx  ##选择label为app:ngx的pod建立代理关系
   ports:
     - name: http
       protocol: TCP  ##代理的协议,可选TCP或者UDP
       port: 80       ##service对外服务端口
       targetPort: 80  ##Pod上的服务端口
     - name: https
       protocol: TCP  ##代理的协议,可选TCP或者UDP
       port: 443       ##service对外服务端口
       targetPort: 443  ##Pod上的服务端口

  

NodePort类型的Service
定义清单如下

kind: Service
apiVersion: v1
metadata:
   name: ngx-sr-nodeport
spec:
   type: NodePort   ##虽然为NodePort但仍会为其分配一个ClusterIP
   selector:
     app: ngx
   ports:
     - protocol: TCP
       port: 80    ##供集群内部使用CluserIP+port访问服务
       targetPort: 80  ##Pod上的服务端口
       nodePort: 30080   ##供集群外部使用node的IP+nodeport访问服务

  

依据清单创建service并观察代理情况

`仍会生成clusterIP,也能提供服务`
[root@k8s-master k8s-yaml]# kubectl get services
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP        7d
ngx-sr-nodeport   NodePort    10.106.74.134   <none>        80:30080/TCP   6s
[root@k8s-master k8s-yaml]# curl 10.106.74.134/hostname.html
ngx-deployment-58d847f49c-9tbwh
[root@k8s-master k8s-yaml]# curl 10.106.74.134/hostname.html
ngx-deployment-58d847f49c-vvnrj

  

`从集群外的主机访问服务`
[root@192-168-80-121 ~]# curl 192.168.80.147:30080/hostname.html
ngx-deployment-58d847f49c-9tbwh
[root@192-168-80-121 ~]# curl 192.168.80.147:30080/hostname.html
ngx-deployment-58d847f49c-vvnrj
[root@192-168-80-121 ~]# curl 192.168.80.147:30080/hostname.html
ngx-deployment-58d847f49c-9tbwh

  

外部Service
实现访问集群外(或另一个k8s集群或同个集群中的另一个namespace)的服务。需要自建service使用Endpoint,service不需要使用spec.selector。为了将Endpoint和service绑定,需要定义Endpoint的name与service相同。

service清单

kind: Service
apiVersion: v1
metadata:
   name: ngx-service
spec:
   ports:
     - protocol: TCP  ##代理的协议,可选TCP或者UDP
       port: 80       ##service对外服务端口
       targetPort: 80  ##Pod上的服务端口

  

自建Endpoint清单

kind: Service
apiVersion: v1
metadata:
   name: ngx-service
subsets:
   - address:
   	 - IP:1.2.3.4
   	 ports:
   	 - port:80 

  

Headless Service
不为Service设置ClusterIP(即clusterIP:none),同个spec.selector将后端的Pod列表直接返回给用户,尤其自行负载调度。

kind: Service
apiVersion: v1
metadata:
   name: ngx-service
spec:
   selector:
     app: ngx  ##选择label为app:ngx的pod建立代理关系
   clusterIP: None
   ports:
     - name: http
       protocol: TCP  ##代理的协议,可选TCP或者UDP
       port: 80       ##service对外服务端口
       targetPort: 80  ##Pod上的服务端口

  

 

 

 

 

 原文:

https://blog.csdn.net/liukuan73/article/details/82585732

https://blog.csdn.net/flat0809/article/details/103275026

 

k8s Service详解(概念、原理、流量分析、代码)

标签:ddr   缓存   balance   解析   访问   路由规则   app   不可   href   

原文地址:https://www.cnblogs.com/sucretan2010/p/14743300.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!