您的位置:首页 > 文旅 > 旅游 > 谷歌优化培训_中移电子商务有限公司_搜索引擎谷歌入口_sem网络推广公司

谷歌优化培训_中移电子商务有限公司_搜索引擎谷歌入口_sem网络推广公司

2024/12/23 10:15:28 来源:https://blog.csdn.net/u013522701/article/details/142649339  浏览:    关键词:谷歌优化培训_中移电子商务有限公司_搜索引擎谷歌入口_sem网络推广公司
谷歌优化培训_中移电子商务有限公司_搜索引擎谷歌入口_sem网络推广公司

【Kubernetes知识点】 解读 Service 和 EndpointSlice 之间的关系

目录

  • 1 概念
    • 1.1 Service的概念
    • 1.2 Endpoint 的概念
    • 1.3 EndpointSlice 的引入
      • 1.3.1 EndpointSlice支持的地址
      • 1.3.2 EndpointSlice的状态
      • 1.3.3 EndpointSlice的拓扑信息
    • 1.4 Service 、Endpoint和 EndpointSlice 的关系
    • 1.5 Endpoint 和 EndpointSlice 的对比
    • 1.6 无选择器 Service 的场景
    • 1.7 自定义EndpointSlice 要求
  • 2 实验设计:验证Service 和 EndpointSlice关联
    • 2.1 创建测试应用:
    • 2.2 观察Service和EndpointSlice
    • 2.3 模拟 Pod 变化: 扩容和缩容Pod
    • 2.4 无选择器 Service 实验:
  • 3 结论
  • 4 参考文献

❤️ 摘要:在 Kubernetes 中,Service 和 EndpointSlice 是实现负载均衡和服务发现的重要组件。 EndpointSlice让Service更好地处理大量后端,并允许集群有效地更新其健康后端列表。本文将深入探讨它们之间的关系,并设计实验来验证这一关系。


💯 本文关联好文:

  • 《一文读懂Service以及实践攻略》

1 概念

1.1 Service的概念

❔说明:想深入了解Service,请提前看前文《一文读懂Service以及实践攻略》

Kubernetes 中的 Service 是一种网络抽象层,旨在为一组 Pod 提供稳定的访问入口。通过 Service,用户可以不必关心 Pod 的变化,而是通过统一的 IP 地址和端口来访问这些 Pod。

1.2 Endpoint 的概念

Endpoints 是 Kubernetes 中用于跟踪服务网络端点的原始 API。每个 Service 都有一个对应的 Endpoints 对象,存储该服务的所有网络端点。然而,随着 Kubernetes 集群和服务的扩展,原有的 Endpoints API 逐渐暴露出其局限性,特别是在处理大量网络端点的时候。

Kubernetes 限制单个 Endpoints 对象中可以容纳的端点数量。当服务有超过 1000 个支持端点时,Kubernetes 会截断 Endpoints 对象中的数据, 并在 Endpoints 上设置注释: endpoints.kubernetes.io/over-capacity: truncated

1.3 EndpointSlice 的引入

❔ 说明: Kubernetes v1.21之后, EndpointSlice特性是stable

为了更有效地管理服务的端点,Kubernetes 引入了 EndpointSlice。与传统的 Endpoints 资源相比,EndpointSlice 提供了更好的扩展性,尤其是在处理大规模集群时。它将多个端点组织成切片,减少 API 调用次数,提高效率。

如果某个服务的端点数量达到阈值,那么 Kubernetes 将添加另一个空的 EndpointSlice 并在其中存储新的端点信息。默认情况下,一旦现有 EndpointSlice 全部包含至少 100 个端点,Kubernetes 就会创建一个新的 EndpointSlice。

1.3.1 EndpointSlice支持的地址

EndpointSlices 支持三种地址类型,设置addressType字段:

  • IPv4
  • IPv6
  • FQDN (Fully Qualified Domain Name)

❔ 说明: 每个 EndpointSlice 对象代表一个特定的IP地址类型。如果您有一项可通过 IPv4 和 IPv6 使用的服务,则至少有两个 EndpointSlice 对象。

1.3.2 EndpointSlice的状态

EndpointSlice API有三个状态条件, 说明以下:

