☰
Kubernetes Python Client 的 DiscoveryV1EndpointPort 模型详解:EndpointSlice 端口定义与异步客户端实战
2026/9/28 3:27:12 网站建设 项目流程
  • 后端
  • 云原生
  • 容器编排

【免费下载链接】python

Official Python client library for kubernetes

项目地址:https://gitcode.com/gh_mirrors/python1/python
点击查看免费下载

本篇文章聚焦 Kubernetes 官方 Python 客户端(kubernetes-python-client)中kubernetes.aio.client.models.discovery_v1_endpoint_port模块所定义的DiscoveryV1EndpointPort模型。该模型是 EndpointSlice 中描述单个网络端口的核心数据结构,读者将掌握其四个字段的完整语义与校验规则、pydantic 底层序列化机制,以及如何在同步与异步客户端中通过V1EndpointSlice与DiscoveryV1Api完成端口的创建、读取与转换。

一、模型定位:EndpointSlice 的端口描述单元

DiscoveryV1EndpointPort的官方定义是 "EndpointPort represents a Port used by an EndpointSlice",即它在 Kubernetes 的 discovery API 体系中承担"单个端点(Pod/IP)上暴露的一个网络端口"的建模职责。

在 Kubernetes 中,EndpointSlice(discovery.k8s.io/v1)是对传统 Endpoints 对象的一种可扩展分片替代方案。一个 EndpointSlice 由addressType、endpoints(端点列表)和ports(端口列表)三部分组成,其中ports列表的每个元素正是DiscoveryV1EndpointPort。从本仓库源码 v1_endpoint_slice.py 可以看到:

ports: Optional[List[DiscoveryV1EndpointPort]] = Field( default=None, description="ports specifies the list of network ports exposed by each endpoint in this slice. ..." )

同时该字段还有明确的规模约束:每个 slice 最多包含 100 个端口;由于 Service 至少有一个端口,由 EndpointSlice controller 生成的 slice 也至少包含一个端口;用于其他目的的自定义 EndpointSlice 则允许ports为空列表。这正解释了为什么本文的主角是一个"小而关键"的模型——它直接决定了 EndpointSlice 能被 kube-proxy 等组件正确消费。

二、模块文档的组织方式

doc/source/kubernetes.aio.client.models.discovery_v1_endpoint_port.rst是 Sphinx 文档中的 automodule 占位页:

kubernetes.aio.client.models.discovery_v1_endpoint_port module ================================================================= .. automodule:: kubernetes.aio.client.models.discovery_v1_endpoint_port :members: :show-inheritance: :undoc-members:

也就是说,该 RST 页面本身并不直接书写文档正文,而是通过automodule指令在构建时从 Python 模块源码中提取 docstring 自动生成 API 文档。因此,文档的真实技术内容全部沉淀在模型源码 kubernetes/aio/client/models/discovery_v1_endpoint_port.py 中,其类定义位于 L96-L247。文章后续的所有字段语义与行为说明均以这份源码及其生成的文档为准。

三、字段完整解析(核心内容)

DiscoveryV1EndpointPort基于 pydantic 的BaseModel定义,共包含四个可选字段。其openapi_types与attribute_map(见 源码 L110-L122)声明了 Python 属性名与 JSON 线上的序列化名称(camelCase)之间的映射关系:

Python 属性JSON 字段类型是否必填说明摘要
app_protocolappProtocolstr可选应用层协议提示,遵循 Kubernetes 标签语法
namenamestr可选端口名称,需通过 DNS_LABEL 校验,默认空字符串
portportint可选端口号;Service 派生 slice 时等于 targetPort
protocolprotocolstr可选IP 协议,取值 UDP/TCP/SCTP,默认 TCP

3.1 appProtocol:应用层协议提示

app_protocol用于向实现方提示该端口的应用层协议,帮助提供更丰富的协议感知行为(例如协议检测、流量特征识别)。该字段遵循标准 Kubernetes 标签(label)语法,合法取值分为三类:

  • 无前缀协议名:保留给 IANA 标准服务名使用(依据 RFC-6335 及 IANA service names 注册表),例如http、https这类通用名称;
  • Kubernetes 定义的前缀名称:
    • kubernetes.io/h2c—— 明文 HTTP/2 直连(prior knowledge),对应 RFC 9113 中关于 HTTP/2 直连启动的描述;
    • kubernetes.io/ws—— 明文 WebSocket(对应 RFC 6455);
    • kubernetes.io/wss—— 基于 TLS 的 WebSocket(对应 RFC 6455);
  • 其他协议:应使用实现方自定义的前缀名称,例如mycompany.com/my-custom-protocol。

