kubernetes之service

service出现的动机

Kubernetes Pods 是有生命周期的。他们可以被创建,而且销毁不会再启动。 如果您使用 Deployment 来运行您的应用程序,则它可以动态创建和销毁 Pod。

每个 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。

这导致了一个问题: 如果一组 Pod(称为“后端”)为群集内的其他 Pod(称为“前端”)提供功能,那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用工作量的后端部分?

进入 _Services_。

定义 Service

一个 Service 在 Kubernetes 中是一个 REST 对象,和 Pod 类似。 像所有的 REST 对象一样, Servic定义可以基于 POST 方式,请求 API server 创建新的实例。

例如,假定有一组 Pod,它们对外暴露了 9376 端口,同时还被打上 app=MyApp 标签。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

上述配置创建一个名称为 “my-service” 的 Service 对象,它会将请求代理到使用 TCP 端口 9376,并且具有标签 "app=MyApp"Pod 上。 Kubernetes 为该服务分配一个 IP 地址(有时称为 “集群IP” ),该 IP 地址由服务代理使用。

没有 selector 的 Service

服务最常见的是抽象化对 Kubernetes Pod 的访问,但是它们也可以抽象化其他种类的后端。 实例:

1.希望在生产环境中使用外部的数据库集群,但测试环境使用自己的数据库。

2.希望服务指向另一个 Namespace 中或其它集群中的服务。

3.您正在将工作负载迁移到 Kubernetes。 在评估该方法时,您仅在 Kubernetes 中运行一部分后端。

在任何这些场景中,都能够定义没有 selector 的 Service。 实例:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 30080
      targetPort: 80

由于此服务没有选择器,因此 不会 自动创建相应的 Endpoint 对象。 您可以通过手动添加 Endpoint 对象,将服务手动映射到运行该服务的网络地址和端口:

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 192.168.100.80
    ports:
      - port: 30080

VIP 和 Service 代理

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

为什么不使用 DNS 轮询?

使用服务代理有以下几个原因:

1.DNS 实现的历史由来已久,它不遵守记录 TTL,并且在名称查找结果到期后对其进行缓存。  

2.有些应用程序仅执行一次 DNS 查找,并无限期地缓存结果。  

3.即使应用和库进行了适当的重新解析,DNS 记录上的 TTL 值低或为零也可能会给 DNS 带来高负载,从而使管理变得困难。

userspace 代理模式

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

最后,它安装 iptables 规则,捕获到达该 ServiceclusterIP(是虚拟 IP)和 Port 的请求,并重定向到代理端口,代理端口再代理请求到 backend Pod

默认情况下,用户空间模式下的kube-proxy通过循环算法选择后端。默认的策略是,通过 round-robin 算法来选择 backend Pod

userspace 代理模式

iptables 代理模式

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

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

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

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

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

iptables 代理模式

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 (smallest number of open connections)
  • dh: destination hashing
  • sh: source hashing
  • sed: shortest expected delay
  • nq: never queue

IPVS 代理模式

注意:

1.要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS Linux 在节点上可用。

2.当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。

发布服务 —— 服务类型

ClusterIP(集群内部通信), NodePort(接入集群外部流量),LoadBalancer(kubernetes部署在云环境上,lbaas负载均衡), ExternalName(集群外部的接入集群内部直接使用)

ClusterIP类型

示例

apiVersion: v1
kind: Service
metadata:
     name: redis
     namespace: default
spec:
     selector:
         app: myweb
         tier: frontend
     clusterIP: 10.98.98.98
     type:
     ports:
     - port: 30080
       targetPort: 80

验证

[root@master kubernetes]# kubectl get service
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)     AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP     5d5h
redis        ClusterIP   10.98.98.98   <none>        30080/TCP   27m

[root@master kubernetes]# kubectl get pod --show-labels
NAME                            READY   STATUS    RESTARTS   AGE   LABELS
deploy-myweb-85996f4d65-dlgjr   1/1     Running   0          27m   app=myweb,pod-template-hash=85996f4d65,tier=frontend
deploy-myweb-85996f4d65-fdjcm   1/1     Running   0          27m   app=myweb,pod-template-hash=85996f4d65,tier=frontend
deploy-myweb-85996f4d65-g9qzg   1/1     Running   0          27m   app=myweb,pod-template-hash=85996f4d65,tier=frontend

[root@master ~]# while true; do curl 10.98.98.98:30080/hostname.html; sleep 1;done
deploy-myweb-85996f4d65-fdjcm
deploy-myweb-85996f4d65-dlgjr
deploy-myweb-85996f4d65-dlgjr
deploy-myweb-85996f4d65-fdjcm
deploy-myweb-85996f4d65-g9qzg
deploy-myweb-85996f4d65-g9qzg
deploy-myweb-85996f4d65-g9qzg
deploy-myweb-85996f4d65-dlgjr

NodePort类型


LoadBalancer 类型

使用支持外部负载均衡器的云提供商的服务,设置 type 的值为 "LoadBalancer",将为 Service 提供负载均衡器。 负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Servicestatus.loadBalancer 字段被发布出去。

实例:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  clusterIP: 10.0.171.239
  loadBalancerIP: 78.11.24.19
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
      - ip: 146.148.47.155

来自外部负载均衡器的流量将直接打到 backend Pod 上,不过实际它们是如何工作的,这要依赖于云提供商。

在这些情况下,将根据用户设置的 loadBalancerIP 来创建负载均衡器。 某些云提供商允许设置 loadBalancerIP。如果没有设置 loadBalancerIP,将会给负载均衡器指派一个临时 IP。 如果设置了 loadBalancerIP,但云提供商并不支持这种特性,那么设置的 loadBalancerIP 值将会被忽略掉。

ExternalName类型

如果外部的 IP 路由到集群中一个或多个 Node 上,Kubernetes Service 会被暴露给这些 externalIPs。 通过外部 IP(作为目的 IP 地址)进入到集群,打到 Service 的端口上的流量,将会被路由到 Service 的 Endpoint 上。 externalIPs 不会被 Kubernetes 管理,它属于集群管理员的职责范畴。

根据 Service 的规定,externalIPs 可以同任意的 ServiceType 来一起指定。 在上面的例子中,my-service 可以在 “80.11.12.10:80”(externalIP:port) 上被客户端访问。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
  externalIPs:
    - 80.11.12.10

猜你喜欢

转载自www.cnblogs.com/mycloudedu/p/12046782.html