云原生系列技术(七):Kubernetes Service详解

通过上一节介绍的《Kubernetes架构及核心组件详解》,我们对Kubernetes的架构以及核心组件有了一定了解。这节给大家详细介绍下Kubernetes中的Service。

Service 介绍

服务概述

通常情况下,我们访问一个应用是通过IP+Port的形式,如果应用跑在Kubernetes的Pod中,就可以通过Pod的IP+Port也可以访问,但是一般情况下Pod的IP是内部的,集群外部无法访问,另外Pod会不断的创建和销毁,Pod的IP就会一直变化,这样就会存在很多麻烦,所以Kubernetes引入Service为我们解决了上述问题,Service是对一组提供相同功能的 Pods 的抽象,并为它们提供一个统一的入口,同时提供服务发现和负载均衡的功能。

服务定义

那么如何使用Service呢,下面通过一段编排代码定义一个服务:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 81
      targetPort: 80

上面的编排创建一个名为nginx的服务,将后端Pod的80端口映射到集群的81端口进行访问,后端的Pod是通过selector(标签选择器) app=MyApp来过滤选择的。

多端口服务

有时候我们的应用会有多个访问端口,比如80为http访问端口,443为https访问端口,我们可以采用如下方式定义服务:

apiVersion: v1
kind: Service
metadata:
  name: nginx2
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
    - name: https
      protocol: TCP
      port: 443
      targetPort: 443

以此类推,如果有更多的端口按照上述格式增加就可以。

服务类型

上面我们定义的服务都没有指定服务的类型,默认为ClusterIP,服务支持指定以下几种类型:

  • ClusterIP:服务只能在集群内部被访问,这是默认的服务类型。

  • NodePort:在ClusterIP的基础上,在集群的每个Node上都暴露一个同样的端口,供集群外部访问。

  • LoadBalancer:服务可以在集群外被访问,且支持负载均衡。

  • ExternalName:可以将服务映射到 externalName 字段指定的DNS域名。例如:

 apiVersion: v1
 kind: Service
 metadata:
   name: my-service
 spec:
   type: ExternalName
   externalName: my.database.example.com

这种类型需要CoreDNS版本在 1.7+ 才支持

Headless服务

有时候,我们不需要对一个服务进行负载均衡,我们希望服务后面的每一个Pod都有一个固定的DNS,比如在搭建Hbase的nameNode和dataNode的时候,他们之间希望以hostname的形式来通信,这时就可以指定Service的spec.clusterIP值为None,这样就定义了一个Headless服务。

Endpoints

Endpoints是Kubernetes集群中的一个资源对象,存储在etcd中,用来记录一个Service对应的所有Pod的访问地址。

当我们创建一个Service后,如果指定了selector,Kubernetes中的Endpoints Controller会自动帮我们创建对应的Endpoints。如果不指定selector,就不会生成Endpoints对象。

Endpoints Controller负责监听Service和对应Pod的变化:

  • 监听到Service被删除,则删除和该Service同名的Endpoints对象.

  • 监听到新的Service被创建,则根据新建Service信息获取相关Pod列表,然后创建对应Endpoints对象.

  • 监听到Service被更新,则根据更新后的Service信息获取相关Pod列表,然后更新对应Endpoints对象.

  • 监听到Pod被更新,则更新对应的Service的Endpoints对象,将Pod IP记录到Endpoints中.

引入外部服务

上面我们提到,如果我们不给Service指定selector,Endpoints Controller就不会生成Endpoints,这种情况一般用于引入外部服务,下面以引入www.supermap.com为例进行说明:

1.使用以下编排创建外部服务supermap

apiVersion: v1
kind: Service
metadata:
  name: supermap
  namespace: default
spec:
  type: ExternalName
  externalName: www.supermap.com

查看创建的服务:
在这里插入图片描述
2.通过curl命令验证服务可访问:
在这里插入图片描述

Endpoints方式

有些时候我们的外部服务是通过IP访问的,没有对应的域名,那么我们可以通过手动创建Endpoints对象的方式来引入外部服务:

1.使用以下编排创建服务

apiVersion: v1
kind: Service
metadata:
  name: supermap-ip
  namespace: default
spec:
  ports:
    - port: 80

2.使用以下编排创建Endpoints

apiVersion: v1
kind: Endpoints
metadata:
  name: supermap-ip
  namespace: default
subsets:
- addresses:
  - ip: 182.92.194.1
  ports:
  - port: 80

3.通过curl命令验证服务可访问:
在这里插入图片描述

Service 服务发现

当Pod要访问集群中的Service时,必须知道Service对应的IP,这种Service IP获取的过程我们称之为服务发现,Kubernetes目前支持两种模式的服务发现机制:

环境变量

当创建一个Pod的时候,kubelet会在该Pod中注入集群内所有Service的相关环境变量。

格式类似:{SVCNAME}_SERVICE_HOST, {SVCNAME}_SERVICE_PORT等。其中{SVCNAME}为服务名大写形式。

需要注意的是,要想一个Pod中注入某个Service的环境变量,则必须Service要先比该Pod创建。另外如果服务过多的情况下,会造成环境变量泛滥,可能会导致容器启动失败(docker启动参数过长)。

比如我当前环境有名为nginx的服务:
在这里插入图片描述
在Pod中看到以下环境变量:
在这里插入图片描述

DNS

通过DNS进行服务发现的方式很简单,就跟我们通过域名访问网站一个道理。我们可以通过cluster add-on的方式轻松的创建KubeDNS/CoreDNS来对集群内的Service进行服务发现,这也是Kubernetes官方强烈推荐的方式。

假如当前环境的default命名空间下有一个名为nginx的服务,其他Pod要访问该nginx可以通过以下形式:ngxin.default(如果同在一个命名空间下可以省略.default,直接通过服务名就可以)。

Service 负载均衡

Kubernetes通过kube-proxy组件来实现服务的负载均衡。具体实现主要有两种模式:

iptables

iptables是一个工具(应用程序),也称为用户空间(user space),通过配置Netfilter规则表来构建Linux内核防火墙。

iptables 相关知识还需大家自己去了解,不是一句话能说清楚的。

使用iptables实现负载均衡的方式是:

  • kube-proxy监听Service和Endpoint对象的变化,为每个Service创建iptables规则。
  • 客户端访问服务的时候就会根据iptables规则进行转发。

如图所示:在这里插入图片描述

IPVS

IPVS(IP虚拟服务器)实现传输层负载均衡,通常称为第4层LAN交换,是Linux内核的一部分。

IPVS在主机上运行,在真实服务器集群前充当负载均衡器。 IPVS可以将对基于TCP和UDP的服务的请求定向到真实服务器,并使真实服务器的服务在单个IP地址上显示为虚拟服务。

使用IPVS实现负载均衡的方式是:

  • kube-proxy监听Service和Endpoint对象的变化,来创建IPVS规则。

  • 客户端访问服务的时候就会根据IPVS规则进行转发。

如图所示:

在这里插入图片描述

两种实现模式的区别

IPVS模式在Kubernetes v1.8中引入,并在v1.9中进入了beta。 iptables模式在v1.1中添加,并成为自v1.2以来的默认操作模式。 IPVS和iptables都基于netfilter。 IPVS模式和iptables模式之间的差异如下:

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

总结

本文介绍了Kubernetes Service的概念、服务发现和负载均衡功能,帮助大家对Service有更深入一层的理解。篇幅有限,文中一些知识点还需要大家自行补充,比如iptables和IPVS。下节给大家分享《Kubernetes 工作负载详解》。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值