条件说明
ready正在运行的Pod将Ready 条件设置为 True 时,同时将 EndpointSlice 条件也设置为 true。
servingserving 条件几乎与 ready 条件相同。不同之处在于,如果用户在 pod 终止时关心 pod是否还运行,则应检查 serving 条件。
TerminatingTerminating 是指示端点是否正在终止的条件。对于 Pod,这是设置了删除时间戳的任何 Pod。

1.3.3 EndpointSlice的拓扑信息

EndpointSlice 中的每个端点都可以包含相关的拓扑信息。拓扑信息包括端点的位置以及对应的Node和Zone的信息。字段说明以下:

  • nodeName - 此端点所在节点的名称。
  • zone - 此端点所在的区域。

1.4 Service 、Endpoint和 EndpointSlice 的关系

打个比喻:在一个大型活动中,K8s中的Service作为活动入口的前台人员,他为所有来宾提供入口进入指示。每个来宾Endpoint在活动中有自己的身份标识,比如知道他们的座位号。

现在这个活动区,划分了多个小区域,EndpointSlice就像是一个拿着分区名单的组长,名单记录了一组来宾的身份信息和他们的座位分布。通过EndpointSlice,你可以更高效地管理和查找来宾的位置信息,尤其是在活动人数众多时。这种分片的方式让协调工作变得更加灵活和高效。

Kubernetes中,Service与EndpointSlice实现以下机制:

  1. 选择器机制:Service 使用标签选择器来确定哪些 Pod 作为其后端。EndpointSlice 则维护与这些 Pod 相关联的网络端点信息。
  2. 动态更新:当 Pod 的状态变化时,Service 控制器会自动更新 EndpointSlice,确保服务始终指向活跃的 Pod。
  3. 负载均衡:EndpointSlice 的分组机制使得负载均衡变得更加高效,能够快速响应 Pod 的变化。

1.5 Endpoint 和 EndpointSlice 的对比

作为新的替代方案,EndpointSlice与Endpoint有以下不同点:

资源对象EndpointsEndpointSlice
数据结构所有网络端点信息存储在一个单一的 Endpoints 对象中。随着后端 Pod 数量的增加,这些对象可能会变得非常庞大。将网络端点组织为多个切片,使得每个切片只包含一部分端点信息,从而减小单个对象的大小。
性能在更新过程中,Endpoints 的每次变更都会引发大量的流量,这在高频更新的场景下尤其明显。EndpointSlices 的设计使得添加或删除单个 Pod 只需触发相同数量的更新,但更新消息的大小要小得多,从而降低了 CPU 使用率和网络流量。
新特性支持N/AEndpointSlices 支持新的网络功能,如双栈网络和拓扑感知路由,使得 Kubernetes 在网络管理上更加灵活和高效。

1.6 无选择器 Service 的场景

在某些情况下,用户可能希望定义一个没有选择器的 Service。这种情况通常用于以下场景:

  • 外部数据库:在生产环境中使用外部数据库集群,而在测试环境中使用内部数据库。
  • 跨命名空间或集群访问:需要将 Service 指向不同命名空间或其他集群中的 Service。
  • 迁移工作负载:在评估迁移至 Kubernetes 的过程中,可能只在 Kubernetes 中运行部分后端。

在这些场景中,可以定义一个不带选择器的 Service。由于没有选择器,Kubernetes 不会自动创建对应的 EndpointSlice(和旧版的 Endpoints)对象。用户可以手动添加 EndpointSlice 对象,将 Service 映射到实际运行的网络地址和端口。

1.7 自定义EndpointSlice 要求

对于用户手动创建的 EndpointSlice,建议选择合适的标签值,例如 endpointslice.kubernetes.io/managed-by。对于直接使用 kubectl 管理 EndpointSlices 的用户,建议使用描述此手动管理的名称,例如 “staff” 或 “cluster-admins”,应避免使用保留值 “controller”,因为它表示由 Kubernetes 自身控制平面管理的 EndpointSlices。

⚠️ 注意: Kubernetes API 服务器不允许代理未映射到 Pods 的端点。由于这一限制,诸如 kubectl port-forward service/<service-name> 的操作在 Service 没有选择器时会失败。

