一、service资源及其实现模型

通过规则定义出由多个pod对象组合而成的逻辑集合,以及访问这组pod的策略。service关联pod资源的规则要借助于标签选择器来完成

1、service资源概述

由deploy等控制器管理的pod对象中断后会由新建的资源对象所取代,而扩缩容后的应用则会带来pod对象群体的变动,随之变化的还有pod的IP地址访问接口等。pod规模的扩容又会使得客户端无法有效地使用新增的pod对象,从而影响达成规模扩展的目的。为此,service资源可以解决此类问题。

service资源基于标签选择器将一组pod定义成一个逻辑组合,并通过自己的IP地址和端口调度代理至组内的pod对象之上。service对象的IP地址也称为cluster IP,它位于k8s集群配置指定专用IP地址范围之内,而且是一种虚拟IP地址,它在service对象创建后即保持不变,并且能够被同一集群中的pod资源所访问。service端口用于接收客户端请求并将其转发至其后端的pod中应用的相应端口上,因此,这种代理机制也称为端口代理或四层代理,它工作于TCP/IP协议栈的传输层。

通过其标签选择器匹配到的后端pod资源不止一个时,service资源能够以负载均衡的方式进行流量调度,实现了请求流量的分发机制。service与pod对象之间的关联关系通过标签选择器以松耦合的方式建立,它可以先于pod对象创建而不会发生错误,于是,创建service和pod资源的任务可由不同的用户分别完成。

service资源会通过api server持续监视着标签选择器匹配到的后端pod对象,并实时跟踪各对象的变动。service并不直接链接至pod对象,它们之间还有一个中间层---endpoint资源对象,它是一个由IP地址和端口组成的列表,这些IP地址和端口则来自于由service的标签选择器匹配到的pod资源。

2、虚拟IP和服务代理

一个service对象就是工作节点上的一些iptables或ipvs规则,用于将到达service对象IP地址的流量调度转发至相应的endpoints对象指向的IP地址和端口之上。工作于每个工作节点的kube-proxy组件通过api server持续监控着各service及与其关联的pod对象,并将其创建和更新实时反映至当前节点上相应的iptables或ipvs规则上。

service IP事实上是用于生成iptables或ipvs规则时使用的IP地址,它仅用于实现k8s集群网络的内部通信,并且进能够将规则中定义的转发服务的请求作为目标地址予以响应。kube-proxy将请求代理至相应端点的方式有三种:userspace、iptables和ipvs。

1、userspace代理模型

这种模型中,kube-proxy负责跟踪aip server上service和endpoint对象的变动,并根据此调整service资源的定义,对于每个service对象,它会随机打开一个本地端口,任何到达此端口的连接请求都将被代理至当前service资源后端的各pod对象上。这种代理模型中,请求流量到达内核空间后经由套接字送往用户空间的kube-proxy,而后由它送回内核空间,并调度至后端pod。这种方式中,请求在内核空间和用户空间来回转发必然导致效率低下。

2、iptables代理模型

iptables代理模型中,kube-proxy负责跟踪api server上service和endpoint对象的变动,并据此做出service资源定义的变动。同时,对于每个service,他都会创建iptables规则直接捕获到达cluster IP和pod的流量,并将其重定向至当前service的后端。在创建service资源时,集群中每个节点上的kube-proxy都会收到通知并将其定义为当前节点上的iptables规则,用于转发工作接口接收到的与此service资源的clusterIP和端口的相关流量。客户端发来的请求流量被相关的iptables规则进行调度和目标地址转换后再转发至集群内的pod对象之上。其缺点是iptables代理模型不会在被选中的后端pod资源无响应时自动进行重定向,而userspace可以。

3、ipvs代理模型

此模型中,kube-proxy跟踪apiserver上service和endpoint对象的变动,据此来调用netlink接口创建ipvs规则,并确保与api server中的变动保持同步。类似于iptables模型,ipvs构建于netfilter的钩子函数之上,但它使用hash表作为底层数据结构并工作于内核空间,因此具有流量转发速度快、规则同步性能好的特性。另外,ipvs支持众多调度算法,如rr、lc、dh、sh、sed和nq等。

二、service资源的基础应用

1、创建service资源

创建service资源对象有两种方法:一种是直接使用kubectl expose命令,另一种是使用资源配置文件。定义service对象时,spec的两个较为常用的内嵌字段分别为selector和ports,分别用于定义使用的标签选择器和要暴露的端口。如下:

apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp
ports:
- protocol: TCP
port:
targetPort:

service资源myapp-svc通过标签选择器关联至标签为“app=myapp”的各pod对象,它会自动创建名为pyapp-svc的endpoint资源对象,并自动配置一个clusterIP,暴露的端口由port资源进行指定,后端各pod对象的端口则由targetPort给出,也可以使用同port字段的默认值。

2、service会话粘性

service资源还支持session affinity机制,它能够将来自同一个客户端的请求始终转发至同一个后端pod对象,这意味着它会影响调度算法的流量分发功用,进而降低负载均衡的效果。

session affinity的效果仅会在一定时间期限内生效,默认值为10800s,超出时长后,客户端的再次访问会被调度算法重新调度。另外,session affinity机制仅能基于客户端IP地址识别客户端身份,它会把经由同一个nat服务器进行源地址转换的所有客户端识别为同一个客户端,调度粒度粗糙且效果不佳。

三、服务发现

1、服务发现概述

服务发现就是服务或者应用之间互相定位的过程。服务发现机制的基本实现,一般是先部署好一个网络为止较为稳定的服务注册中心(也称为服务总线),服务提供者向注册中心注册自己的位置信息,并在变动后及时予以更新,相应地,服务消费者则周期性地从注册中心获取服务提供者的最新位置信息从而发现要访问的目标服务资源。复杂的服务发现机制还能够让服务提供者提供其描述信息、状态信息及资源使用信息等,以供消费者实现更为复杂的服务选择逻辑。根据服务发现过程的实现方式,服务发现还可分为两种类型:客户端发现和服务端发现:

客户端发现:由客户端到服务注册中心发现其依赖到的服务的相关信息,因此,它需要内置特定的服务发现程序和发现逻辑

服务端发现:这种方式需要额外用到一个称为中央路由器或服务均衡器的组件;服务消费者将请求发往中央路由器或者负载均衡器,由它们负责查询服务注册中心获取服务提供者的位置信息,并将服务消费者的请求转发给服务提供者。

Netflix的eureka是目前较为流行的服务发现系统之一,它是专门开发用来实现服务发现的系统,以可用性目的为先,可以在多种故障期间保持服务发现和服务注册的功能可用。另一个同级别的实现是consul。

2、服务发现方式:环境变量

创建pod资源时,kubelet会将其所属名称空间内的每个活动的service对象以一系列环境变量的形式注入其中。它支持使用service环境变量以及docker的link兼容的变量

1)k8s service环境变量

k8s为每个service资源生成包括以下形式的环境变量在内的一系列环境变量,在同一名称空间中创建的pod对象都会自动拥有这些变量

2)docker link形式的环境变量

docker使用--link选项实现容器连接时说设置的环境变量形式,在创建pod对象时,k8s也会将与此形式兼容的一系列环境变量注入pod对象中。基于环境变量的服务发现其功能简单、易用,但存在一定局限,例如,仅有那些与创建的pod对象在同一名称空间中且事先存在的service对象的信息才会以环境变量的形式注入,那些处于非同一名称空间,或者是在pod资源创建之后才创建的service对象的相关环境变量则不会被添加。基于dns的发现机制并不存在此类限制。

3、clusterdns和服务发现

k8s系统之上用于名称解析和服务发现的clusterdns是集群的核心组件之一,集群中创建的每个service对象,都会由其自动生成相关的资源记录。默认情况下,集群内各pod资源会自动配置器作为名称解析服务器,并在其dns搜索列表中包含它所属名称空间的域名后缀。

四、服务暴露

service的IP地址仅在集群内可达,然而,总会有些服务需要暴露到外部网络中接受各类客户端的访问,此时,就需要在集群的边缘为其添加一层转发机制,以实现将外部请求流量转入到集群的service资源之上,这种操作也成为发布服务到外部网络中。

1、service类型

service共有四种类型:

ClusterIP:通过集群内部IP地址暴露服务,此地址仅在集群内部可达,而无法被集群外部的客户端访问

NodePort:这种类型建立在ClusterIP之上,其在每个节点的IP地址的某静态端口暴露服务,因此,它依然会为service分配集群IP地址,并将此作为NodePort的路由目标

LoadBalancer:这种类型建构在NodePort之上,其通过cloud provider提供的负载均衡器将服务暴露到集群外部,因此LoadBalancer一样具有NodePort和ClusterIP

