深入掌握Service

深入掌握Service

  • 创建Service
  • Service的负载均衡机制
    • kube-proxy的代理模式
    • 会话保持机制
  • 将外部服务定义为Service
  • 将Service暴露到集群外部
    • NodePort类型
    • LoadBalancer类型
    • ExternalName

Service是Kubernetes实现微服务架构的核心概念,通过创建 Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。

创建Service

一个例子:

apiVersion: v1
kind: Service
metadata:
 name: webapp
spec:
 ports:
 -protocol: TCP
  port:8080		//监听端口
  targetPort: 8080		//转发到pod的端口
 selector:
  app: webapp

创建这个Service后,查看系统为其分配的ClusterIP

kubectl creat -f webapp-service.yaml
kubectl get svc

输出

NAME		TYPE		CLUSTER-IP		  EXTERNAL-IP	PORT(S)
webapp	 ClusterIP  	169.169.140.229				8080/TCP

这个Service会监听访问169.169.140.229:8080端口的请求,然后把这些请求发送到集群中拥有label:app=webapp的pod的8080端口上,这样使用者就可以不管pod由于新建或销毁导致的podip变化,直接访问serviceip就可以访问服务

Service的负载均衡机制

当一个Service对象在Kubernetes集群中被定义出来时,集群内的客户端应用就可以通过服务IP访问到具体的Pod容器提供的服务了。从服务IP到后端Pod的负载均衡机制,则是由每个Node上的kube-proxy负责实现的。

kube-proxy的代理模式

目前kube-proxy提供了以下代理模式(通过启动参数–proxy-mode 设置)。
◎ userspace模式:用户空间模式,由kube-proxy完成代理的实现,效率最低,不再推荐使用。
◎ iptables模式:kube-proxy通过设置Linux Kernel的iptables规则,实现从Service到后端Endpoint列表的负载分发规则,效率很高。但是,如果某个后端Endpoint在转发时不可用,此次客户端请求就会得到失败的响应,相对于userspace模式来说更不可靠。此时应该通过为Pod设置readinessprobe(服务可用性健康检查)来保证只有达到 ready状态的Endpoint才会被设置为Service的后端Endpoint。
◎ ipvs模式:在Kubernetes 1.11版本中达到Stable阶段,kubeproxy通过设置Linux Kernel的netlink接口设置IPVS规则,转发效率和支持的吞吐率都是最高的。ipvs模式要求Linux Kernel启用IPVS模块,如果操作系统未启用IPVS内核模块,kube-proxy则会自动切换至 iptables模式。

会话保持机制

Service支持通过设置sessionAffinity实现基于客户端IP的会话保持机制,即首次将某个客户端来源IP发起的请求转发到后端的某个Pod 上,之后从相同的客户端IP发起的请求都将被转发到相同的后端Pod
通过设置service.spec.sessionAffinity就可以了

*******************
kind: Service
metadata:
 name: webapp
spec:
 sessionAffinity: ClientIP
*******************
*******************

也可以设置会话保持的最长时间
下面的服务将会话保持时间设置为 10800s(3h)

*******************
kind: Service
metadata:
 name: webapp
spec:
 sessionAffinity: ClientIP
 sessionAffinityConfig:
  lcientIP:
   timeoutSeconds: 10800
*******************
*******************

将外部服务定义为Service

普通的Service通过Label Selector对后端Endpoint列表进行了一次抽象,如果后端的Endpoint不是由Pod副本集提供的,则Service还可以抽象定义任意其他服务,将一个Kubernetes集群外部的已知服务定义为 Kubernetes内的一个Service,供集群内的其他应用访问

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

apiVersion: v1
kind: Service
metadata: 
 name: my_service
sepc:
 ports:
 -portocol: TCP
  port: 80
  targetPort: 80
apiVersion: v1
kind: Endpoints
metadata:
 name: my-service
subsets:
-addresses:
 -IP: 1.2.3.4
 ports:
 -port: 80

访问没有标签选择器的Service和带有标签选择器的Service一样,请求将被路由到由用户自定义的后端Endpoint上

将Service暴露到集群外部

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

目前Service的类型如下
◎ ClusterIP:Kubernetes默认会自动设置Service的虚拟IP地址,仅可被集群内部的客户端应用访问。当然,用户也可手工指定一个 ClusterIP地址,不过需要确保该IP在Kubernetes集群设置的ClusterIP地址范围内(通过kube-apiserver服务的启动参数–service-cluster-ip-range 设置),并且没有被其他Service使用。

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

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

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

NodePort类型

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

然后就可以通过任意一个Node的IP地址和NodePort 8081端口号访问服务了

LoadBalancer类型

通常在公有云环境中设置Service的类型为“LoadBalancer”,可以将 Service映射到公有云提供的某个负载均衡器的IP地址上,客户端通过负载均衡器的IP和Service的端口号就可以访问到具体的服务

apiVersion: v1
kind: Service
metadata: 
 name: my-service 
spec:
 type: LoadBalancer
 ports:
 -portocol: TCP
  port: 80
  targetPort: 8080
 selector: 
  app: MyApp

在服务创建成功之后,云服务商会在Service的定义中补充LoadBalancer的IP地址

ExternalName

ExternalName类型的服务用于将集群外的服务定义为Kubernetes的集群的Service,并且通过externalName字段指定外部服务的地址,可以使用域名或IP格式。集群内的客户端应用通过访问这个Service就能访问外部服务了。这种类型的Service没有后端Pod,所以无须设置Label Selector

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

你可能感兴趣的:(k8s学习,kubernetes,java,docker)