入门Kubernetes-Service

一、前言

 前一篇文章通过 Deployment 实现了Pod中服务实现滚动更新/回滚等操作;在真实应用场景中,需要将一组Pod提供给外部访问。而且Pod生命周期是短暂的,在 Pod 的生命周期过程中,比如它创建或销毁, IP 地址都会发生变化。不能使用传统的部署方式使用IP方式访问。

 所以需要将Deployment 创建的Pod组统一提供一个访问入口,需要提供给外部的用户去调用的。此时就需要服务发现。那么在k8s中怎么实现呢?—Service

二、服务-Service

 1、Service 的定义

  Service是 k8s 的核心资源类型之一,Service是将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。

  Service资源基于标签选择器将一组Pod定义成一个逻辑组合,并通过自己的IP地址和端口调度代理请求到组内的Pod对象

  

 2、Service 的工作方式

  在 k8s 集群中,每个 Node 运行一个 kube-proxy 进程。 kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。

  kube-proxy 这个组件始终监视着apiserver中有关service的变动信息,获取任何一个与service资源相关的变动状态,通过watch监视,一旦有service资源相关的变动和创建,kube-proxy都要转换为当前节点上的能够实现资源调度规则(例如:iptables、ipvs)  

  • userspace 代理模式

  kube-proxy 会监视 Kubernetes 控制平面对 Service 对象和 Endpoints 对象的添加和移除操作。 对每个 Service,它会在本地 Node 上打开一个端口(随机选择)。 任何连接到“代理端口”的请求,都会被代理到 Service 的后端 Pods 中的某个上面(如 Endpoints 所报告的一样)。 使用哪个后端 Pod,是 kube-proxy 基于 SessionAffinity 来确定的。

  最后,它配置 iptables 规则,捕获到达该 Service 的 clusterIP(是虚拟 IP) 和 Port 的请求,并重定向到代理端口,代理端口再代理请求到后端Pod。

  默认情况下,用户空间模式下的 kube-proxy 通过轮转算法选择后端。

   

  • iptables 代理模式

  这种模式,kube-proxy 会监视 Kubernetes 控制节点对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会配置 iptables 规则,从而捕获到达该 Service 的 clusterIP 和端口的请求,进而将请求重定向到 Service 的一组后端中的某个 Pod 上面。 对于每个 Endpoints 对象,它也会配置 iptables 规则,这个规则会选择一个后端组合。

  默认的策略是,kube-proxy 在 iptables 模式下随机选择一个后端。

  使用 iptables 处理流量具有较低的系统开销,因为流量由 Linux netfilter 处理, 而无需在用户空间和内核空间之间切换。 这种方法也可能更可靠。

  如果 kube-proxy 在 iptables 模式下运行,并且所选的第一个 Pod 没有响应, 则连接失败。 这与用户空间模式不同:在这种情况下,kube-proxy 将检测到与第一个 Pod 的连接已失败, 并会自动使用其他后端 Pod 重试。

  你可以使用 Pod 就绪探测器 验证后端 Pod 可以正常工作,以便 iptables 模式下的 kube-proxy 仅看到测试正常的后端。 这样做意味着你避免将流量通过 kube-proxy 发送到已知已失败的 Pod。

  

  • ipvs 代理模式

  在 ipvs 模式下,kube-proxy 监视 Kubernetes 服务和端点,调用 netlink 接口相应地创建 IPVS 规则, 并定期将 IPVS 规则与 Kubernetes 服务和端点同步。 该控制循环可确保IPVS 状态与所需状态匹配。访问服务时,IPVS 将流量定向到后端Pod之一。

  IPVS代理模式基于类似于 iptables 模式的 netfilter 挂钩函数, 但是使用哈希表作为基础数据结构,并且在内核空间中工作。 这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。 与其他代理模式相比,IPVS 模    式还支持更高的网络流量吞吐量。

  IPVS 提供了更多选项来平衡后端 Pod 的流量。 这些是:

    • rr:轮替(Round-Robin)
    • lc:最少链接(Least Connection),即打开链接数量最少者优先
    • dh:目标地址哈希(Destination Hashing)
    • sh:源地址哈希(Source Hashing)
    • sed:最短预期延迟(Shortest Expected Delay)
    • nq:从不排队(Never Queue)

   

 3、Service的使用

  a、服务类型:创建Service对象,指定类型为NodePort