ExternalName:其通过将service映射至由externalName字段的内容指定的主机名来暴露服务,此主机名需要被dns服务解析至cname类型的记录。此种类型并非定义由k8s集群提供的服务,而是把集群外部的某服务以dns cname记录的方式映射到集群内,从而让集群内的pod资源能够访问外部的service的一种实现方式。

2、NodePort类型的service资源

NodePort即节点port,通常在安装部署k8s集群系统时会预留一个端口范围用于NodePort,默认为3000-32767之间。定义NodePort类型的service资源时,需要通过此属性明确指定其类型名称。

apiVersion: v1
kind:service
metadata:
name: myapp-svc-nodeport
spec:
type: NodePort
selector:
app: myapp
ports:
- protocol: TCP
port:
targetPort:
nodePort:

一般并不推荐用户自定义使用nodePort,除非事先能够明确知道它不会与某个现存的service资源产生冲突。对于集群外部的客户端来说,它们可经由任何一个节点的节点IP及端口访问NodePort类型的service资源,而对于集群内部的pod客户端来说,依然可通过clusterIP对其进行访问。

3、LoadBalancer类型的service资源

NodePort类型的service资源虽然能够于集群外部访问得到,但外部客户端必须得事先得知NodePort和集群中至少一个节点的IP地址,且选定的节点发生故障时,客户端还得自行选择请求访问其他的节点。另外,集群节点很可能是某IaaS云环境中使用私有IP地址的VM,或者是idc中使用私有地址的物理机,这类地址对互联网客户端不可达,因此,一般还应该在集群之外创建一个具有公网IP地址的负载均衡器,由它接入外部客户端的请求并调度至节点相应的NodePort之上。

4、ExternalName service

ExternalName类型的service资源用于将集群外部的服务发布到集群中以供pod中的应用程序访问,因此,它不需要使用标签选择器关联任何的pod对象,但必须要使用spec.externalName属性定义一个cname记录用于返回外部真正提供服务的主机的别名,而后通过cname记录值获取到相关主机的IP地址。

apiVersion: v1
kind: service
metadata:
name: external-redis-svc
namespace: default
spec:
type: ExternalName
externalName: redis.ilinux.io
ports:
- protocol: TCP
port:
targetPort:
nodePort:
selector: {}

由于ExternalName类型的service资源实现于dns级别,客户端将直接接入外部的服务而完全不需要服务代理,因此,它也无须配置cluster IP,此种类型的服务也称为HeadlessService。

五、Headless类型的service

service对象隐藏了各pod资源,并负责将客户端的请求流量调度至该组pod对象之上。不过,有时候也会存在这样的需求:客户端需要直接访问service资源后端的所有pod资源,这时就应该向客户端暴露每个pod资源的IP地址,而不再是中间层service对象的clusterIP,这种类型的service资源便称为Headless Service。

Headless Service对象没有clusterIP,于是kube-proxy便无须处理此类请求,也就更没有了负载均衡或代理它的需要。在前端应用拥有自有的其他服务发现机制时,Headless service即可省去定义clusterIP的需求。至于如何为此类service资源配置IP地址,取决于它的标签选择器的定义。

具有标签选择器:端点控制器会在api中为其创建endpoint记录,并将clusterdns服务中的A记录直接解析到此service后端的pod对象的IP地址上

没有标签选择器:端点控制器不会在api中为其创建endpoints记录,clusterdns的配置分为两种情形,对externalName类型的服务创建cname记录,对其他三种类型来说,为那些与当前service共享名称的所有endpoints对象创建一条记录。

1、创建Headless Service资源

配置service资源清单时,只需要将clusterIP字段的值设置为None即可,例如:

apiVersion: v1
kind: service
metadata:
name: myapp-headless-svc
spec:
clusterIP: None
selector:
app: myapp
ports:
- port:
targetPort:
name: httpport

2、pod资源发现

记录于clusterdns的A记录的相关解析结果是后端pod资源的IP地址,这就意味着客户端通过此service资源的名称发现的是各pod资源。客户端向此service对象发起的请求将直接接入到pod资源中的应用之上,而不再由service资源进行代理转发,它每次接入的pod资源则由DNS服务器接收到查询请求时以轮询的方式返回的IP地址。