从 字段定义源码 L106 可见,该字段使用AliasChoices("appProtocol", "app_protocol")同时接受 camelCase 与 snake_case 两种输入写法,序列化时固定输出为appProtocol。

3.2 name:端口唯一名称

name表示端口名称,其约束是 EndpointSlice 语义层面的核心规则:一个 EndpointSlice 内所有端口的名称必须唯一。如果该 EndpointSlice 由 Kubernetes Service 派生而来,则此名称对应该 Service 中ports[].name。

名称取值要么是空字符串,要么必须通过 DNS_LABEL 校验,具体规则(见 源码 L107):

  • 长度不超过 63 个字符;
  • 只能由小写字母、数字和连字符-组成;
  • 必须以字母或数字开头和结尾。

默认值为空字符串。

3.3 port:端点端口号

port表示端点实际监听/暴露的端口号。关键的语义约定是:如果 EndpointSlice 由 Kubernetes Service 派生,则该值必须设置为该 Service 的 targetPort(即转发到 Pod 的目标端口),而非 Service 对外暴露的port。用于其他目的的自定义 EndpointSlice 允许port为None(即文档所述 "may have a nil port")。类型上它是Optional[StrictInt],pydantic 的StrictInt会拒绝非 int 类型的隐式转换。

3.4 protocol:IP 层协议

protocol表示该端口的 IP 层协议,取值必须是UDP、TCP或SCTP三者之一,默认值为TCP。结合appProtocol的使用场景可以理解:protocol回答"传输层用什么协议",而appProtocol回答"应用层是什么协议",二者互补,共同描述一个端口的完整协议栈。

四、模型底层机制:pydantic 校验与序列化

作为 OpenAPI Generator 基于 Kubernetes OpenAPI 规范(source 注释标注版本为release-1.37,见 源码 L8)自动生成的模型,DiscoveryV1EndpointPort的底层行为由model_config统一控制(源码 L139-L145):

model_config = ConfigDict( validate_by_name=True, validate_by_alias=True, validate_assignment=True, extra="forbid", protected_namespaces=(), )
  • validate_by_name=True与validate_by_alias=True:既可按属性名(snake_case)也可按别名(camelCase)进行输入校验,配合字段上的AliasChoices实现"写app_protocol或appProtocol都能正确赋值";
  • validate_assignment=True:实例创建之后直接给属性赋值也会触发类型校验;
  • extra="forbid":拒绝未知字段,避免把拼写错误的字段静默带入请求体;
  • protected_namespaces=():允许使用model_*之类前缀的属性名而不触发 pydantic 保留命名空间警告。

在序列化层面,模型提供了一组完整的方法:

  • to_dict(serialize=False):返回 Python 字典。默认使用 public 名称(snake_case,如app_protocol);当serialize=True时切换为 wire 名称(camelCase,如appProtocol),见 源码 L183-L190;
  • to_json():返回 JSON 字符串表示,使用别名(camelCase)输出;
  • from_json(json_str):从 JSON 字符串解析出模型实例,内部经由from_dict;
  • from_dict(obj):从字典构造实例。其内部会先调用__preprocess_input_names(源码 L125-L137),将 snake_case 的app_protocol归一化为appProtocol后再进行 pydantic 校验;
  • to_str()/__repr__:返回便于调试打印的格式化字符串。

五、实战:在同步与异步客户端中使用该模型

仓库中kubernetes/client(同步)与kubernetes/aio/client(异步)两个包各有一份完全同构的模型文件:

  • 同步版:kubernetes/client/models/discovery_v1_endpoint_port.py
  • 异步版:kubernetes/aio/client/models/discovery_v1_endpoint_port.py

两份实现除导入路径外逻辑一致,均已在各自的models/__init__.py中导出,可直接from kubernetes.aio.client.models import DiscoveryV1EndpointPort导入。

5.1 基础构造与序列化

以官方文档示例为基础(见 kubernetes/aio/docs/DiscoveryV1EndpointPort.md),模型的基本用法如下:

from kubernetes.aio.client.models.discovery_v1_endpoint_port import DiscoveryV1EndpointPort # 直接按字段构造 port = DiscoveryV1EndpointPort( app_protocol="kubernetes.io/h2c", name="http", port=8080, protocol="TCP", ) # 从 JSON 字符串创建实例 port_from_json = DiscoveryV1EndpointPort.from_json( '{"appProtocol": "kubernetes.io/h2c", "name": "http", "port": 8080, "protocol": "TCP"}' ) # 转回字典(默认 snake_case)与 JSON(camelCase) port_dict = port.to_dict() print(port.to_json()) # {"appProtocol": "kubernetes.io/h2c", ...} # 字典 -> 模型 -> 字典 的往返转换 port_from_dict = DiscoveryV1EndpointPort.from_dict(port_dict)

