GVK
在本节中,我们将介绍GVK的概念,同时会进一步扩充前面初识kind小节引入的kind概念。
从GVR说起
在正式介绍GVK之前,我们需要从一个近似的术语GVR说起;
通常,对于一个Kubernetes API URL,我们可以从中提取出它的API分组(group),版本(version),以及资源类型(resource type)信息,例如:
换个角度来说,我们也可以认为资源类型依属于API分组和版本而存在——想要唯一确定一种资源类型,我们还需要API分组和版本信息(为了叙述上的方便,在后续章节中,我们将简称API分组和版本为GV)。 由group,version,以及resource type这三个字符串组成的三元组被称为GroupVersionResource,简称GVR。
实际上GVR的概念来源于apimachinery
库中一个简单却又基础的结构体,它被定义在runtime
包的schema
下:
type GroupVersionResource struct {
Group string
Version string
Resource string
}
我们其实可以这样认为,先有了源码上定义的结构体,再衍生出了相关术语和概念。🌧️️
这是本书第一次具体引用apimachinery
库中的代码。
apimachinery
库是Kubernetes API类型系统的基石。在apimachinery
库中,定义了许多基础接口和元类型。
在后续的runtime.Object小节,我们还会介绍这些基础接口和元类型。
我们介绍GVR的目的仅仅是为了引出GVK的概念。本书所讨论的内容并不依赖于GVR。GVR概念在kube-apiserver
组件以及kubectl
命令行工具中有重要应用。
对于kube-apiserver
来说,作为服务端,它需要完成从HTTP Path中包含的GVR信息到具体Go类型的映射和转换。
对于kubectl
工具, 它需要完成从命令包含的GVR信息到具体Go类型的映射和转换。
例如:
$ kubectl get deployments {deploy} -n default
其中deployments
正是资源类型。kubectl
工具其实在背后默默地为资源类型补全了API分组和版本信息,最后组装成发送到Kubernetes API的REST请求。
另外,值得一提的是:上述kubectl
用法虽然常见,但是它其实是一个会"产生歧义"的用法,特别是当一个资源类型同时存在于多个版本时或分组时。
例如,以horizontalpodautoscalers
(hpa)为例,在Kubernetes v1.25中同时存在:v1
以及v2beta2
两个版本。
通过命令:
$ kubectl get horizontalpodautoscalers {hpa} -n default
只能默认获得v1
版本的资源。将资源类型带上分组和版本信息,我们可以通过如下形式的命令获取某一个特定分组及版本的资源:
kubectl get horizontalpodautoscalers.v2beta2.autoscaling {hpa} -n default
从GVR到具体Go类型的映射相关的重要数据类型是RESTMapper
,它也被定义在apimachinery
库中,但这不在本书的讨论范围之内,感兴趣的读者请参考扩展阅读Kubernetes API请求的生命周期。
从GVR到GVK
在之前的初识kind小结,我们介绍了每种资源类型都对应一个Go类型——kind。
相应地,与GroupVersionResource类似,kind也有一个与之对应的结构体GroupVersionKind。
在Kubernetes中,由Go类型本身的名称和此类型所在的分组和版本三个字符串组成的三元组被成为GroupVersionKind,简称GVK。
它在apimachinery
库中对应的数据结构为:
type GroupVersionKind struct {
Group string
Version string
Kind string
}
例如,Job
类型的名字为Job
,由Job
,batch
(API分组),v1
(版本)三个字符串组成的三元组即为GVK。
与资源类型一样,想要唯一确定一种kind,我们还需要GV的信息。
其实,kind/资源类型不仅可以拥有不同版本,它们甚至可以同时存在于不同分组中;
例如在Kubernetes v1.6之前,Deployment
/deployments
就同时存在于apps
和extensions
两个API分组中。
你可以使用kubectl api-resources
命令获取当前Kubernetes集群所有不同版本和分组的资源类型以及对应kind。
kubectl api-resources命令输出样例
$ kubectl api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
podtemplates v1 true PodTemplate
replicationcontrollers rc v1 true ReplicationController
resourcequotas quota v1 true ResourceQuota
secrets v1 true Secret
serviceaccounts sa v1 true ServiceAccount
services svc v1 true Service
mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration
validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration
canonicalservices anthos.cloud.google.com/v1beta1 true CanonicalService
entitlements anthos.gke.io/v1alpha1 false Entitlement
customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition
apiservices apiregistration.k8s.io/v1 false APIService
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
meshpolicies authentication.istio.io/v1alpha1 false MeshPolicy
policies authentication.istio.io/v1alpha1 true Policy
tokenreviews authentication.k8s.io/v1 false TokenReview
localsubjectaccessreviews authorization.k8s.io/v1 true LocalSubjectAccessReview
selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview
selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview
subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview
horizontalpodautoscalers hpa autoscaling/v2 true HorizontalPodAutoscaler
metrics autoscaling.internal.knative.dev/v1alpha1 true Metric
podautoscalers kpa,pa autoscaling.internal.knative.dev/v1alpha1 true PodAutoscaler
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true Job
images img caching.internal.knative.dev/v1alpha1 true Image
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
backendconfigs bc cloud.google.com/v1 true BackendConfig
adapters config.istio.io/v1alpha2 true adapter
attributemanifests config.istio.io/v1alpha2 true attributemanifest
handlers config.istio.io/v1alpha2 true handler
httpapispecbindings config.istio.io/v1alpha2 true HTTPAPISpecBinding
httpapispecs config.istio.io/v1alpha2 true HTTPAPISpec
instances config.istio.io/v1alpha2 true instance
quotaspecbindings config.istio.io/v1alpha2 true QuotaSpecBinding
quotaspecs config.istio.io/v1alpha2 true QuotaSpec
rules config.istio.io/v1alpha2 true rule
templates config.istio.io/v1alpha2 true template
leases coordination.k8s.io/v1 true Lease
bgpconfigurations crd.projectcalico.org/v1 false BGPConfiguration
bgppeers crd.projectcalico.org/v1 false BGPPeer
blockaffinities crd.projectcalico.org/v1 false BlockAffinity
caliconodestatuses crd.projectcalico.org/v1 false CalicoNodeStatus
clusterinformations crd.projectcalico.org/v1 false ClusterInformation
felixconfigurations crd.projectcalico.org/v1 false FelixConfiguration
globalnetworkpolicies crd.projectcalico.org/v1 false GlobalNetworkPolicy
globalnetworksets crd.projectcalico.org/v1 false GlobalNetworkSet
hostendpoints crd.projectcalico.org/v1 false HostEndpoint
ipamblocks crd.projectcalico.org/v1 false IPAMBlock
ipamconfigs crd.projectcalico.org/v1 false IPAMConfig
ipamhandles crd.projectcalico.org/v1 false IPAMHandle
ippools crd.projectcalico.org/v1 false IPPool
ipreservations crd.projectcalico.org/v1 false IPReservation
kubecontrollersconfigurations crd.projectcalico.org/v1 false KubeControllersConfiguration
networkpolicies crd.projectcalico.org/v1 true NetworkPolicy
networksets crd.projectcalico.org/v1 true NetworkSet
endpointslices discovery.k8s.io/v1 true EndpointSlice
domainmappings domains.cloudrun.com/v1alpha1 true DomainMapping
brokers eventing.knative.dev/v1 true Broker
triggers eventing.knative.dev/v1 true Trigger
cloudauditlogssources events.cloud.google.com/v1 true CloudAuditLogsSource
cloudpubsubsources events.cloud.google.com/v1 true CloudPubSubSource
cloudschedulersources events.cloud.google.com/v1 true CloudSchedulerSource
cloudstoragesources events.cloud.google.com/v1 true CloudStorageSource
events ev events.k8s.io/v1 true Event
wasmplugins extensions.istio.io/v1alpha1 true WasmPlugin
s0-prometheus-access_frequency external.metrics.k8s.io/v1beta1 true ExternalMetricValueList
flowschemas flowcontrol.apiserver.k8s.io/v1beta2 false FlowSchema
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1beta2 false PriorityLevelConfiguration
memberships hub.gke.io/v1 false Membership
istiooperators iop,io install.istio.io/v1alpha1 true IstioOperator
capacityrequests capreq internal.autoscaling.gke.io/v1alpha1 true CapacityRequest
capacityrequests capreq internal.autoscaling.k8s.io/v1alpha1 true CapacityRequest
brokercells internal.events.cloud.google.com/v1alpha1 true BrokerCell
pullsubscriptions internal.events.cloud.google.com/v1 true PullSubscription
topics internal.events.cloud.google.com/v1 true Topic
clustertriggerauthentications cta,clustertriggerauth keda.sh/v1alpha1 false ClusterTriggerAuthentication
scaledjobs sj keda.sh/v1alpha1 true ScaledJob
scaledobjects so keda.sh/v1alpha1 true ScaledObject
triggerauthentications ta,triggerauth keda.sh/v1alpha1 true TriggerAuthentication
seldondeployments sdep machinelearning.seldon.io/v1 true SeldonDeployment
controlplanerevisions cpr,cprs mesh.cloud.google.com/v1beta1 true ControlPlaneRevision
dataplanecontrols mesh.cloud.google.com/v1alpha1 false DataPlaneControl
dataplanerevisions mesh.cloud.google.com/v1alpha1 true DataPlaneRevision
nodes metrics.k8s.io/v1beta1 false NodeMetrics
pods metrics.k8s.io/v1beta1 true PodMetrics
frontendconfigs networking.gke.io/v1beta1 true FrontendConfig
managedcertificates mcrt networking.gke.io/v1 true ManagedCertificate
serviceattachments networking.gke.io/v1 true ServiceAttachment
servicenetworkendpointgroups svcneg networking.gke.io/v1beta1 true ServiceNetworkEndpointGroup
certificates kcert networking.internal.knative.dev/v1alpha1 true Certificate
clusterdomainclaims cdc networking.internal.knative.dev/v1alpha1 false ClusterDomainClaim
ingresses kingress,king networking.internal.knative.dev/v1alpha1 true Ingress
serverlessservices sks networking.internal.knative.dev/v1alpha1 true ServerlessService
destinationrules dr networking.istio.io/v1alpha3 true DestinationRule
envoyfilters networking.istio.io/v1alpha3 true EnvoyFilter
gateways gw networking.istio.io/v1alpha3 true Gateway
proxyconfigs networking.istio.io/v1beta1 true ProxyConfig
serviceentries se networking.istio.io/v1alpha3 true ServiceEntry
sidecars networking.istio.io/v1alpha3 true Sidecar
virtualservices vs networking.istio.io/v1alpha3 true VirtualService
workloadentries we networking.istio.io/v1beta1 true WorkloadEntry
workloadgroups wg networking.istio.io/v1beta1 true WorkloadGroup
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
runtimeclasses node.k8s.io/v1 false RuntimeClass
updateinfos updinf nodemanagement.gke.io/v1alpha1 true UpdateInfo
activeoperands ao,aos operand.run.cloud.google.com/v1alpha1 true ActiveOperand
clusteractiveoperands cao,caos operand.run.cloud.google.com/v1alpha1 false ClusterActiveOperand
operands op,ops operand.run.cloud.google.com/v1alpha1 false Operand
cloudruns run,runs operator.run.cloud.google.com/v1alpha1 true CloudRun
poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget
podsecuritypolicies psp policy/v1beta1 false PodSecurityPolicy
clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding
clusterroles rbac.authorization.k8s.io/v1 false ClusterRole
rolebindings rbac.authorization.k8s.io/v1 true RoleBinding
roles rbac.authorization.k8s.io/v1 true Role
clusterrbacconfigs rbac.istio.io/v1alpha1 false ClusterRbacConfig
rbacconfigs rbac.istio.io/v1alpha1 true RbacConfig
servicerolebindings rbac.istio.io/v1alpha1 true ServiceRoleBinding
serviceroles rbac.istio.io/v1alpha1 true ServiceRole
priorityclasses pc scheduling.k8s.io/v1 false PriorityClass
authorizationpolicies security.istio.io/v1beta1 true AuthorizationPolicy
peerauthentications pa security.istio.io/v1beta1 true PeerAuthentication
requestauthentications ra security.istio.io/v1beta1 true RequestAuthentication
configurations config,cfg serving.knative.dev/v1 true Configuration
revisions rev serving.knative.dev/v1 true Revision
routes rt serving.knative.dev/v1 true Route
services kservice,ksvc serving.knative.dev/v1 true Service
volumesnapshotclasses snapshot.storage.k8s.io/v1 false VolumeSnapshotClass
volumesnapshotcontents snapshot.storage.k8s.io/v1 false VolumeSnapshotContent
volumesnapshots snapshot.storage.k8s.io/v1 true VolumeSnapshot
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
csistoragecapacities storage.k8s.io/v1beta1 true CSIStorageCapacity
storageclasses sc storage.k8s.io/v1 false StorageClass
volumeattachments storage.k8s.io/v1 false VolumeAttachment
telemetries telemetry telemetry.istio.io/v1alpha1 true Telemetry
orders tls.cloudrun.com/v1alpha1 true Order
关于KubernetesAPI/资源的版本命名规则以及如何进行迭代的具体细节可以参考文档Changing the API .
再识kind
在之前的初识kind小节,我们从资源类型(resource type)的角度引入了kind,其实kind的概念却要更广。 在Kubernetes系统中,任何需要被序列化/反序列化(以用于在网络中传输或者落盘)的Go类型都被称为kind。
注意,凡是本书中所提及的序列化/反序列化特指在Kubernetes基础库(apimachinery
, client-go
, api-server
)上下文中。
在Kubernetes中,序列化除了基本的序列化操作外,还包括一些特殊的机制,这些特殊机制我们将在后续章节中详细介绍;
我们当然也可以不借助apimachinery
库提供的序列化工具,用Go的net/http
,json.Unmarshal
和json.Marshal
基础库就可以完成向Kubernetes API发起请求以及对Kubernetes kind的编/解码。
例如我们可以先通过如下命令获取与Kubernetes API Server进行TLS通信的证书和密钥:
获取与Kubernetes API Server通信的证书和密钥
# Extract the Cluster Certificate Authorithy (PEM)
$ kubectl config view --minify --raw --output 'jsonpath={..cluster.certificate-authority-data}' | base64 -d
...
# Extract the Client Certificate (PEM)
$kubectl config view --minify --raw --output 'jsonpath={..user.client-certificate-data}' | base64 -d
...
# Extract the Client Private Key (PEM)
$ kubectl config view --minify --raw --output 'jsonpath={..user.client-key-data}' | base64 -d
接下来我们利用获取的证书和密钥直接基于Go的网络和序列化基础库直接与Kubernetes API交互。
基于Go基础库与Kubernetes API直接通信
package main
import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"flag"
"io"
v1 "k8s.io/api/batch/v1"
"net/http"
"os"
)
var (
certFile = flag.String("cert", "client.crt", "A PEM encoded certificate file.")
keyFile = flag.String("key", "client.key", "A PEM encoded private key file.")
caFile = flag.String("ca-cert", "ca.crt", "A PEM encoded CA's certificate file.")
kubeAPI = flag.String("kube-api", "https://127.0.0.1:6443", "Kubernetes API prefix.")
)
func main() {
flag.Parse()
caCert, _ := os.ReadFile(*caFile)
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
cert, _ := tls.LoadX509KeyPair(*certFile, *keyFile)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
Certificates: []tls.Certificate{cert},
},
},
}
r, _ := client.Get(*kubeAPI + "/apis/batch/v1/namespaces/default/jobs/my-job")
bytes, _ := io.ReadAll(r.Body)
_ = json.Unmarshal(bytes, &v1.Job{})
}
我们使用net/http
库直接向Kubernetes API发起请求,并用json.Unmarshal
完成对返回体的解码。
在上述例子中,我们仅使用了Go的基础库就完成了与Kubernetes API的交互,理论上我们可以用任意语言(甚至是curl
工具)达到同样的效果。
例如,根据Kubernetes API Reference Doc ,我们可以通过如下REST请求:
GET /apis/batch/v1/namespaces/{namespace}/jobs
来获取某个namespace
下面所有的job
资源。
下面是一个上述请求返回体(JSON格式)1的例子:
获取一个namespace下所有job资源API的返回体
{
"apiVersion": "batch/v1",
"kind": "JobList",
"metadata": {
"resourceVersion": ""
}
"items": [
{
"apiVersion": "batch/v1",
"kind": "Job",
"metadata": {
"creationTimestamp": "2021-11-02T09:06:03Z",
"name": "debug-b392ad51-b656-3af0-8718-0f96d09a92cf",
"namespace": "default",
"resourceVersion": "223357957",
"uid": "28b061c5-d1ba-4a2e-8aa8-88bf216c2b2f"
},
"spec": {
"backoffLimit": 0,
"completions": 1,
"parallelism": 1,
"selector": {
"matchLabels": {
"controller-uid": "28b061c5-d1ba-4a2e-8aa8-88bf216c2b2f"
}
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"controller-uid": "28b061c5-d1ba-4a2e-8aa8-88bf216c2b2f",
"job-name": "debug-b392ad51-b656-3af0-8718-0f96d09a92cf"
}
},
"spec": {
"containers": [
{
"image": "busybox",
"imagePullPolicy": "IfNotPresent",
"name": "debug-pod"
}
],
"restartPolicy": "Never"
}
}
},
"status": {
"active": 1,
"startTime": "2021-11-02T09:06:03Z"
}
}
]
}
根据文档说明,请求返回体(被编码前)对应的Go类型为JobList
:
type JobList struct {
metav1.TypeMeta
metav1.ListMeta
Items []Job
}
显然这个类型并不直接对应任何资源类型,它表示的是job
资源的集合,其中Items
字段正是Job
类型的切片,以用于存放job
资源的集合。
再比如,当我们想要删除一个job
资源的时候,根据Kubernetes API Reference Doc ,我们可以通过如下REST请求:
DELETE /apis/batch/v1/namespaces/{namespace}/jobs/{name}
一个请求体4样例为:
{
"kind": "DeleteOptions",
"apiVersion": "meta.k8s.io/v1",
"gracePeriodSeconds": 1,
"preconditions": {
"uid": "uidValue",
"resourceVersion": "resourceVersionValue"
},
"orphanDependents": true,
"propagationPolicy": "propagationPolicyValue",
"dryRun": [
"dryRunValue"
]
}
该请求体在被kube-apiserver
接受并解码后对应的Go类型为DeleteOptions
:
type DeleteOptions struct {
TypeMeta
GracePeriodSeconds *int64
Preconditions *Preconditions
OrphanDependents *bool
PropagationPolicy *DeletionPropagation
DryRun []string
}
该请求对应的一个返回体样例为:
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"details": {
"name": "my-job",
"kind": "jobs"
},
"code": 200
}
该请求的返回体(被编码前)对应的Go类型为Status
:
type Status struct {
ListMeta
Status string
Message string
Reason StatusReason
Details *StatusDetails
Code int32
}
此类型中Status
字段(字符串)表示删除操作的结果:Success
或者Failure
, Code
字段(整型)与HTTP的状态码相对应。
除此以外,对于任何请求,kube-apiserver
如果处理异常或者失败(HTTP状态码非2xx
时),都会返回这个Status
类型编码后的JSON数据。
例如,当我们尝试通过Kubernetes API获取一个不存在的资源时:
> GET /api/v1/namespaces/default/pods/grafana
< HTTP/1.1 404 Not Found
< Content-Type: application/json
< Date: Wed, 20 May 2015 18:10:42 GMT
< Content-Length: 232
<
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "pods \"grafana\" not found",
"reason": "NotFound",
"details": {
"name": "grafana",
"kind": "pods"
},
"code": 404
}
显然,上述的例子中DeleteOptions
和Status
都不对应任何Kubernetes资源类型。
这些特殊的kind有些例如DeleteOptions
被放置在meta.k8s.io
这个特殊的分组中(也就是它对应的GVK信息中Group字段为meta.k8s.io
,apiVersion
字段为meta.k8s.io/v1
),它的版本则被定为v1
。
有的kind(例如Status
)在Kubernetes引入API分组之前就已经存在,它们可以被认为属于core
分组(历史遗留组(legacy group)),因此它对应的GV中分组用一个空字符串表示,它的版本则为v1
。
基于Kubernetes API Reference Doc ,我们可以将kind 总结为三类:
- Kubernetes资源类型对应的Go类型:如
Pod
,Job
。(在后续章节中,我们会简称此类型为单体类型) - 集合类型:Kubernetes资源2对应的集合类型,如
PodList
,JobList
。 - 其他特殊或元类型: 如
DeleteOptions
,Status
,WatchEvent
等2。
这三种类型如下图所示:

另外,需要注意的是Kubernetes原生资源的kind(单体种类和集合种类)被定义在k8s.io/api
库中,那些通用或者特殊的kind则被定义在k8s.io/apimachiery
库中。
小结
本小节中我们从GVR引入了GVK,意在指出:kind和资源类型一样必须依赖于API分组及版本(GV)而存在。
同时我们又从序列化/反序列化的角度进一步扩充了Kubernetes kind的概念并且根据Kubernetes API Reference Doc 总结了 kind的三种类型。其中第三个种类比较特殊,类型之间并没有共同的规范或者约定。但需要注意的是,它们仍要依赖于API分组及版本(GV)而存在。这些知识在后续章节中有重要应用。
另外,对于kind前两个种类,它们在源码实现上还需要遵循具体的约定,在后续kind的三类小节我们还会继续介绍它们。
最后需要说明的是,我们特意把kind概念的扩充放在讨论GVK的章节——意在强调即便是对于需要参与编解码的特殊通用类型(kind第三种类),它们也有所属的GV。 可见GVK是Kubernetes中极为重要及基础的概念。