k8sService资源的更多相关文章

  1. [置顶] kubernetes资源类型--ingress

    Ingress在K8S1.1之前还没有. 概念 Ingress是一种HTTP方式的路由转发机制,为K8S服务配置HTTP负载均衡器,通常会将服务暴露给K8S群集外的客户端. Ingress是一个允许入 ...

  2. Fis3的前端工程化之路[三大特性篇之资源定位]

    Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...

  3. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  4. ABP文档 - 嵌入的资源文件

    文档目录 本节内容: 简介 创建嵌入的文件 暴露嵌入的文件 使用嵌入的文件 简介 一个web应用里,客户端包含javascript,css,xml等文件,这此文件被添加到一个web项目后,发布成独立的 ...

  5. 【资源】.Net 入门@提高 - 逆天的高薪之路!

     入门看视频,提高看书籍,飘升做项目.老练研开源,高手读外文,大牛讲低调~    官方学习计划 http://www.cnblogs.com/dunitian/p/5667901.html ----- ...

  6. 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?

    0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...

  7. Xamarin+Prism开发详解二:Xaml文件如何简单绑定Resources资源文件内容

    我们知道在UWP里面有Resources文件xxx.resx,在Android里面有String.Xml文件等.那跨平台如何统一这些类别不一的资源文件以及Xaml设计文件如何绑定这些资源?应用支持多国 ...

  8. 一个表缺失索引发的CPU资源瓶颈案例

    背景 近几日,公司的应用团队反应业务系统突然变慢了,之前是一直比较正常.后与业务部门沟通了解详情,得知最近生意比较好,同时也在做大的促销活动,使得业务数据处理的量出现较大的增长,最终系统在处理时出现瓶 ...

  9. 【NLP】Python NLTK获取文本语料和词汇资源

    Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...

随机推荐

  1. Pytorch1.0深度学习:损失函数、优化器、常见激活函数、批归一化详解

    不用相当的独立功夫,不论在哪个严重的问题上都不能找出真理:谁怕用功夫,谁就无法找到真理. —— 列宁 本文主要介绍损失函数.优化器.反向传播.链式求导法则.激活函数.批归一化. 1 经典损失函数 1. ...

  2. Asp.NetCore应用--部署到 ubuntu 进行托管

    准备过程 netcore linux发布包(本人是通过vs2017发布) ubuntu 16.0.4虚机 进行托管 ubuntu  netcore发布文件路径 服务器设置为将对 http://< ...

  3. mysql——操作数据库

    一.查看数据库 show databases; 二.创建数据库 create database 数据库名; 三.删除数据库 drop database 数据库名; 四.查看数据库存储引擎 show e ...

  4. CF450A 【Jzzhu and Children】

    普通的模拟题这题用一个队列容器来模拟队列元素是pair类型的,first用来存每个小朋友想要的糖数,second用来存小朋友的序号,然后开始模拟,模拟出口是当队列迟到等于1时就输出当前队列里小朋友的序 ...

  5. python线程中的同步问题

    多线程开发可能遇到的问题 假设两个线程t1和t2都要对num=0进行增1运算,t1和t2都各对num修改1000000次,num的最终的结果应该为2000000.但是由于是多线程访问,有可能出现下面情 ...

  6. Python_4day

    函数 函数可以用来定义可重复代码,组织和简化 一般来说一个函数在实际开发中为一个小功能 一个类为一个大功能 同样函数的长度不要超过一屏   Python中的所有函数实际上都是有返回值(return N ...

  7. Vue首页加载过慢 解决方案

    一.什么导致了首页初步加载过慢:app.js文件体积过大 二.解决方法: 1.Vue-router懒加载 vue-router懒加载可以解决首次加载资源过多导致的速度缓慢问题:vue-router支持 ...

  8. Codeforces 1201C. Maximum Median

    传送门 看到中位数考虑先把数排序一下 然后有个显然的贪心,一个数增加后一定不能比下一个数大,不然我们直接增加下一个数显然更优 所以初始时的中位数操作后也是中位数 那么我们只要考虑中间再往后怎么加使得答 ...

  9. Constructing Tests CodeForces - 938C

    大意: 定义m-free矩阵: 所有$m*m$的子矩阵至少有一个$0$的$01$矩阵. 定义一个函数$f(n,m)=n*n$的m-free矩阵最大$1$的个数. 给出$t$个询问, 每个询问给出$x$ ...

  10. java实现spark常用算子之count

    import org.apache.spark.SparkConf;import org.apache.spark.api.java.JavaRDD;import org.apache.spark.a ...