Kubernetes基础(十七)-Endpoint

Kubernetes基础(十七)-EndpointEndpoint 代表了 Service 后端的一组 IP 地址和端口号 用于将流量从 Service 引导到实际运行应用程序的 Pod

大家好,欢迎来到IT知识分享网。

1 概述

在Kubernetes(K8s)中,Endpoint是一个关键的核心对象,它承担着连接Service和后端Pod的重要角色。Endpoint提供了对服务后端的抽象,允许用户在集群中动态地管理服务的网络终端。本文将深入研究K8s中Endpoint的概念、作用以及使用方法,并通过详细的示例来帮助读者更好地理解。

1.1 什么是Kubernetes Endpoint?

Endpoint代表了Service后端的一组IP地址和端口号,用于将流量从Service引导到实际运行应用程序的Pod。每个Service都关联着一个对应的Endpoint,这个Endpoint动态地维护了所有Service所选择的Pod的网络终端信息。

简而言之,Endpoint是Service的一种实现,是Service背后真实运行的Pod的地址和端口的集合。通过Endpoint,K8s可以实现服务的动态发现和负载均衡。

 +----------+ / +----> Pod1 | +--------+ / / +----------+ | Client +-----+------+ Pod2 | +--------+ \ \ +----------+ \ +----> Pod3 | +----------+

1.2 Endpoint的结构

Endpoint主要由以下几个部分组成:

  • IP地址: 指定Pod的IP地址,用于标识网络上的唯一位置。
  • 端口号: 指定Pod中运行应用程序的端口,用于标识应用程序的通信端口。

一个Endpoint可以包含多个IP地址和端口号的组合,这取决于与Service相关联的Pod的数量。Endpoint的结构使得它能够适应不同Service的需求,实现对多个Pod的动态管理。

1.3 Endpoint与Service的关系

在K8s中,每个Service都有一个相应的Endpoint。当Service被创建时,K8s会自动创建对应的Endpoint,并将Service选择的Pod的IP地址和端口号添加到Endpoint中。这种关系保证了Service与Pod之间的正确通信。

在Service和Endpoint之间的关系中,Service充当了一种抽象,为应用程序提供了一个稳定的入口点,而Endpoint则提供了Service后端的真实网络终端。这种分离使得用户能够更加灵活地管理和维护后端Pod的变化,而不需要改变Service的定义。

+----------+ +--------+ | Client +-----> | Service | +----------+ +--------+ | v +-----------+ | Endpoint | +-----------+ 

1.4 Endpoint的使用

为了更好地理解Endpoint的使用,让我们通过一个具体的示例来演示。

假设我们有一个简单的Web应用,由多个前端(frontend)和后端(backend)Pod组成。前端提供Web页面,后端处理业务逻辑。我们已经创建了一个名为web-service的Service,现在让我们看看与之关联的Endpoint。

首先,我们查看web-service的定义:

apiVersion: v1 kind: Service metadata: name: web-service spec: selector: app: frontend ports: - protocol: TCP port: 80 targetPort: 8080 

这个Service选择了标签为app=frontend的所有Pod,并将流量引导到它们的80端口。现在,我们来查看与之关联的Endpoint:

kubectl get endpoints web-service 

上述命令的输出可能如下所示:

NAME ENDPOINTS AGE web-service 192.168.1.2:8080,192.168.1.3:8080,192.168.1.4:8080 1h 

在这个示例中,web-service的Endpoint列举了所有与该Service相关联的Pod的IP地址和端口号。这样,K8s就能够动态地将流量引导到这些具体的Pod,实现负载均衡和服务发现。

1.5 动态管理Endpoint

在K8s中,Endpoint的管理是动态的。当Service的相关Pod发生变化时,Endpoint会相应地更新。例如,当我们扩展了前端Pod的数量时,Endpoint会自动添加新的IP地址和端口号。

让我们通过一个扩展Pod数量的例子来演示:

kubectl scale deployment frontend --replicas=5 

然后,我们再次查看web-service的Endpoint:

shell kubectl get endpoints web-service 

输出如下所示:

NAME ENDPOINTS AGE web-service 192.168.1.2:8080,192.168.1.3:8080,192.168.1.4:8080,192.168.1.5:8080,192.168.1.6:8080 5m 

在这个例子中,我们扩展了前端Pod的数量,Endpoint相应地添加了新的IP地址和端口号,确保了与Service相关联的所有Pod都能够被正确地服务。

2 Endpoint增删改查

2.1 创建Endpoint

apiVersion: v1 kind: Endpoints metadata: name: my-endpoint subsets: - addresses: - ip: 192.168.1.1 - ip: 192.168.1.2 ports: - name: port1 port: 80 protocol: TCP - addresses: - ip: 192.168.1.3 ports: - name: port2 port: 8080 protocol: TCP

