完全指南:API 动态发现、CRUD 与 Watch 实战)
后端云原生容器编排【免费下载链接】pythonOfficial Python client library for kubernetes项目地址https://gitcode.com/gh_mirrors/python1/python点击查看免费下载导读kubernetes.aio.dynamic.client是 Kubernetes 官方 Python 客户端当前仓库python中基于asyncio的**动态客户端DynamicClient**模块。与针对每个 API 群组生成静态方法如CoreV1Api的客户端不同动态客户端在运行时向集群 API Server 发起 discovery 请求动态发现资源类型并以统一的Resource对象执行增删改查。本文面向希望用异步方式操作原生资源与 CRDCustom Resource Definition的开发者读完你将掌握如何初始化异步动态客户端、如何通过resources.get(...)发现资源、如何使用get/create/delete/replace/patch/server_side_apply/watch等核心方法以及背后的资源对象模型、异常体系与缓存机制。文中所有代码均可直接复制运行需可访问的集群与 kubeconfig。一、模块定位与适用场景本模块由文档页 kubernetes.aio.dynamic.client.rst 通过automodule自动生成其源码位于 kubernetes/aio/dynamic/client.py。它对外导出DynamicClient—— 动态客户端主体Resource/ResourceList/ResourceInstance/ResourceField/Subresource—— 资源对象模型见 resource.pyEagerDiscoverer/LazyDiscoverer—— 资源发现策略见 discovery.py。适用场景在开发 Operator、控制器、自定义控制器或管理 CRD 的工具时静态生成的 API 无法覆盖集群中未知/新增的资源类型而动态客户端可以在运行时发现并操作任意已注册资源。同步版动态客户端位于 kubernetes/dynamic/而本模块是其在asyncio体系下的等价实现依赖kubernetes.aio的异步ApiClient。二、环境准备与客户端初始化异步动态客户端需要asyncio环境。当前仓库提供异步专属依赖与安装入口requirements-asyncio.txt、setup-asyncio.py。运行时需要一个可访问的 Kubernetes 集群有效的 kubeconfig或 in-cluster 配置异步 HTTP 客户端kubernetes.aio.client.ApiClient。2.1 标准初始化流程参考官方示例 configmap.pyimport asyncio from kubernetes.aio.client import api_client from kubernetes.aio.client.configuration import Configuration from kubernetes.aio.config import kube_config from kubernetes.aio.dynamic import DynamicClient async def main(): config Configuration() await kube_config.load_kube_config(client_configurationconfig) async with api_client.ApiClient(configurationconfig) as apic: client await DynamicClient(apic) # ... 使用 client if __name__ __main__: loop asyncio.new_event_loop() loop.run_until_complete(main()) loop.close()初始化时DynamicClient.__await__会调用discoverer(self, cache_file)并执行资源发现见 client.pydef __await__(self): async def closure(): self.__discoverer await self.discoverer(self, self.cache_file) return self return closure().__await__()因此await DynamicClient(apic)是必须的。也可以使用异步上下文管理器async with DynamicClient(apic) as client: ...其__aenter__与__await__等价地完成 discoverer 初始化见 client.py示例 accept_header.py 采用的就是这种写法。2.2 构造参数DynamicClient.__init__(client, cache_fileNone, discovererNone)见 client.py参数默认值说明client必填异步ApiClient实例同时提供configurationcache_fileNone资源发现结果的磁盘缓存文件路径discovererLazyDiscoverer发现策略类可替换为EagerDiscoverer初始化后可通过两个属性访问内部状态client.resources返回 discoverer 对象用于搜索资源client.version返回从/version端点获取的集群版本信息见 client.py。三、资源发现LazyDiscoverer 与 EagerDiscoverer动态客户端之所以动态核心在于 discovery 机制。抽象基类Discoverer负责向集群请求 API 组信息parse_api_groups按(prefix, group, version)拉取每个 API 组的资源清单get_resources_for_api_version将结果构建为Resource/ResourceList对象写入/读取本地缓存文件见 discovery.py。3.1 两种发现策略LazyDiscoverer默认discover()只加载 API 组骨架不立即请求每个组的资源当search()命中某个尚未拉取资源的组时才按需向集群请求该组的资源清单discovery.py。适合资源种类多的集群首启开销小。EagerDiscovererdiscover()一次性拉取所有 API 组的全部资源request_resourcesTrue适合对首查延迟敏感、资源种类可控的场景discovery.py。3.2 本地缓存机制Discoverer.__init__会根据client.configuration.host的 MD5 值生成默认缓存文件名osrcp-md5.json存放于系统临时目录discovery.py。缓存中记录了library_version当客户端库版本变化时缓存会被自动判定失效并刷新search在本地未命中时也会触发invalidate_cache()重新发现以感知新创建的 CRD。缓存通过CacheEncoder/CacheDecoder以_type字段实现对象与 JSON 的互相转换discovery.py。3.3 查找资源get 与 searchresources对象提供两个关键方法见 discovery.pysearch(prefix..., group..., api_version..., kind..., **kwargs)返回所有匹配的资源对象列表api_version中若包含/如apps/v1会被自动拆分为group与api_version。get(**kwargs)基于search的结果做消歧恰好匹配一个时返回该资源无匹配抛ResourceNotFoundError多匹配抛ResourceNotUniqueError。若有多个匹配优先选择api_version精确匹配者、其次优先非List类型。最常见的用法是# 内置资源 api await client.resources.get(api_versionv1, kindConfigMap) deploy await client.resources.get(api_versionapps/v1, kindDeployment) # 自定义资源CRD crd_api await client.resources.get( api_versionapiextensions.k8s.io/v1, kindCustomResourceDefinition ) ingressroute_api await client.resources.get( api_versionapps.example.com/v1, kindIngressRoute )注意创建 CRD 后discovery 缓存需要短暂刷新。官方示例与 e2e 测试采用先捕获ResourceNotFoundErrorawait asyncio.sleep(2)后重试的策略见 namespaced_custom_resource.py。四、核心 CRUD 操作DynamicClient的 CRUD 方法统一签名风格await api.get(...)、await api.create(body..., namespace...)。这些方法本质上都是先构建资源 URL 路径再调用统一的request方法。4.1 Resource.path 与 URL 构建Resource.path(nameNone, namespaceNone)根据资源的namespaced标志和传入参数从urls字典中选取合适的模板并格式化resource.pyurls { base: /{prefix}/{group_version}/{name_lower}, namespaced_base: /{prefix}/{group_version}/namespaces/{namespace}/{name_lower}, full: /{prefix}/{group_version}/{name_lower}/{name}, namespaced_full: /{prefix}/{group_version}/namespaces/{namespace}/{name_lower}/{name}, }4.2 获取get# 读取单个对象 pod await api.get(namemy-pod, namespacedefault) # 列出对象支持 label/field 选择器 pods await api.get(namespacedefault, label_selectorappnginx)get(resource, nameNone, namespaceNone, **kwargs)将name/namespace交给resource.path()并把label_selector、field_selector、pretty、limit、_continue、resource_version等透传给底层请求client.py。4.3 创建createawait api.create(bodyconfigmap_manifest, namespacedefault)create的处理逻辑client.pyserialize_body(body)若body是ResourceInstance具备to_dict先转回普通 dict否则原样使用若资源是namespaced的调用ensure_namespace—— 优先取namespace参数其次取body[metadata][namespace]两者皆无则抛出ValueError以POST请求resource.path(namespace...)。4.4 删除deleteawait api.delete(namemy-cm, namespacedefault) await api.delete(namemy-rc, namespacedefault, propagation_policyBackground)delete的校验逻辑client.py值得注意name、label_selector、field_selector至少提供其一否则抛ValueError(At least one of name|label_selector|field_selector is required)对 namespaced 资源还必须提供namespace、label_selector或field_selector之一否则抛ValueError。它支持propagation_policy、grace_period_seconds、orphan_dependents、dry_run等查询参数例如测试中用propagation_policyBackground删除 ReplicationController见 client_test.py。4.5 整体替换replaceawait api.replace(bodydeployment_manifest, namename, namespacedefault)replace基于PUT语义name可从参数或body[metadata][name]推断缺省抛ValueErrornamespaced 资源同样需要 namespaceclient.py。4.6 局部更新patchawait api.patch( bodyconfigmap_manifest, nameconfigmap_name, namespacedefault, )patch默认的Content-Type为application/strategic-merge-patchjsonKubernetes 内置资源的策略合并补丁对 CRD无策略合并语义应显式指定content_typeapplication/merge-patchjson示例见 namespaced_custom_resource.py。patch也会从body[metadata][name]推断nameclient.py。4.7 服务端应用server_side_applyresp await api.server_side_apply( namespacedefault, bodypod_manifest, field_managerkubernetes-unittests, dry_runAll, )server_side_apply强制使用Content-Type: application/apply-patchyaml并支持force_conflicts转为查询参数force、field_manager、dry_runclient.py。e2e 测试通过检查resp.metadata.managedFields[0].manager验证 field manager 生效client_test.py。五、异步 Watch实时监听资源事件DynamicClient.watch是静态方法用于流式监听资源事件client.pyasync for event in client.watch(api, timeout3, namespacedefault, namename): print(event[type]) # ADDED / MODIFIED / DELETED 等 print(event[object].metadata)参数与返回说明源码 docstring参数说明resource目标Resource对象namespace命名空间过滤name指定实例名内部自动转为field_selector fmetadata.name{name}label_selector/field_selector选择器过滤resource_version只返回大于该版本的事件timeout流式监听持续秒数内部映射为timeout_secondswatcher复用watch.Watch()实例可用watcher.stop()优雅停止每个事件是包含type、raw_object、object三个键的字典其中object被包装为ResourceInstance因此可以用点号访问字段。timeout传None时流不会自行终止——e2e 测试用asyncio.wait_for(..., timeout5)验证了这一点client_test.py。参考用法见 client.py 中的 docstring 示例。六、底层 request 与查询参数体系所有高层方法最终汇聚到request(method, path, bodyNone, **params)client.py。它被meta_request装饰器包裹装饰器负责把ApiException翻译成dynamic.exceptions中的语义化异常并把响应 JSON 序列化为ResourceInstance可通过serializeFalse关闭、用serializer替换序列化器见 client.py。request内部完成路径补/前缀、查询参数组装、Accept/Content-Type头设置、BearerToken 认证然后通过param_serializecall_api发起请求。支持的查询参数下划线命名 → HTTP 参数名包括Python 参数HTTP 查询参数prettypretty_continuecontinueinclude_uninitializedincludeUninitializedfield_selectorfieldSelectorlabel_selectorlabelSelectorlimitlimitresource_versionresourceVersiontimeout_secondstimeoutSecondswatchwatchgrace_period_secondsgracePeriodSecondspropagation_policypropagationPolicyorphan_dependentsorphanDependentsdry_rundryRunfield_managerfieldManagerforce_conflictsforce头部处理上Accept默认协商application/json与application/yamlContent-Type默认application/jsondiscovery 路由不接受通配*/*可通过header_params传入自定义头。测试中通过自定义Accept: application/json;asPartialObjectMetadataList;vv1;gmeta.k8s.io获取 PartialObjectMetadata 列表client_test.py示例见 accept_header.py。请求超时可通过_request_timeout参数控制示例 request_timeout.py 在每次调用中传入_request_time6060 秒客户端超时。七、资源对象模型Resource、ResourceInstance、ResourceField 等7.1 ResourceResource代表一种 API 资源类型保存构建 URL 所需的信息prefix、group、api_version、kind、namespaced、verbs、name、singular_name、short_names、subresources等。group_version属性在存在 group 时返回group/version如apps/v1否则仅返回版本。构造时要求api_version、kind、prefix至少不为空resource.py。Resource.__getattr__有两个巧妙行为若访问的属性名匹配某个subresource返回对应的Subresource对象否则返回partial(getattr(self.client, name), self)即把DynamicClient的方法如get、create绑定到该资源上。这就是await api.create(...)、await api.get(...)能够直接调用、且api自动作为resource参数传入的原因。7.2 SubresourceSubresource表示资源的子资源如scale、statusURL 形如/apis/{group}/{version}/namespaces/{ns}/{parent}/{name}/{subresource}同样继承DynamicClient的 CRUD 方法resource.py。7.3 ResourceListResourceList表示资源的*List类型持有base_kind支持对 List body 中每个 item 批量执行get、delete、create、replace、patchverb_mapper。注意其源码注释标注部分方法未被任何测试场景执行是否必要待确认批量语义请以实际行为为准resource.py。7.4 ResourceInstance 与 ResourceFieldResourceInstance是把 API 响应解析后的实例核心价值是支持点号访问resp.metadata.name、resp.spec.replicas、resp.status.conditions[0][type]。它递归地把 dict 解析为ResourceField__getattr__返回None而非抛错从而能通过hasattr判断、把 list 解析为 list同时保留resp[items]下标访问与resp.items点号访问两种形式。to_dict()可随时还原为纯 dictresource.py。__repr__会用 YAML 格式化打印对象便于调试。7.5 序列化serialize_body(body)client.py接受dict或ResourceInstance对具备to_dict的对象调用之否则原样返回空值返回{}。序列化测试覆盖了 dict、ResourceInstance、ResourceField 三种输入client_test.py。八、异常体系语义化 HTTP 错误动态客户端将底层ApiException通过api_exception()映射为语义化异常exceptions.pyHTTP 状态码异常类400BadRequestError401UnauthorizedError403ForbiddenError404NotFoundError405MethodNotAllowedError409ConflictError410GoneError422UnprocessibleEntityError429TooManyRequestsError500InternalServerError503ServiceUnavailableError504ServerTimeoutError未列出的状态码映射为通用DynamicApiError。所有动态异常继承ApiException保留status、reason、body、headers并额外携带original_tracebacksummary()可从 JSON body 中提取message字段。另有非 HTTP 异常ResourceNotFoundError资源未发现、ResourceNotUniqueError匹配到多个资源、KubernetesValidateMissing未安装kubernetes-validate。九、资源定义校验validateDynamicClient.validate(definition, versionNone, strictFalse)client.py用于校验资源定义是否合法依赖可选包kubernetes_validate未安装时抛KubernetesValidateMissingversion未指定时优先取self.version[kubernetes][gitVersion]即集群版本失败则回退到kubernetes_validate.latest_version()strictTrue时意外的多余属性会被视为错误返回(warnings, errors)二元组warnings中包括找不到对应 schema可能为自定义资源的提示errors中包括校验错误与Kubernetes 版本不受支持等。十、实战完整示例串讲10.1 ConfigMap 增删改查完整代码见 configmap.py流程为创建create→ 按名字 label 选择器列出get→ 修改 data 后patch→delete。其get返回的对象configmap_list.metadata.name、configmap_list.data展示了ResourceInstance的点号访问。10.2 Deployment 滚动重启完整代码见 deployment_rolling_restart.py创建 3 副本 nginx Deployment 后通过patch修改spec.template.metadata.annotations写入kubectl.kubernetes.io/restartedAt时间戳触发滚动重启最后删除。这是动态客户端驱动控制器式运维的典型例子。10.3 Node 集群级查询完整代码见 node.pyclient.resources.get(api_versionv1, kindNode)后列出所有节点并对每个节点二次get读取node.status.nodeInfo.kubeProxyVersion等字段。10.4 Namespaced / Cluster CRD 全流程完整代码见 namespaced_custom_resource.py 与 cluster_scoped_custom_resource.py。两者演示了动态客户端最核心的价值通过apiextensions.k8s.io/v1的CustomResourceDefinition资源创建 CRD捕获ResourceNotFoundError并等待约 2 秒等待 discovery 更新后重新resources.get获取自定义资源 API对自定义资源执行create/get列表/patch指定application/merge-patchjson/delete最后删除 CRD。两者的差别在于 CRDspec.scope为Namespaced需要 namespace还是Cluster不需要 namespace。10.5 自定义 Accept 头与请求超时accept_header.py 通过header_params传递Accept: application/json;asPartialObjectMetadataList;vv1;gmeta.k8s.io演示如何请求部分对象元数据request_timeout.py 演示每次调用传入_request_time60设置客户端超时。十一、测试与可靠性佐证模块自带 e2e 测试 client_test.py覆盖集群级与命名空间级自定义资源的完整生命周期含 watch 超时行为、缓存失效后资源不可见Service、ReplicationController、ConfigMap、Node 等内置资源的 CRUD 与propagation_policy、pretty、label_selector等参数PartialObjectMetadata自定义 Accept 头与 Server-Side Applyfield_manager、dry_runserialize_body对 dict / ResourceInstance / ResourceField 的序列化一致性。这些测试直接佐证了本文描述的调用签名、参数语义与异常行为是动手前值得通读的活文档。十二、使用注意事项小结必须异步初始化DynamicClient(apic)需要await或async with否则 discoverer 未初始化访问resources/version会失败。CRD 刚创建后需等待 discovery 刷新捕获ResourceNotFoundError后重试或调用client.resources.invalidate_cache()强制刷新。namespaced 资源必须提供 namespace可显式传namespace或在body[metadata][namespace]中声明否则抛ValueError。patch CRD 要显式指定 content_typeCRD 无策略合并语义使用application/merge-patchjson或application/json-patchjson内置资源才适用默认的strategic-merge-patchjson。delete 的选择器要求至少提供name/label_selector/field_selector之一namespaced 资源还需 namespace 或选择器。watch 记得设置 timeout 或主动 stoptimeoutNone时流不自动结束。validate 为可选能力依赖kubernetes_validate包未安装时相关调用会抛KubernetesValidateMissing。相关资源索引模块源码kubernetes/aio/dynamic/client.py、resource.py、discovery.py、exceptions.py官方示例examples_asyncio/dynamic-client/e2e 测试kubernetes/aio/dynamic/client_test.py同步版动态客户端参考kubernetes/dynamic/赞分享后端云原生容器编排【免费下载链接】pythonOfficial Python client library for kubernetes项目地址https://gitcode.com/gh_mirrors/python1/python点击查看免费下载相关推荐为什么选择vite-svg-loaderVue开发者不可错过的SVG加载神器为什么选择vite svg loaderVue开发者不可错过的SVG加载神器 vite svg loader是一款专为Vue开发者打造的Vite插件它能让你Kubernetes Python 客户端 asyncio 版 AppsV1Api 实战指南Deployment/StatefulSet/DaemonSet 全量异步 CRUD 编程Kubernetes Python 客户端 asyncio 版 AppsV1Api 实战指南Deployment/StatefulSet/DaemonSet后端云原生容器编排gRPC Python Reflection 实战指南服务端开启与客户端动态发现gRPC Python Reflection 实战指南服务端开启与客户端动态发现 导读 本文围绕 gRPC 仓库中的 doc/python/sphinx/gr后端RPC框架微服务通信上一篇Windows系统优化完整指南ExplorerPatcher专业安装与故障排除下一篇AutoValue SerializableAutoValue 扩展开发指南用 SerializerExtension 为任意非可序列化类型接入 Java 序列化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考