- 后端
- 云原生
- 容器编排
【免费下载链接】python
Official Python client library for kubernetes
本文基于开源仓库 gh_mirrors/python1/python 中由
doc/source/kubernetes.aio.client.models.v1_node_features.rst自动生成的模型文档,深入剖析V1NodeFeatures这一 Kubernetes Node 状态模型的设计初衷、字段语义、序列化规则及其在同步/异步客户端中的真实用法。读完本文,你将掌握如何通过 Kubernetes 官方 Python 客户端读取节点 CRI 实现的特性能力(尤其是 SupplementalGroupsPolicy 支持情况),并理解生成模型在 JSON 反序列化、别名解析与 pydantic 校验层面的实现细节,可直接用于集群巡检、调度能力判断与运行时兼容性探测等场景。
一、V1NodeFeatures 是什么:CRI 能力声明的数据载体
V1NodeFeatures对应 Kubernetes 核心 API(io.k8s.api.core.v1.NodeFeatures)中的一个模型类,其官方定义为:
NodeFeatures describes the set of features implemented by the CRI implementation. The features contained in the NodeFeatures should depend only on the cri implementation independent of runtime handlers.
翻译过来即是:该模型描述的是节点上容器运行时接口(CRI)实现所支持的功能集合,且这些特性只依赖于 CRI 实现本身,与具体的 runtime handler(运行时处理器)无关。这一点从仓库中同步生成的 API 文档 kubernetes/docs/V1NodeFeatures.md 和 kubernetes/aio/docs/V1NodeFeatures.md 可以得到完全一致的描述。
它在 Kubernetes 集群中的实际挂载位置是Node.status.features。也就是说,kubelet 上报节点状态时,会将 CRI 实现的特性集写入 Node 对象的status.features字段,客户端通过读取该字段即可获知节点运行时支持哪些高级容器能力。
二、字段语义:supplementalGroupsPolicy 的准确含义
V1NodeFeatures当前只有一个可选字段,源码中的完整声明位于 kubernetes/client/models/v1_node_features.py(异步版本见 kubernetes/aio/client/models/v1_node_features.py):
supplemental_groups_policy: Optional[StrictBool] = Field( default=None, validation_alias=AliasChoices("supplementalGroupsPolicy", "supplemental_groups_policy"), serialization_alias="supplementalGroupsPolicy", description="SupplementalGroupsPolicy is set to true if the runtime supports " "SupplementalGroupsPolicy and ContainerUser.", )其字段语义要点如下:
| 项目 | 值 | 说明 |
|---|---|---|
| 属性名(Python 端) | supplemental_groups_policy | snake_case 命名,Python 习惯 |
| 线缆名(Wire/JSON 端) | supplementalGroupsPolicy | camelCase 命名,与 Kubernetes API 对齐 |
| 类型 | Optional[StrictBool] | 布尔类型,None表示未上报 |
| 默认值 | None | 可选字段,未设置时输出 JSON 不含该键 |
| 含义 | true表示运行时支持SupplementalGroupsPolicy与ContainerUser | 判断 CRI 是否具备附加组策略能力 |
StrictBool意味着在 pydantic 校验时只接受严格的布尔值(True/False),不会把1、"true"之类的内容隐式转换,这保证了从 API 响应解析时数据类型的严谨性。
为了理解这个布尔标志的业务价值,可以对照同一仓库中的 kubernetes/aio/client/models/v1_pod_security_context.py:Pod 的securityContext.supplementalGroupsPolicy字段合法取值为"Merge"与"Strict"(默认Merge),其作用是决定容器首个进程的补充组(supplemental groups)计算方式——是合并镜像中定义的组成员关系,还是严格只使用显式指定的组。而使用该字段的前提就是运行时支持SupplementalGroupsPolicy特性门控,这正是Node.status.features.supplementalGroupsPolicy为true时所传达的能力信号。因此,在向某个节点调度带有supplementalGroupsPolicy: Strict的 Pod 前,先读取该节点的V1NodeFeatures做能力探测,是一个合理的防御性编程思路。
三、在 NodeStatus 中的位置:数据来源链路
V1NodeFeatures不是孤立存在的,它是V1NodeStatus的一个嵌套子模型。在 kubernetes/client/models/v1_node_status.py 中可以看到:
features: Optional[V1NodeFeatures] = None对应到openapi_types声明为"features": "V1NodeFeatures",attribute_map为"features": "features"(见同一文件 L129-L161)。这意味着 Node API 返回的status.features对象在反序列化时会被递归构造为V1NodeFeatures实例;反向序列化(from_dict)时则调用V1NodeFeatures.from_dict(obj["features"])(v1_node_status.py)。
V1NodeStatus还包含与特性相关的另一字段declared_features(List[str]),它表示节点声明的、与特性门控(feature gates)相关的特性列表。两者配合使用时:
status.features:CRI 实现本身具备的能力(本文主题);status.declaredFeatures:节点层面声明的特性门控列表。
二者共同刻画了节点在容器能力层面的“可做什么”。
四、同步与异步双实现:import 路径与使用差异
本仓库同时维护同步客户端与异步客户端两套生成代码,V1NodeFeatures在两侧均有完整实现且逻辑一致:
- 同步版:kubernetes/client/models/v1_node_features.py
- 异步版:kubernetes/aio/client/models/v1_node_features.py
异步版在 kubernetes/aio/client/init.py 与 kubernetes/aio/client/models/init.py 中导出;同步版则通过 kubernetes/client/init.py 导出,并在 L1345 处执行from kubernetes.client.models.v1_node_features import V1NodeFeatures as V1NodeFeatures,同时注册进__all__(L415)与模块映射(L2270),保证from kubernetes.client import V1NodeFeatures可以直接工作。
由于模型层是纯数据结构、无网络 IO,同步与异步版本在字段、方法与校验规则上完全对齐,唯一差异是上层 API 调用的并发模型:
# 同步方式:直接使用模型类 from kubernetes.client.models.v1_node_features import V1NodeFeatures # 异步方式:使用 aio 包路径 from kubernetes.aio.client.models.v1_node_features import V1NodeFeatures异步客户端完整示例可参考仓库 examples_asyncio/list_pods.py;同步方式可参考 examples/deployment_create.py 的建连思路。需要注意的是,异步客户端需要额外的依赖,其依赖清单见 requirements-asyncio.txt。
五、核心 API 方法逐个击破:序列化与反序列化
作为 OpenAPI Generator 生成的 pydantic 模型,V1NodeFeatures提供了一组完整的数据转换方法,源码见 kubernetes/client/models/v1_node_features.py。下面逐一说明。
5.1 from_json:从 JSON 字符串构造实例
@classmethod def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of V1NodeFeatures from a JSON string""" return cls.from_dict(json.loads(json_str))它先把 JSON 字符串json.loads成 Python dict,再交给from_dict。例如:
features = V1NodeFeatures.from_json('{"supplementalGroupsPolicy": true}') print(features.supplemental_groups_policy) # True5.2 from_dict:从字典构造实例(别名归一化关键)
@classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj is None: return None if not isinstance(obj, dict): return cls.model_validate(obj) obj = _cast(Dict[str, Any], cls.__preprocess_input_names(obj, remove_hidden_storage_names=True)) _obj = cls.model_validate({"supplementalGroupsPolicy": obj.get("supplementalGroupsPolicy")}) return _obj这里的__preprocess_input_names做了一件事:同时接受 camelCase 与 snake_case 两种输入键。源码中逻辑为:如果 dict 中没有"supplementalGroupsPolicy"但有"supplemental_groups_policy",则把后者复制为前者,随后移除 snake_case 键(v1_node_features.py)。这意味着以下两种写法等价:
V1NodeFeatures.from_dict({"supplementalGroupsPolicy": True}) # 线缆格式 V1NodeFeatures.from_dict({"supplemental_groups_policy": True}) # Python 风格此外model_config设置了validate_by_name=True, validate_by_alias=True, validate_assignment=True, extra="forbid"(L130-L136),其中extra="forbid"意味着传入未知字段会直接校验失败,避免拼写错误被静默忽略。
5.3 to_dict:转回普通字典
def to_dict(self, serialize: bool = False) -> Dict[str, Any]: """Return all declared model fields using public or wire names.""" return { ("supplementalGroupsPolicy" if serialize else "supplemental_groups_policy"): _to_legacy_value(getattr(self, "supplemental_groups_policy", None), serialize), }注意:默认(serialize=False)输出 snake_case 键supplemental_groups_policy;serialize=True时输出线缆格式supplementalGroupsPolicy。若字段值为None(即未设置),_to_legacy_value会原样返回None。
5.4 to_json / to_str:JSON 与可读字符串
to_json使用serialization_alias(即supplementalGroupsPolicy)输出 JSON,并经由to_jsonable_python保证可被json.dumps直接处理(L162-L167);to_str则调用pprint.pformat(self.to_dict())给出易读的调试文本(L139-L141)。
5.5 完整示例:JSON → 实例 → 字典 → 实例 的往返
以下是 kubernetes/docs/V1NodeFeatures.md 中官方示例的完善版,可直接复制运行:
from kubernetes.client.models.v1_node_features import V1NodeFeatures # TODO 按需更新 JSON 字符串 json_str = '{"supplementalGroupsPolicy": true}' # 从 JSON 字符串创建实例 v1_node_features_instance = V1NodeFeatures.from_json(json_str) # 打印 JSON 字符串表示(输出线缆格式键) print(V1NodeFeatures.to_json()) # {"supplementalGroupsPolicy": true} # 转换为普通 dict(默认输出 snake_case 键) v1_node_features_dict = v1_node_features_instance.to_dict() print(v1_node_features_dict) # {'supplemental_groups_policy': True} # 从 dict 重新创建实例 v1_node_features_from_dict = V1NodeFeatures.from_dict(v1_node_features_dict) assert v1_node_features_from_dict == v1_node_features_instance此外,模型实现了__eq__/__ne__(基于to_dict()结果比较,L147-L159),因此两个语义相同的实例可以直接用==比较。
六、真实场景:读取节点 CRI 能力
下面给出一个基于同步客户端的实战片段,演示如何从 Node 对象中取出features并判断运行时是否支持SupplementalGroupsPolicy:
from kubernetes import client, config config.load_kube_config() # 或 config.load_incluster_config() 在集群内运行 v1 = client.CoreV1Api() for node in v1.list_node().items: features = node.status.features # V1NodeFeatures | None if features is None: print(f"{node.metadata.name}: 未上报 features") continue support = features.supplemental_groups_policy print(f"{node.metadata.name}: supplementalGroupsPolicy 支持 = {support}")- 若
support is True:CRI 支持SupplementalGroupsPolicy与ContainerUser,可以向该节点调度使用securityContext.supplementalGroupsPolicy: Strict的 Pod(前提是该特性门控已开启); - 若
support is False或None:运行时能力不明确或未上报,调度时应保守处理。
异步版本则使用kubernetes.aio包,整体流程与 examples_asyncio/list_pods.py 一致,只需把client换成client(aio 包同名模块)、把 API 调用变为await即可。
七、模型生成源头:从 Swagger 到 Python
V1NodeFeatures是代码生成产物,其源头定义在仓库内的 OpenAPI 描述文件中。在 kubernetes/aio/swagger.json.unprocessed 中可以看到原始 schema:
"io.k8s.api.core.v1.NodeFeatures": { "description": "NodeFeatures describes the set of features implemented by the CRI implementation. The features contained in the NodeFeatures should depend only on the cri implementation independent of runtime handlers.", "properties": { "supplementalGroupsPolicy": { "description": "SupplementalGroupsPolicy is set to true if the runtime supports SupplementalGroupsPolicy and ContainerUser.", "type": "boolean" } }, "type": "object" }"type": "boolean"对应 Python 端的StrictBool,"supplementalGroupsPolicy"(camelCase)被映射为 Python 属性supplemental_groups_policy,并通过AliasChoices实现双向别名兼容。该 schema 的版本标注为release-1.37(见生成文件头部的 OpenAPI document 版本说明),也就是模型能力以 Kubernetes 1.37 API 快照为准。仓库中同步生成客户端的脚本位于 scripts/update-client.sh 与 scripts/update-client-asyncio.sh,文档树则通过 doc/Makefile 配合 Sphinx 的automodule指令生成——这正是doc/source/kubernetes.aio.client.models.v1_node_features.rst里.. automodule:: kubernetes.aio.client.models.v1_node_features的职责所在。
八、常见问题速查
| 问题 | 结论 |
|---|---|
features.supplemental_groups_policy为None怎么办? | 表示字段未上报,属于可选字段,读取端应做空值防护 |
| 传入的 dict 键该用 camelCase 还是 snake_case? | 均可,from_dict的__preprocess_input_names会自动归一化 |
to_dict()与to_json()输出的键名不一致? | 正常:to_dict()默认 snake_case,to_json()与serialize=True输出 camelCase 线缆格式 |
| 传入多余字段会怎样? | 校验失败,因为extra="forbid" |
| 同步与异步模型有差异吗? | 无实质差异,字段、方法与规则一致,仅包路径不同 |
总结
V1NodeFeatures虽小,却是连接「节点 CRI 能力」与「客户端程序判断逻辑」的关键桥梁。本文从模型定义、字段语义、NodeStatus 挂载位置、同步/异步双实现、序列化 API 到实战读取,完整覆盖了该模型在 gh_mirrors/python1/python 仓库中的全部可用细节。读者在实际项目中可直接以node.status.features.supplemental_groups_policy作为运行时能力探针,并在调度敏感工作负载前结合 Pod 安全上下文的supplementalGroupsPolicy字段做一致性校验。进一步阅读可参考 kubernetes/docs/V1NodeFeatures.md、kubernetes/aio/docs/V1NodeFeatures.md 与 kubernetes/docs/V1NodeStatus.md。
- 后端
- 云原生
- 容器编排
【免费下载链接】python
Official Python client library for kubernetes
相关推荐
Kubernetes Python 客户端 V1CustomResourceValidation 模型解析:为 CRD 声明 OpenAPI v3 Schema 校验
Kubernetes Python 客户端 V1CustomResourceValidation 模型解析:为 CRD 声明 OpenAPI v3 Schema
后端云原生容器编排Kubernetes Python 客户端 V1DeviceClaimConfiguration 详解:DRA 设备声明配置模型解析与实战
Kubernetes Python 客户端 V1DeviceClaimConfiguration 详解:DRA 设备声明配置模型解析与实战 本指南以 Kuber
后端云原生容器编排Perfetto heapprofd 原生堆内存分析指南:从 3 分钟上手到 SQL 深挖
Perfetto heapprofd 原生堆内存分析指南:从 3 分钟上手到 SQL 深挖 想让"这些内存到底是谁分配的"有个确切答案?Perfetto 的 h
后端云原生容器编排
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考