在 Kubernetes 中,Endpoint 的定义会随着 Service 的创建自动生成。例如,创建一个 Service,如下所示:

apiVersion: v1 kind: Service metadata: name: backend-service spec: selector: app: my-app ports: - name: http port: 80 targetPort: http 

该 Service 定义了一个名叫 backend-service 的虚拟服务,它包含了一个名叫 http 的端口,映射到后端的 http 服务端口。

Kubernetes 会自动为该 Service 创建一个 Endpoint,并将其关联起来。如果需要手动修改 Endpoint,可以使用以下命令:

kubectl edit endpoints backend-service

2.2 Endpoint 更新 

在 Kubernetes 中,当 Endpoint 中的某些 Pod 不可用时,Kubernetes 会自动地从 Endpoint 中删除这些 Pod,并将 Endpoint 更新为不可用状态。新的 Endpoint 会在缺失 Pod 的同一端口上生成一个新的地址,并将服务转发到可用的 Pod。

为了避免 Endpoint 的数据丢失,Kubernetes 具有自动和手动两种更新 Endpoint 的方式。

2.2.1 自动更新 Endpoint

当 Pod 恢复正常时,Kubernetes 会自动更新 Endpoint 并将该 Pod 重新添加到 Endpoint 中,从而使该 Service 再次可用。这种自动更新是 Kubernetes Endpoint 更改监控机制的一部分。

2.2.2 手动更新 Endpoint。

在某些情况下,特别是在进行操作系统多次启动后,Kubernetes 可能无法监视 Endpoint 中的所有更改。此时,可以手动更新 Endpoint。

我们可以使用以下命令手动更新 Endpoint:

kubectl get endpoints my-endpoint -n my-namespace -o yaml | kubectl apply -f -

在执行上述命令之后,Kubernetes 将自动更新 Endpoint 并重新加载流量。

2.3 Endpoint 的删除

Endpoint 可以通过以下命令进行删除:

kubectl delete endpoints my-endpoint -n my-namespace

执行上述命令后,Endpoint 会被删除,但 Service 仍然存在。如果需要同时删除 Service,请执行以下命令:

kubectl delete service backend-service -n my-namespace

3 Endpoint controlor

endpoint controlor是k8s集群的其中一个组件,主要是维护endpoint,保证endpoint内ip:port 能够提供正常服务,其功能如下:

  • endpoint controller 建立 service 与 pod 的list-watch
  • 轮询service队列,查询属于对应该service的pods
  • 判断pods状态以及port情况,生成endpoint对象
    • 过滤掉状态为not ready 的pods
    • 过滤掉不满足service.spec.targetPort 的pods
    • 获取pods 的ip 以及service.spec.ports ,生成endpoint对象
  • 比较该endpoint对象与当前endpoint ,若当前endpoint不存在,则发送给apiserver创建请求,若与当前endpoint不一致,则发送给apiserver更新请求

4 Endpoint参数解释

apiVersion: v1 kind: Endpoint metadata: # 对象元数据 name: namespace: subsets: # 端点对象的列表 - addresses: # 处于“就绪”状态的端点地址对象列表 - hostname <string> # 端点主机名 ip <string> # 端点的IP地址,必选字段 nodeName <string> # 节点主机名 targetRef: # 提供了该端点的对象引用 apiVersion <string> # 被引用对象所属的API群组及版本 kind <string> # 被引用对象的资源类型,多为Pod name <string> # 对象名称 namespace <string> # 对象所属的名称究竟 fieldPath <string> # 被引用的对象的字段,在未引用整个对象时使用,常用于仅引用 # 指定Pod对象中的单容器,例如spec.containers[1] uid <string> # 对象的标识符; notReadyAddresses: # 处于“未就绪”状态的端点地址对象列表,格式与address相同 ports: # 端口对象列表 - name <string> # 端口名称; port <integer> # 端口号,必选字段; protocol <string> # 协议类型,仅支持UDP、TCP和SCTP,默认为TCP; appProtocol <string> # 应用层协议; 
  • endpoint.metadata.name : 代表着service name
  • endpoint.subsets[].addresses[].ip 代表 状态为ready pod 的ip
  • endpoint.subsets[].targetRef: 代表来自该ip的pod详情
  • endpoint. subsets[].ports[]:  数据来源于service.spec.ports,当pods内的port 并不满足targetPort ,则会在endpoint.subsets[].addresses[]中剔除该pod ip
  • endpoint. subsets[].notReadyAddresses:未就绪pod列表

5 Endpoint实战

5.1 利用readiness测试endpoint

目的:

  • 测试是否创建service就会自动创建endpoint资源
  • 利用readiness(就绪探针)模拟后端pod宕机,查看endpoint资源是否会将宕机的pod下线

5.1.1 编写services-readiness.yaml