2 实验设计:验证Service 和 EndpointSlice关联

为验证 Service 和 EndpointSlice 之间的关系,我们可以进行以下实验:

2.1 创建测试应用:

沿用《一文读懂Service以及实践攻略》案例,创建一个简单的 Web 应用,定义一个 Deployment 和对应的 Service。

Deployment 示例

apiVersion: apps/v1
kind: Deployment
metadata:
# 定义Deployment的名字name: nginx-deploymentlabels:app: nginx
spec:# 定义副本数replicas: 1# 选择器指定label与pod模板的label匹配selector:matchLabels:app: nginxtemplate:metadata:# 与选择器指定label匹配labels:app: nginxspec:containers:# pod名字,可自定义- name: nginx# 镜像源, 这里设置私有镜像源image: harbor.zx/hcie/nginx:1.26.1# pod暴露端口号ports:- containerPort: 80name: httpprotocol: TCP

Service 示例

---
apiVersion: v1
kind: Service
metadata:name: my-clusterip-service
spec:selector:app: nginxports:- protocol: TCPport: 80targetPort: 80type: ClusterIP

部署Service和Deployment

kubectl apply -f nginx-deployment.yaml
kubectl apply -f clusterip-service.yaml

2.2 观察Service和EndpointSlice

查看service详细信息

kubectl describe svc my-clusterip-service

输出如下:

Name:              my-clusterip-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.245.81.75
IPs:               10.245.81.75
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         172.16.194.102:80
Session Affinity:  None
Events:            <none>

查看endpointslice

kubectl describe endpointslices.discovery.k8s.io my-clusterip-service-xvl7k

输出如下:

Name:         my-clusterip-service-xvl7k
Namespace:    default
Labels:       endpointslice.kubernetes.io/managed-by=endpointslice-controller.k8s.io
# 通过label,自动关联my-clusterip-servicekubernetes.io/service-name=my-clusterip-service
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2024-09-28T09:43:42Z
AddressType:  IPv4
Ports:Name     Port  Protocol----     ----  --------<unset>  80    TCP
# 自动关联Endpoint,对应pod
Endpoints:- Addresses:  172.16.194.102# pod状态是Ready时, EndpointSlice状态自动设置为ReadyConditions:Ready:    trueHostname:   <unset># 关联某个Deployment下podTargetRef:  Pod/nginx-deployment-64db67d8bc-zblx6# 描述pod在当前的节点NodeName:   k8s-worker1# 描述pod在当前的域Zone:       <unset>
Events:         <none>

❔ 说明:

  • 通过创建上述 Deployment 和 Service,Kubernetes 会自动生成 EndpointSlice。

2.3 模拟 Pod 变化: 扩容和缩容Pod

扩容Deployment的副本数到3,观察EndpointSlice的变化:

kubectl scale deployment/nginx-deployment --replicas=3

观察Endpointslice,执行以下命令

kubectl describe endpointslices.discovery.k8s.io my-clusterip-service-xvl7k

输出如下:

erip-service-xvl7k
Name:         my-clusterip-service-xvl7k
Namespace:    default
Labels:       endpointslice.kubernetes.io/managed-by=endpointslice-controller.k8s.iokubernetes.io/service-name=my-clusterip-service
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2024-09-28T09:57:26Z
AddressType:  IPv4
Ports:Name     Port  Protocol----     ----  --------<unset>  80    TCP
# 新增两个Endpoint,并分配到不同的节点
Endpoints:- Addresses:  172.16.194.102Conditions:Ready:    trueHostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-zblx6NodeName:   k8s-worker1Zone:       <unset>- Addresses:  172.16.135.200Conditions:Ready:    trueHostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-qbmvdNodeName:   k8s-master3Zone:       <unset>- Addresses:  172.16.126.43Conditions:Ready:    trueHostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-p7xqjNodeName:   k8s-worker2Zone:       <unset>
Events:         <none>

手动删除一个 Pod,并观察 EndpointSlice 的变化:

kubectl delete pod nginx-deployment-64db67d8bc-zblx6 

观察Endpointslice,执行以下命令

kubectl describe endpointslices.discovery.k8s.io my-clusterip-service-xvl7k

输出如下:

