貔貅云原生

貔貅云原生

Service

84
0
0
2023-12-05
Service

Service

Service 资源

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-test-01
spec:
  selector:
    apps: test-nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

这个资源的意思是创建一个 Service,名字为nginx-test-01,通过标签test-nginx选择后端进行负载(标签就是 Pod 的标签),后端的端口是80映射为80

创建这个资源对象:

[root@kube01 svc]# kubectl apply -f service.yaml
service/nginx-test-01 created

访问 Service 就可以直接访问到后端服务,可以通过快捷命令进行测试。

[root@kube01 svc]# kubectl run temp-curl --image=curlimages/curl --restart=OnFailure --rm -it -- curl nginx-test-01.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
pod "temp-curl" deleted

Service 类型

查看一下 Service 的列表

[root@kube01 svc]# kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
nginx-test-01   ClusterIP   10.254.175.241   <none>        80/TCP    18m

Service 列表主要分为6类,分别为:

  • Name: 名称
  • TYPE:分为四类:ClusterIP、NodePort、LoadBalancer、ExternalName
  • CLUSTER-IP:Service 内部 IP
  • EXTERNAL-IP:Service 外部 IP(可以用公有云的 LB 实现)
  • PORT(S):端口映射
  • AGE:存活时间

在 Service 中每个 TYPE 类型做的工作都是不一样的,下面分析一下各种类型:

ClusterIP

ClusterIP 类型的 Service 会分配一个虚拟的 IP 地址,用于代表 Service。这个虚拟 IP 只在集群内部可用,对外不可访问。当其它 Pod 需要访问这个 Service 时,它们可以通过 Service 的名称或 DNS 名称来进行访问,而不需要了解后端实际的 Pod IP 地址。
在创建 Service 资源时默认为 ClusterIP,所以不需要指定 type 类型

NodePort

NodePort 类型的 Service 用于将服务公开到集群外部,并通过每个节点上的特定端口进行访问。这种类型允许外部流量通过节点上的固定端口访问服务,然后 Kubernetes 会将流量路由到匹配的后端 Pod。
NodePort 端口范围(默认:30000-32767),配置 NodePort 后,每个 Node 节点都会启用这个端口,此时通过任意节点都可以访问。

在创建 Service 资源时需要指定 type 类型

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  selector:
    app: my-app  # 根据标签选择要暴露的 Pod
  ports:
    - protocol: TCP
      port: 80     # Service 使用的端口
      targetPort: 8080  # Pod 中实际运行服务的端口
  type: NodePort   # 指定 Service 类型为 NodePort
LoadBalancer

当您创建一个 Service 类型为 LoadBalancer 时,Kubernetes 会与云服务提供商(如 AWS、GCP、Azure 等)交互,以创建一个外部负载均衡器,并分配一个外部 IP 地址,即 EXTERNAL-IP,用于访问您的服务。
此处类型为 LoadBalancer,只有部署在公有云上,Kubernetes 才能后自动跟厂商自动协商获取 LB

在创建 Service 资源时需要指定 type 类型

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  selector:
    app: my-app  # 根据标签选择要暴露的 Pod
  ports:
    - protocol: TCP
      port: 80     # Service 使用的端口
      targetPort: 8080  # Pod 中实际运行服务的端口
  type: LoadBalancer   # 指定 Service 类型为 LoadBalancer
ExternalName

ExternalName 类型的 Service 用于将 Kubernetes 集群内的 Service 映射到集群外部的外部域名。这种类型的 Service 通常用于访问位于集群外部的服务,而不需要进行负载均衡或代理。
当您创建 ExternalName 类型的 Service 后,您的应用程序可以使用 my-external-service 这个虚拟服务名称来访问 external-service.example.com 这个外部域名。这种方式对于需要与外部服务进行交互的场景很有用,例如连接到外部数据库或其他服务。

在创建 Service 资源时需要指定 type 类型

apiVersion: v1
kind: Service
metadata:
  name: my-external-service
spec:
  type: ExternalName   # 指定 Service 类型为 ExternalName
  externalName: external-service.example.com  # 外部域名

Service 关联 EndPoints

通过kubectl 查看 Endpoints

[root@kube01 svc]# kubectl get endpoints
NAME            ENDPOINTS                                                  AGE
kubernetes      192.168.17.42:6443                                         167d
nginx-test      172.30.1.22:80,172.30.1.25:80,172.30.1.26:80 + 3 more...   71d
nginx-test-01   172.30.1.23:80

在 Ednpoints 中Name就是SVC的名称,ENDPOINTS就是SVC对应的后端,Service 的后端数量与 Endpoints 有关,Endpoints 的动态更新与控制器有关,一般需要在 Deployment 中配置健康检测,健康检测存活与失败关系着 Endpoints 的更新。

kube-proxy

Service 与 Endpoints 都是负责完成对资源的编排或者资源的存储,实际上在创建一个 Service 后,通过curl访问,是需要有一个程序专门配置对应的一条条规则的

kube-proxy 是集群中的一个关键组件,负责实现 Service 的网络代理和负载均衡功能。它通过维护一组规则和 IP 表,将流量从 Service 的虚拟 IP 地址路由到相应的后端 Pod。kube-proxy 可以工作在不同的模式下,包括userspace iptablesipvs模式。