apiVersion: apps/v1 kind: Deployment metadata: name: demoapp namespace: dev spec: replicas: 3 selector: matchLabels: app: demoapp-with-readiness template: metadata: creationTimestamp: null labels: app: demoapp-with-readiness spec: containers: - image: ikubernetes/demoapp:v1.0 name: demoapp imagePullPolicy: IfNotPresent readinessProbe: httpGet: path: '/readyz' port: 80 initialDelaySeconds: 15 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: services-readiness-demo namespace: dev spec: selector: app: demoapp-with-readiness ports: - name: http protocol: TCP port: 80 targetPort: 80

5.1.2  查看部署状态

[root@master01 yaml]# kubectl get pod -n dev NAME READY STATUS RESTARTS AGE demoapp-677db795b4-9zf5t 1/1 Running 0 63s demoapp-677db795b4-wdf7g 1/1 Running 0 63s demoapp-677db795b4-wn76j 1/1 Running 0 63s [root@master01 yaml]# kubectl get svc -n dev NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE services-readiness-demo ClusterIP 10.109.208.211 <none> 80/TCP 66s #这里看到确实有一个endpoint的资源而且和svc重名,因为endpoint资源和svc资源就是以名字来进行关联的 [root@master01 yaml]# kubectl get endpoints -n dev NAME ENDPOINTS AGE services-readiness-demo 10.244.1.15:80,10.244.2.23:80,10.244.2.24:80 68s #可以看到以下A [root@master01 yaml]# kubectl describe endpoints services-readiness-demo -n dev Name: services-readiness-demo Namespace: dev Labels: <none> Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2022-06-17T07:02:49Z Subsets: Addresses: 10.244.1.15,10.244.2.23,10.244.2.24 NotReadyAddresses: <none> Ports: Name Port Protocol ---- ---- -------- http 80 TCP Events: <none>

5.1.3 访问测试

正常是可以访问200的,并且现在endpoint资源里后端pod还是三个
[root@master01 yaml]# curl 10.109.208.211:80/readyz
OK 
[root@master01 yaml]# curl -I 10.109.208.211:80/readyz
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 2
Server: Werkzeug/1.0.0 Python/3.8.2
Date: Fri, 17 Jun 2022 07:25:57 GMT

修改某一个pod的readyz参数,就会导致访问出现5xx,之后readiness探针就会检测到pod宕机,endpoint就会下线宕机的pod
curl -X POST -d "readyz=fail" 10.244.2.23/readyz
[root@master01 yaml]# curl 10.244.2.23/readyz
fail
[root@master01 yaml]# curl -I 10.244.2.23/readyz
HTTP/1.0 507 INSUFFICIENT STORAGE
Content-Type: text/html; charset=utf-8
Content-Length: 4
Server: Werkzeug/1.0.0 Python/3.8.2
Date: Fri, 17 Jun 2022 07:32:23 GMT

查看endpoint详细信息,会看到NotReadAddresses字段中已经有刚刚宕机pod了
[root@master01 yaml]# kubectl describe endpoints services-readiness-demo -n dev
Name:         services-readiness-demo
Namespace:    dev
Labels:       <none>
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2022-06-17T07:32:28Z
Subsets:
  Addresses:          10.244.1.15,10.244.2.24
  NotReadyAddresses:  10.244.2.23
  Ports:
    Name  Port  Protocol
    ----  ----  --------
    http  80    TCP

Events:  <none>

可以看到READY字段中有一个pod的状态已经是0了
[root@master01 yaml]# kubectl get pod -n dev -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
demoapp-677db795b4-9zf5t   1/1     Running   0          32m   10.244.2.24   node02   <none>           <none>
demoapp-677db795b4-wdf7g   1/1     Running   0          32m   10.244.1.15   node01   <none>           <none>
demoapp-677db795b4-wn76j   0/1     Running   0          32m   10.244.2.23   node02   <none>           <none>

5.2  利用endpoint代理外部mysql(externalName的示例)

5.2.1 编写mysql-endpoints-demo.yaml

这里Endpoints和Service不需要通过labels来进行关联,只需要通过metadata.name字段关联即可(保持一致)

$ vim mysql-endpoints-demo.yaml apiVersion: v1 kind: Endpoints metadata: name: mysql-external namespace: default subsets: - addresses: - ip: 172.29.9.51 #这里的地址可以是外部mysql的读写分离器的IP这样就能保证数据一致性了 - ip: 172.29.9.52 ports: - name: mysql port: 3306 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: mysql-external namespace: default spec: type: ClusterIP ports: - name: mysql port: 3306 targetPort: 3306 protocol: TCP 

5.2.2 部署验证

部署之后,任何pod都可以通过service来访问数据库了。

  

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/152290.html

(0)
上一篇 2025-03-09 14:05
下一篇 2025-03-09 14:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信