ResourceEventHandler for Service

Selector Cache

endpoint-controller-service-cache.svg
EndpointController 在收到 v1.Service 资源变更时,将服务 Spec 中指定的 Selector 对象,保存在一个 map 中。该 map 的 key 通过 DeletionHandlingMetaNamespaceKeyFunc 方法生成,如下所示:
image.png
使用的 MetaNamespaceKeyFunc 如下所示:
image.png
最后,将生成的 key 放入 EndpointController 的工作队列,待后续处理。附上 Kubernetes 官方的 Service 对象配置示例。

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: my-service
  5. spec:
  6. selector:
  7. app: MyApp
  8. ports:
  9. - protocol: TCP
  10. port: 80
  11. targetPort: 9376

Synchronize Service

endpoint-controller-sync-service.svg
上图为 syncService 完整的流程。第一步,先根据通过 Service 获取的 Key 值,还原 Namespace 与 Name,这两个值是后续向 API Server 查询的核心依据。

  • 服务删除,那么通知 API Server 删除该服务相关的 Endpoint
  • 如果是创建、更新服务
    • 从 API Server 根据 (Namespace, Name) 拉取与现有与 Service.Spec.Selector 相关的 Pod 列表
    • 根据 Pod 列表获取子网地址列表
    • 获取当前与 Service 关联的 Endpoints
    • DeepCopy 返回的 Endpoints 对象,并更新 Copy 的 Endpoints 的子网地址列表
    • 使用新 Endpoints,通知 API Server 创建或更新 Endpoints 资源
    • 创建/更新过程发生错误时,记录事件

Subnets

从 API Server 获取的全部 Pod 都会做如下处理来生成 EndpointAddress,以下两种情况下,Pod 被跳过,继续处理下个 Pod:

  • Pod.PodStatus.IP 长度为 0
  • 没有设置 tolerateUnreadyEndpoints 且 Pod 将被删除


如果设置了 IPv6DualStack,则根据 Service.Spec.ClusterIP 的类型(IPv4 或 IPv6),从 Pod.PodStatus.PodIPs 中存在同类型的地址,找到即刻返回。如果同类型地址不存在,则报错。
endpoint-controller-subnet.svg

Set Hostname

获取到 IP 地址的 EndpointAddress 结构,会根据下图条件,设置 EndpointAddress 结构的 Hostname 域。
endpoint-controller-set-hostname.svg

EndpointSubset

生成 EndpointAddress 后,根据 Service.ServiceSpec.Ports 配置,生成 EndpointSubset 列表,并存入全局的列表中。

  • 如果设置了 tolerateUnreadyEndpoints 或当前遍历的 Pod 处于 Ready 状态,Ready 计数 +1
  • 如果不满足上述情况,且当前遍历的 Pod 应该归属于 Endpoint,那么 Unready 计数 +1

endpoint-controller-subnet-port.svg

ResourceEventHandler for Pod

On Add Pod

endpoint-controller-on-add-pod.svg
从 API Server 获取 Pod.Namespace 下所有 Service。遍历 Service,如果缓存中没有该 Service 存在,更新缓存。从缓存中获取 Service 使用的 Selector,并与 Pod 的 Labels 比对,如果一致,说明该服务受到 Pod 影响,添加进队列等待处理。

On Update Pod

endpoint-controller-on-update-pod.svg

On Delete Pod

删除的 Pod 无法从 API Server 上获取,那么从传入的 obj 中获取即可。找到被删除节点后,处理方式就和添加 Pod 一样了。
image.png
获取 Pod 对象的方法如下
image.png