kube-proxy 的主要功能包括:

  • Service IP 负载均衡: kube-proxy 在各个节点上配置网络规则,以实现 Service 的虚拟 IP 负载均衡,将流量平衡地分发到后端的 Pod。

  • 服务代理: kube-proxy 为每个 Service 创建了一个代理,该代理可以通过 Service 的虚拟 IP 地址访问后端 Pod。

  • 端点更新: kube-proxy 监听 Kubernetes API 服务器中的 Endpoints 对象的变化,以获取后端 Pod 的 IP 地址和端口信息。当 Endpoints 对象发生变化时,kube-proxy 更新其规则,确保流量被正确地路由到新的后端 Pod。

  • 健康检查: 在某些模式下,kube-proxy 还可以执行后端 Pod 的健康检查,以确保只有可用的 Pod 被选中。

在使用 kube-proxy 中,常用模式有 iptables 与 ipvs

Iptables

在 iptables 模式下,kube-proxy 会通过操作节点上的 iptables 规则来实现 Service 的负载均衡和代理。下面是一些关于 kube-proxy 使用 iptables 模式的重要信息:

  • 工作原理: 在 iptables 模式下,每个节点上的 kube-proxy 会监控 Kubernetes API 服务器中的 Endpoints 对象,以获取 Service 对应的后端 Pod 的 IP 地址和端口信息。然后,kube-proxy 使用 iptables 规则来将流量从 Service 的虚拟 IP 地址转发到后端 Pod 的 IP 地址和端口。

  • 负载均衡: 通过 iptables 规则,kube-proxy 在每个节点上进行负载均衡,将流量分发到多个后端 Pod 上,实现服务的高可用性和负载均衡。

  • 代理: kube-proxy 会为每个 Service 创建一个 iptables 规则,以允许访问该 Service。这样,应用程序可以通过 Service 的虚拟 IP 地址访问后端 Pod。

  • 健康检查: 在 iptables 模式下,kube-proxy 不直接执行健康检查。它通过 iptables 规则将流量路由到后端 Pod,而健康检查的责任通常由上游的 LoadBalancer 或应用程序本身负责。

  • 不适用于大规模负载: 尽管 iptables 模式在很多场景下表现良好,但在大规模负载下可能会产生较多的 iptables 规则,导致性能下降和资源消耗增加。

在 iptables 模式下,kube-proxy 提供了以下简单的负载均衡策略:

  • 轮询(Round Robin): 默认情况下,kube-proxy 在 iptables 模式下使用轮询策略,将流量均匀分配给后端 Pod。

  • 会话保持(Session Affinity): 您可以通过在 Service 上设置 sessionAffinity: ClientIP,以确保同一客户端的请求总是路由到相同的后端 Pod。这可以通过 iptables 规则来实现。

IPVS

在 Kubernetes 中,kube-proxy 可以使用 ipvs 模式来实现 Service 的负载均衡和代理功能,使用 Linux IPVS(IP Virtual Server)技术。ipvs 模式相对于默认的 iptables 模式在性能和可伸缩性方面具有一些优势,特别适用于大规模负载。

以下是关于 kube-proxy 使用 ipvs 模式的一些重要信息:

  • 工作原理: 在 ipvs 模式下,kube-proxy 利用 Linux IPVS 技术来实现负载均衡和代理功能。每个节点上的 kube-proxy 会监控 Kubernetes API 服务器中的 Endpoints 对象,以获取 Service 对应的后端 Pod 的 IP 地址和端口信息。然后,kube-proxy 使用 IPVS 规则将流量从 Service 的虚拟 IP 地址转发到后端 Pod 的 IP 地址和端口。

  • 负载均衡: 使用 IPVS,kube-proxy 在内核空间执行负载均衡,具有更好的性能和可伸缩性,适用于大规模负载和高并发情况。

  • 代理: kube-proxy 为每个 Service 创建一个 IPVS 规则,以允许访问该 Service。这样,应用程序可以通过 Service 的虚拟 IP 地址访问后端 Pod。

  • 健康检查: 在 ipvs 模式下,kube-proxy 不直接执行健康检查。类似于 iptables 模式,健康检查的责任通常由上游的 LoadBalancer 或应用程序本身负责。

在 ipvs 模式下,kube-proxy 支持多种负载均衡算法,这些算法可以通过设置 Service 的 sessionAffinity 字段来选择。以下是 ipvs 模式下支持的负载均衡算法:

  • rr(Round Robin): 轮询算法将每个请求依次分配给后端 Pod,实现基本的轮询负载均衡。

  • lc(Least Connections): 最小连接数算法将请求分配给连接数最少的后端 Pod,以实现负载均衡。

  • dh(Destination Hashing): 目标哈希算法使用客户端 IP 地址和端口计算哈希值,将同一客户端的请求路由到相同的后端 Pod,实现会话保持。

  • sh(Source Hashing): 源哈希算法使用后端 Pod IP 地址和端口计算哈希值,将同一后端 Pod 的流量路由到相同的客户端,实现会话保持。

  • sed(Shortest Expected Delay): 最短期望延迟算法根据后端 Pod 的预期延迟选择将请求路由到最快响应的后端 Pod。

  • nq(Never Queue): 不排队算法将请求直接分配给一个空闲的后端 Pod,不排队等待。

不过现在只能整体修改策略,可以通过 kube-proxy 中配置 –ipvs-scheduler 参数来实现,暂时不支持特定的 Service 进行配置。