bigywater.tech
Kubernetes · 106

kubectl explain 与 api-resources:API 的自描述

kubectl explain 的字段文档从哪来?api-resources 是怎么知道集群里有什么资源的?CRD 装好之后 explain 能不能用?这篇看 discovery 请求、OpenAPI v3 文档本身,再装一个 CRD 验证它们如何同步。

2 个请求
冷缓存下 api-resources 发出的发现请求数:GET /api 和 GET /apis
702 KiB / 166
apps/v1 的 OpenAPI v3 文档大小与其中的 schema 数
1.8 秒
创建 CRD 后 kubectl explain 能显示其字段文档所需的时间

api-resources 与发现

实测 · 本机执行输出
  kubectl api-resources:共 73 种资源;namespaced 的 35 种,集群级的 38 种
  kubectl api-versions:24 个 group/version,例如 ['admissionregistration.k8s.io/v1', 'apiextensions.k8s.io/v1', 'apiregistration.k8s.io/v1', 'apps/v1']
  --api-group=apps -o wide:
    NAME SHORTNAMES APIVERSION NAMESPACED KIND VERBS CATEGORIES
    controllerrevisions apps/v1 true ControllerRevision create,delete,deletecollection,get,list,patch,update,watch
    daemonsets ds apps/v1 true DaemonSet create,delete,deletecollection,get,list,patch,update,watch all
    deployments deploy apps/v1 true Deployment create,delete,deletecollection,get,list,patch,update,watch all
  只看集群级且支持 create 的:['namespaces', 'nodes', 'persistentvolumes', 'mutatingadmissionpolicies', 'mutatingadmissionpolicybindings', 'mutatingwebhookconfigurations', 'validatingadmissionpolicies', 'validatingadmissionpolicybindings']…共 36 种
  冷缓存(--cache-dir 是新目录)下 api-resources 发出的 GET 请求:['/127.0.0.1:50727/api?timeout=32s', '/127.0.0.1:50727/apis?timeout=32s'](聚合发现:/api 和 /apis 两个请求就拿到全部资源)
  GET /apis(普通 Accept)返回的 group 数 22

kubectl api-resources 共 73 种资源,其中命名空间级 35 种、集群级 38 种;kubectl api-versions 有 24 个 group/version。--api-group=apps -o wide 多出 VERBS 和 CATEGORIES 两列(例如 deployments 简称 deploy,支持 create / delete / deletecollection / get / list / patch / update / watch,属于 all 类)。冷缓存下(--cache-dir 指向新目录)api-resources 只发出 GET /api 和 GET /apis 两个请求——聚合发现一次拿全,不用逐个 group 去问。

explain

实测 · 本机执行输出
  kubectl explain pod.spec.containers.imagePullPolicy:
    KIND:       Pod
    VERSION:    v1
    
    FIELD: imagePullPolicy <string>
    ENUM:
        Always
        IfNotPresent
        Never
    
  kubectl explain deployment.spec.strategy.rollingUpdate:
    GROUP:      apps
    KIND:       Deployment
    VERSION:    v1
    
    FIELD: rollingUpdate <RollingUpdateDeployment>
    
    
    DESCRIPTION:
  kubectl explain service.spec.type 的 FIELD/VERSION/TYPE 头:['KIND: Service', 'VERSION: v1', 'FIELD: type <string>', 'ENUM:']
  explain deployment.spec --recursive 展开了 1276 行字段树(前几行:['Specification of the desired behavior of the Deplo', 'DeploymentSpec is the specification of the desired', 'Deployment.', 'minReadySeconds\t<integer>', 'paused\t<boolean>', 'progressDeadlineSeconds\t<integer>'])
  不存在的字段 pod.spec.nonexistent:退出码 1;error: field "nonexistent" does not exist
  指定 API 版本:--api-version=networking.k8s.io/v1 → ['GROUP: networking.k8s.io', 'KIND: Ingress', 'VERSION: v1']

kubectl explain pod.spec.containers.imagePullPolicy 显示 FIELD: imagePullPolicy <string> 和 ENUM: Always / IfNotPresent / Never;explain deployment.spec --recursive 展开 1276 行字段树;不存在的字段返回 error: field "nonexistent" does not exist;--api-version=networking.k8s.io/v1 可以选定 group 和版本。

OpenAPI 文档本身

实测 · 本机执行输出
  GET /openapi/v3:51 个路径(每个 group/version 一份文档),例如 ['.well-known/openid-configuration', 'api', 'api/v1', 'apis']
  GET /openapi/v3/apis/apps/v1:702 KiB;含 166 个 schema;其中 io.k8s.api.apps.v1.Deployment 的字段:['apiVersion', 'kind', 'metadata', 'spec', 'status']
  Container.imagePullPolicy 在 OpenAPI 里:type=string;enum=['Always', 'IfNotPresent', 'Never'];description 开头='Image pull policy. One of Always, Never, IfNotPresent. Defaults to Alw'…
  Deployment 的 x-kubernetes-group-version-kind=[{'group': 'apps', 'kind': 'Deployment', 'version': 'v1'}]

explain 的数据来自 OpenAPI v3:GET /openapi/v3 列出 51 个路径(每个 group/version 一份,如 api/v1、apis);GET /openapi/v3/apis/apps/v1 约 702 KiB,含 166 个 schema,io.k8s.api.apps.v1.Deployment 的字段是 apiVersion、kind、metadata、spec、status;Container.imagePullPolicy 的 schema 里有 type=string、enum 和 description;x-kubernetes-group-version-kind 把 schema 对应到资源。

CRD 自动并入

实测 · 本机执行输出
  创建 CRD gadgets.k100.example.com 后 0.0 秒,api-resources 里出现 gadgets(简称 gd),总数 73 → 74
  kubectl explain gadget.spec.color(1.8 秒后可用):
    GROUP:      k100.example.com
    KIND:       Gadget
    VERSION:    v1
    
    FIELD: color <string>
    ENUM:
        red
        green
  kubectl explain gadget.spec 的字段列表:['FIELD: spec <Object>', 'DESCRIPTION:', ' Gadget 的期望状态', 'FIELDS:', ' color <string>']

创建 CRD gadgets.k100.example.com(简称 gd,spec.size 整数、spec.color 枚举 red / green / blue)后,api-resources 里立刻出现 gadgets,总数 73 → 74;kubectl explain gadget.spec.color 在 1.8 秒后可用,显示 GROUP: k100.example.com、ENUM: red green blue 和 CRD schema 里写的中文 description。给自己的 CRD 写好 schema 和 description,用户就能直接 explain。

分步演示

API 自描述
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0,kubectl 1.36);“冷缓存”用 --cache-dir 指向一个新建的临时目录,-v=6 读 kubectl 发出的 GET;OpenAPI 文档用 kubectl get --raw /openapi/v3/... 直接取;资源数量是这个集群当时的值(装了 metrics-server);CRD 同步时间每 0.3~0.5 秒轮询,单次测量;每种情形各一次
    • 没有验证:发现缓存失效规则(~/.kube/cache);OpenAPI v2(swagger)与 v3 的差异;kubectl explain 在 CRD 多版本时的版本选择;aggregated API(metrics.k8s.io)的发现;server-side field validation 如何利用 OpenAPI;kubectl api-resources 的 --cached 选项
    京ICP备2026067502号-1京公网安备11010502063487号