# Endpoint列表会剔除被删除的pod
Endpoints:- Addresses:  172.16.135.200Conditions:Ready:    trueHostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-qbmvdNodeName:   k8s-master3Zone:       <unset>- Addresses:  172.16.126.43Conditions:Ready:    trueHostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-p7xqjNodeName:   k8s-worker2Zone:       <unset>
Events:         <none>
---
Endpoints:- Addresses:  172.16.135.200Conditions:Ready:    trueHostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-qbmvdNodeName:   k8s-master3Zone:       <unset>- Addresses:  172.16.126.43Conditions:Ready:    trueHostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-p7xqjNodeName:   k8s-worker2Zone:       <unset>- Addresses:  172.16.194.101Conditions:Ready:    false                                   -> Ready状态从false转为true Hostname:   <unset>TargetRef:  Pod/nginx-deployment-64db67d8bc-v86vr   -> 添加新的pod NodeName:   k8s-worker1Zone:       <unset>
Events:         <none>

❔步骤说明:

  1. EndpointSlice监听到Pod被删除的事件;
  2. 更新Endpoint列表,剔除被删除的Pod;
  3. EndpointSlice监听到新的Pod被创建;
  4. 更新Endpoint列表,新增新创建的Pod;
  5. 监听Pod的状态,如果Pod状态转为Ready, 则设置Endpoint的状态为Ready。

❔ 总结:

  1. 动态更新:当 Pod 的状态变化时,Service 控制器会自动更新 EndpointSlice,确保服务始终指向活跃的 Pod。
  2. 负载均衡:EndpointSlice 的分组机制使得负载均衡变得更加高效,能够快速响应 Pod 的变化。

2.4 无选择器 Service 实验:

如果是Service需要代理外部的应用,或者应用的部署在Service之后的, 可能会采用无选择器的Service这种方式部署Service资源。

创建一个不带选择器的 Service:

apiVersion: v1
kind: Service
metadata:name: external-service
spec:ports:- port: 8080targetPort: 8080

然后手动创建 EndpointSlice:

apiVersion: discovery.k8s.io/v1
addressType: IPv4
endpoints:
# 外部应用的IP地址- addresses:- 192.168.1.100conditions:ready: true
kind: EndpointSlice
metadata:labels:endpointslice.kubernetes.io/managed-by: endpointslice-controller.k8s.io# 关联没有选择器的servicekubernetes.io/service-name: external-servicename: external-service-endpointsnamespace: default
# 指定映射的端口
ports:
- name: ""port: 8080protocol: TCP

创建service和endpointslice

kubectl apply -f external-service.yaml
kubectl apply -f external-service-endpoints.yaml

观察service状态

[root@k8s-master1 hcie]# kubectl describe svc external-service
Name:              external-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
# 确实没有selector
Selector:          <none>
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.245.23.244
IPs:               10.245.23.244
Port:              <unset>  8080/TCP
TargetPort:        8080/TCP
# 没有Endpoint
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

观察Endpointslice状态

[root@k8s-master1 hcie]# kubectl describe endpointslices.discovery.k8s.io external-service-endpoints
Name:         external-service-endpoints
Namespace:    default
Labels:       endpointslice.kubernetes.io/managed-by=endpointslice-controller.k8s.iokubernetes.io/service-name=external-service
Annotations:  <none>
AddressType:  IPv4
Ports:Name     Port  Protocol----     ----  --------<unset>  8080  TCP
Endpoints:- Addresses:  192.168.1.100Conditions:Ready:   trueHostname:  <unset>NodeName:  <unset>Zone:      <unset>
Events:        <none>

成功创建并关联。

3 结论

通过以上实验,我们可以验证 Service 和 EndpointSlice 之间的密切关系。EndpointSlices 的引入解决了原有 Endpoints 的性能瓶颈,使 Kubernetes 在网络管理上更加高效和灵活。在实验中,验证了Service 通过标签选择器关联 Pod,而 EndpointSlice 则负责维护这些 Pod 的网络信息。无选择器的 Service 也能够与外部后端进行整合,提供更大的灵活性。希望本文可以帮助你更深入了解它们间的关系。

4 参考文献

[1]Kubernetes 官方文档-service

[2]EndpointSlices

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com