apiVersion: v1
kind: Service           # 定义Kubernetes资源的类型为Service
metadata:
  name: k8sdemoweb-service     # 定义资源的名称
spec:
  selector:             # 指定对应的Pod
    app: k8demosweb     # 指定Pod的标签为k8sweb
  ports:
  - protocol: TCP       # 协议类型
    port: 80            # 指定Service访问的端口
    targetPort: 80      # 指定Service转发请求的端口
    nodePort: 31001
  type: NodePort        # 指定Service的类型,在这里使用NodePort来对外访问

  对一些应用的某些部分(如前端),可能希望将其暴露给 Kubernetes 集群外部 的 IP 地址

  Kubernetes ServiceTypes 允许指定你所需要的 Service 类型,默认是 ClusterIP

  Type 的取值以及行为如下:

    • ClusterIP:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是默认的 ServiceType

    • NodePort:通过每个节点上的 IP 和静态端口(NodePort)暴露服务。 NodePort 服务会路由到自动创建的 ClusterIP 服务。 通过请求 <节点 IP>:<节点端口>,你可以从集群的外部访问一个 NodePort 服务。

    • LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。

    • ExternalName:通过返回 CNAME 和对应值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。 无需创建任何类型代理。

   b、Headless Services(无头服务)

   有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。

  • 带选择算符的服务

对定义了选择算符的无头服务,Endpoint 控制器在 API 中创建了 Endpoints 记录, 并且修改 DNS 配置返回 A 记录(IP 地址),通过这个地址直接到达 Service 的后端 Pod 上。

  • 无选择算符的服务 

对没有定义选择算符的无头服务,Endpoint 控制器不会创建 Endpoints 记录。 然而 DNS 系统会查找和配置,无论是:

    • 对于 ExternalName 类型的服务,查找其 CNAME 记录
    • 对所有其他类型的服务,查找与 Service 名称相同的任何 Endpoints 的记录

三、使用Service访问应用:

 访问在前面创建的服务:由于本机IP为:192.168.0.109,直接访问192.168.0.109:31001 时,直接访问失败。安装Service类型的描述,该Service类型为NodePort;应该就可以直接访问成功。

 但由于本机的k8s环境是使用:minikube 运行在Docker环境中。真实的k8s Node不是本机,导致访问失败。

 启动服务访问:

//开启服务访问
PS > minikube service  k8sdemoweb-service
|-----------|--------------------|-------------|---------------------------|
| NAMESPACE |        NAME        | TARGET PORT |            URL            |
|-----------|--------------------|-------------|---------------------------|
| default   | k8sdemoweb-service |          80 | http://192.168.49.2:31001 |
|-----------|--------------------|-------------|---------------------------|
* Starting tunnel for service k8sdemoweb-service.
|-----------|--------------------|-------------|------------------------|
| NAMESPACE |        NAME        | TARGET PORT |          URL           |
|-----------|--------------------|-------------|------------------------|
| default   | k8sdemoweb-service |             | http://127.0.0.1:29752 |
|-----------|--------------------|-------------|------------------------|
* 正通过默认浏览器打开服务 default/k8sdemoweb-service...
! Because you are using a Docker driver on windows, the terminal needs to be open to run it.

 访问地址:http://127.0.0.1:29752

   

  通过上图看到,访问应用通过Service负载到不同的Pod节点上。

   

四、参考 
 https://kubernetes.io/zh/docs/concepts/services-networking/service/ 

原文地址:https://www.cnblogs.com/cwsheng/p/14998504.html