Service

Service 是Kubernetes 的核心资源类型之一,通常看做微服务的一种实现。

  • Service关联的Pod资源的规则要借助与标签选择器
  • 通过规则定义出由多个Pod对象组合而成的逻辑集合,以及访问这组Pod的策略
  • Service 对象创建完成后即可作为服务被各客户端访问,但要真正响应这些请求还是要依赖于各后端的资源对象

场景:由Deployment等控制器管理的Pod对象中断后由新建的资源对象所取代,而扩索容后的应用则会带来Pod对象群体的变动,随之变化的还有Pod的IP地址访问接口等。

工作原理

Endpoint (端点)

Endpoint是Kubernetes集群中的一个资源对象,存储在etcd中,用来记录一个Service对应的所有pod的访问地址。 Service配置selector,endpoint controller才会自动创建对应的endpoint对象;否则,不会生成endpoint对象。

Netfilter

Netfilter是Linux内核中用于管理网络报文的框架,采用模块化设计,具有良好的可扩充性,提供扩展各种网络服务的结构化底层框架,你可以在网络堆栈中的数据包遍历过程中的各个点(Netfilter Hooks)注册回调并对数据包执行各种操作,比如它允许你对数据报进行过滤、地址或端口转换(NAT)、丢弃数据包、日志记录

代理模型

  • userspace 代理模型;Linux 操作系统的用户空间,随机打开一个本地端口(运行用户空间的Kube-proxy进程负责监听),任何到达代理端口的连接都被代理至当前资源后端各Pod对象上。(1.1版本默认)
  • iptables 代理模型;与 “userspace” 代理类似,对于每个Service,他都会创建规则直接捕获达到ClusterIP和Port流量,并将其重定向至当前Service后端。(1.2版本默认)
  • ipvs 代理模型;类似“iptables” 模型,ipvs 构建于Netfilter的钩子函数之上,他使用hash表作为底层数据结构并工作于内核空间,因此具有流量转发速度快、规则同步性能好的特性。(1.9默认)

    流程图

    Service / Ingress - 图1
    • Service对象的IP地址也称为Cluster IP,它位于Kubernetes集群配置指定专用IP地址的范围之内,而且是一种虚拟IP地址,它在Service对象创建后即保持不变,并且能够被同一集群中的Pod资源所访问。
    • Service 资源能够以负载均衡的方式进行流量调度,实现了请求流量的分发机制。
    • Service 资源会通过API Server 持续监视着标签选择器匹配到的后端Pod对象。

会话粘性

Service 能够将来自同一个客户端的请求转发至同一个后端的Pod对象,这意味着它会影响调度算法的流量分发,进而降低负载均衡的效果。因此,当客户端访问Pod中的应用程序时,如果有基于客户端身份保存默写私有信息没并给予这些私有信息追踪用户的活动等一类的需求时,那么才会启用会话粘性

spec.sessionAffinity 定义要使用的粘性会话类型,Node不适用;ClientIp基于客户端IP地址识别客户端身份

服务发现

服务发现就是服务或者应用之间互相定位的过程

创建Service资源对象时,ClusterDNS会为它自动创建资源记录用于名称解析和服务注册,于是,Pod资源可直接使用标准的DNS名称来访问这些Service资源.

  • {SVC_NAME}.{NAMESPACE}.{CLUSTER_DOMAIN}
  • {SVC_NAME}.{NAMESPACE}.svc.{CLUSTER_DOMAIN}

服务暴露

Service 的IIP地址仅在集群内可达,然而总会有写服务需要暴露到外部网络中接受各类客户端的访问,例如分层架构应用中的前端Web应用程序等。 Kubernetes 的Service 共有四种类型:ClusterIP NodePort LoadBalancer ExternalName

  • ClusterIP 通过集群IP地址暴露服务,此地址仅在集群内可访问
  • NodePort 建立在ClusterIP 之上,其在每个节点的IP地址的某静态端口(30000 ~ 32767)暴露服务,因此依然会为Service 分配IP地址,并将此作为NodePort的路由目标;简单说就是NodePort 在工作的集群节点上选择一个端口用于将外部集群的用户请求转发至目标Service的ClusterIP上
  • LoadBalance 建立在NodePort 类型之上,其通过 云服务厂商 提供的负载均衡器将服务暴露到集群外部
  • ExternalName 通过Service 映射至由ExternalName 字段的内容指定的主机名来暴露服务,此主机名需要被DNS服务解析至CNAME类型的记录,此类型非Kubernetes集群提供的服务,而是把集群外部的某服务以DNS CNAME 记录的方式映射到集群内

Service / Ingress - 图2

Headless 类型

Headless Service 对象没有ClusterIP,于是kube-proxy便无须处理此类请求,也就是更没有了负载均衡或代理

  • spec.clusterIP 设置为None即可将定义为Headless 类型

当Service 是 Headless 类型时候,每次接入的Pod资源则是由DNS服务器接受到查询请求以轮训方式返回IP地址

image.png

案例

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: billbear-api-gateway-svc
  5. namespace: base
  6. spec:
  7. # Headless
  8. # clusterIP: None
  9. internalTrafficPolicy: Cluster
  10. ipFamilies:
  11. - IPv4
  12. ipFamilyPolicy: SingleStack
  13. ports:
  14. - name: http
  15. port: 8080
  16. protocol: TCP
  17. targetPort: 8080
  18. selector:
  19. app: billbear-api-gateway
  20. sessionAffinity: None
  21. # ClusterIP NodePort LoadBalancer ExternalName
  22. type: ClusterIP
  23. status:
  24. loadBalancer: {}

Ingress

Ingress 资源,它实现的是 “HTTP(S)” 负载均衡器 Ingress 控制器不直接运行 Kubernetes-controller-manager 的一部分,需要在集群上单独部署Ingress 控制器可以由任何具有反向代理功能的服务程序实现,例如 Nginx、Envoy、HAProxy,Ingress 基于HTTP虚拟主机或URL的转发规则

  • rule 当前Ingress资源的转发规则列表
  • backend 默认的后端用于服务那些没有匹配任何规则的请求
  • tls TLS 配置

案例

  1. apiVersion: networking.k8s.io/v1
  2. # 类型
  3. kind: Ingress
  4. metadata:
  5. name: billbear-app-gateway
  6. namespace: base
  7. spec:
  8. ingressClassName: nginx
  9. # 转发规则
  10. rules:
  11. - host: interests-m-dev.billbear.vip
  12. http:
  13. paths:
  14. - backend:
  15. service:
  16. name: billbear-app-gateway-svc
  17. port:
  18. number: 8080
  19. # 路由转发
  20. path: /api/
  21. pathType: ImplementationSpecific
  22. # 证书配置
  23. tls:
  24. - hosts:
  25. - interests-m-dev.billbear.vip
  26. secretName: interests-m-dev.billbear.vip.ssl