注意:由于配置了extra="forbid",若传入{"appProtocols": ...}这类拼写错误的键会直接触发校验错误,这有助于在请求发出前就暴露问题。

5.2 组合进 V1EndpointSlice 并调用 DiscoveryV1Api

实际业务中DiscoveryV1EndpointPort极少单独使用,更多是作为V1EndpointSlice.ports的元素参与 CRUD。下面给出一个异步客户端中"构建并创建带端口列表的 EndpointSlice"的完整流程示意:

import asyncio from kubernetes import config from kubernetes.aio.client import ApiClient, Configuration from kubernetes.aio.client.api import DiscoveryV1Api from kubernetes.aio.client.models import ( V1EndpointSlice, V1EndpointSliceSpec, V1Endpoint, DiscoveryV1EndpointPort, V1ObjectMeta, ) async def create_slice_with_ports(): await config.load_kube_config() # 加载 ~/.kube/config client = ApiClient(Configuration()) api = DiscoveryV1Api(client) ports = [ DiscoveryV1EndpointPort(name="http", port=8080, protocol="TCP", app_protocol="kubernetes.io/h2c"), DiscoveryV1EndpointPort(name="metrics", port=9090, protocol="TCP"), ] endpoint_slice = V1EndpointSlice( api_version="discovery.k8s.io/v1", kind="EndpointSlice", metadata=V1ObjectMeta(name="my-slice", namespace="default", labels={"kubernetes.io/service-name": "my-service"}), address_type="IPv4", endpoints=[V1Endpoint(addresses=["10.0.0.1"])], ports=ports, ) created = await api.create_namespaced_endpoint_slice( namespace="default", body=endpoint_slice ) print(created) await client.close() asyncio.run(create_slice_with_ports())

从 discovery_v1_api.py 的源码结构可以看到,DiscoveryV1Api为 EndpointSlice 提供了完整的异步方法族:create_namespaced_endpoint_slice、read_namespaced_endpoint_slice、list_namespaced_endpoint_slice、list_endpoint_slice_for_all_namespaces、patch_namespaced_endpoint_slice、replace_namespaced_endpoint_slice、delete_namespaced_endpoint_slice,每个方法还伴随_with_http_info(返回(ApiResponse, status, headers)元组)与_without_preload_content(流式/原始响应)两个变体,便于按需选择调用形态。

值得留意的是,请求发送时V1EndpointSlice.to_dict()会逐项调用其内部DiscoveryV1EndpointPort.to_dict()(见 v1_endpoint_slice.py 的 to_dict 实现 L233-L238),从而确保嵌套的端口对象被正确展开为 camelCase 的 JSON 字段后写入请求体。

六、版本与使用前提

  • 该模型由 OpenAPI Generator 自动生成,对应 Kubernetes OpenAPI 文档版本release-1.37(当前仓库源码标注),适用于discovery.k8s.io/v1API 组;
  • 同步版本(kubernetes.client.models.discovery_v1_endpoint_port)适用于常规线程阻塞式调用;异步版本(kubernetes.aio.client.models.discovery_v1_endpoint_port)基于asyncio,需配合await与异步ApiClient使用;
  • 本模块是文档(RST + 自动生成的 API 页)与源码一一对应的典型样例,读者若需查看字段的完整英文原始描述,可直接查阅 DiscoveryV1EndpointPort.md 或同步版文档 kubernetes/docs/DiscoveryV1EndpointPort.md。

综上,DiscoveryV1EndpointPort虽然只有四个字段,却是连接 Service 端口语义与 EndpointSlice 网络拓扑的关键桥梁。理解其字段约束(唯一名称、DNS_LABEL、targetPort 对应关系、协议取值)与 pydantic 序列化行为(camelCase 别名、严格校验、嵌套展开),即可在基于 Kubernetes Python 客户端的服务发现、流量转发与自定义 EndpointSlice 场景中准确无误地读写端口信息。

  • 后端
  • 云原生
  • 容器编排

【免费下载链接】python

Official Python client library for kubernetes

项目地址:https://gitcode.com/gh_mirrors/python1/python
点击查看免费下载

相关推荐

上一篇:5步掌握AI变声神器RVC:从零到精通的完整实战指南
下一篇:并行区块引擎:重新定义游戏世界加载性能

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询