Service主要用于提供网络服务,通过Service的定义,能够为客户端应用提供稳定的访问地址(域名或IP地址)和负载均衡功能,以及屏蔽后端Endpoint的变化,是Kubernetes实现微服务的核心资源。

1 Service基础

1.1 从案例认识service

一个提供Web服务的Pod集合,由三个Tomcat容器副本组成,每个容器提供的服务端口号都为8081:

apiVersion: apps/v1
kind: Deployment  
metadata:
  name: webapp
spec:
  selector :
    matchLabels:
      app: webapp
  replicas: 3
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: tomcat
        ports:
        - containerPort: 8081

 kubectl apply -f tomcat.yaml -n [namespace]

客户端应用可以直接通过这些Pod的IP地址和端口号8081访问Web服务。

现在将service加进来,使用如下命令创建service

kubectl expose deployment webapp -n [namespace]

kubectl get service -n [namespace]

查看新创建的Service,可以看到系统为它分配了一个虚拟IP地址(ClusterIP地址),Service的端口号则从Pod中的containerPort复制而来。接下来就可以通过Service的IP地址和Service的端口号访问该Service,访问被自动负载分发到了后端三个Pod之一。

当然也可以使用过yaml文件创建service

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

一个Service对应的“后端”由Pod的IP和容器端口号组成,即一个完整的“IP:Port”访问地址,这在Kubernetes系统中叫作Endpoint。

1.2 负载均衡机制

从服务IP到后端Pod的负载均衡机制,则是由每个Node上的kube-proxy负责实现的。

1)kube-proxy的代理模式:

userspace模式:用户空间模式,由kube-proxy完成代理的实现,效率最低,不再推荐使用。

iptables模式:kube-proxy通过设置Linux Kernel的iptables规则,实现从Service到后端Endpoint列表的负载分发规则,效率很高。但是,如果某个后端Endpoint在转发时不可用,此次客户端请求就会得到失败的响应,相对于userspace模式来说更不可靠。此时应该通过
为Pod设置readinessprobe(服务可用性健康检查)来保证只有达到ready状态的Endpoint才会被设置为Service的后端Endpoint。

ipvs模式:kube-proxy通过设置Linux Kernel的netlink接口设置IPVS规则,转发效率和
支持的吞吐率都是最高的。

详细介绍:

Kubernetes从1.8开始增加了IPVS支持,IPVS相对于iptables来说效率更高,使用ipvs需要在允许proxy节点上安装ipvsadm,ipset工具包加载ipvs内核。并且ipvs可以轻松处理每秒10万次转发请求。

当proxy启动的时候,proxy将验证节点是否安装ipvs模块,如果没有安装将退回iptables模式IPVS模式也是基于Netfilter,支持更复杂的复杂均衡算法(最小复杂、最少连接、加权等),支持Service的健康检查和连接重试功能。

IPVS依赖于iptables,使用iptables进行包过滤,SNAT,masuared。

IPVS将使用ipset来存储需要DROP或MASQUARED的流量源地址和目标地址,这样可以保证iptables规则数量固定,不需要关心集群中有多少Service。

 2)会话保持机制

保证同一个外部IP一直访问同一个后端pod,同时,用户可以设置会话保持的最长时间

apiVersion: v1
kind: Service  
metadata:
  name: webapp
spec:
  sessionAffinity:ClientIP
  sessionAffinityConfig:
    clientIP:
        timeoutSeconds:1000s
  selector:
    app: webapp
  ports:
  - protocol: TCP
    port: 8081
    targetPort: 8081

1.3 多端口服务

Service可以设置多个端口号来分别提供不同的服务:

apiVersion: v1
kind: Service  
metadata:
  name: webapp
spec:
  selector :
    app: webapp
  ports:
   -port: 8081
    targetPort: 8081
    name:web
   -port:8082
    targetPort: 8082
    name:management

或者同一个端口号使用的协议不同,如TCP和UDP,也可以为多个端口号来提供不同的服务

1.4 定义外部服务

普通的Service通过Label Selector对后端Endpoint列表进行了一次抽象,如果后端的Endpoint不是由Pod副本集提供的,则Service还可以抽象定义任意其他服务。

用户在创建Service资源对象时不设置Label Selector(后端Pod也不存在),同时再定义一个与Service关联的Endpoint资源对象,在Endpoint中设置外部服务的IP地址和端口号

 1.5 将service暴露出去

Kubernetes为Service创建的ClusterIP地址是对后端Pod列表的一层抽象,对于集群外部来说并没有意义,但有许多Service是需要对集群外部提供服务的,Kubernetes提供了多种机制将Service暴露出去,供集群外部的客户端访问。可以通过Service资源对象的类型字段“type”进行设置:

ClusterIP:Kubernetes默认会自动设置Service的虚拟IP地址,仅可被集群内部的客户端应用访问。

NodePort:将Service的端口号映射到每个Node的一个端口号上,这样集群中的任意Node都可以作为Service的访问入口地址,即NodeIP:NodePort。

LoadBalancer:将Service映射到一个已存在的负载均衡器的IP地址上,通常在公有云环境中使用。

ExternalName:将Service映射为一个外部域名地址,通过externalName字段进行设置。

apiVersion: v1
kind: Service  
metadata:
  name: webapp
spec:
  tyoe:NodePort
  selector:
    app: webapp
  ports:
   -port: 8081
    targetPort: 8081
    nodePort:8081

2 DNS服务

作为服务发现机制的基本功能,在集群内需要能够通过服务名对服务进行访问,这就需要一个集群范围内的DNS服务来完成从服务名到ClusterIP地址的解析。DNS服务在Kubernetes的发展过程中经历了3个阶段:

 

 

附录:

Service的YAML格式文件定义

各属性的说明如下表:

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