Kubernetes API
Kubernetes API 是 Kubernetes 集群中的核心组件,它提供了一种标准化的方式来与集群进行交互和管理。Kubernetes API 允许用户通过 RESTful 接口与集群中的各种资源进行交互,包括 Pods、Services、Deployments、ConfigMaps 等。
以下是 Kubernetes API 的一些关键特性和功能:
- 统一接口:Kubernetes API 提供了一个统一的接口来管理和操作集群中的资源。无论是部署应用程序、扩展集群、管理网络、配置存储,还是进行监控和日志记录,都可以通过 Kubernetes API 来完成。
- RESTful 设计:Kubernetes API 遵循 RESTful 设计原则,使用 HTTP 协议进行通信,并使用标准的 HTTP 方法(GET、POST、PUT、DELETE)来执行操作。资源对象以 JSON 格式进行表示和传输。
- 资源管理:通过 Kubernetes API,用户可以创建、更新和删除各种资源对象。可以使用 API 来定义和管理应用程序的副本数量、容器的配置、服务的访问方式等。
- 声明式配置:Kubernetes API 支持声明式配置,用户可以通过创建资源对象的 YAML 或 JSON 文件来描述期望的状态。Kubernetes 控制器将根据配置文件中的定义自动调整集群状态,以使集群状态与期望状态保持一致。
- 自定义资源定义(Custom Resource Definitions,CRDs):Kubernetes API提供了 CRD 机制,允许用户定义自定义资源类型。CRD 允许用户扩展 Kubernetes API,引入新的资源类型和控制器,以适应特定的业务需求。
以Deployment资源类型为例,分析K8S的资源定义
// https://github1s.com/kubernetes/kubernetes/blob/master/pkg/apis/apps/types.go#L355
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Deployment provides declarative updates for Pods and ReplicaSets.
type Deployment struct {
metav1.TypeMeta
// +optional
metav1.ObjectMeta
// Specification of the desired behavior of the Deployment.
// +optional
Spec DeploymentSpec
// Most recently observed status of the Deployment.
// +optional
Status DeploymentStatus
}
TypeMeta
TypeMeta 是 Kubernetes API 对象中的一个字段,用于描述该对象的类型信息。它包含两个字段:apiVersion 和 kind。
apiVersion 字段指定了 Kubernetes API 的版本,它用于标识该对象所属的 API 版本。例如,apiVersion: v1 表示该对象属于 Kubernetes 的 v1 版本 API。
kind 字段表示该对象的类型或种类。它用于指示该对象所代表的资源类型。例如,kind: Pod 表示该对象是一个 Pod 类型的资源。
TypeMeta 的作用是提供关于对象类型的元数据信息,使得 Kubernetes API Server 能够正确解析和处理请求。通过查看 TypeMeta 字段,Kubernetes 可以确定对象的 API 版本和类型,从而选择正确的处理逻辑和验证规则。
TypeMeta定义Kubernetes API 对象的规范类型元数据,它是确保对象在与 API Server 进行交互时被正确识别和处理的重要组成部分。
定义中GroupVersionKind
TypeMeta定义中GroupVersionKind分别表示:
- Group: 指定资源所属组
- Kind: 指定资源的类型或类别
- Version: 指定资源对应API的版本
// https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/group_version.go#L86
// GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion
// to avoid automatic coercion. It doesn't use a GroupVersion to avoid custom marshalling
//
// +protobuf.options.(gogoproto.goproto\_stringer)=false
type GroupVersionKind struct {
Group string `json:"group" protobuf:"bytes,1,opt,name=group"`
Version string `json:"version" protobuf:"bytes,2,opt,name=version"`
Kind string `json:"kind" protobuf:"bytes,3,opt,name=kind"`
}
以下是Deployment的GVK定义:
Group: "apps"
Version: "v1"
Kind: "Deployment"
GroupVersionResource
在 Kubernetes 中,"Resource" 字段用于指定资源的名称,以其复数形式和小写形式表示。它表示所引用的实际资源,在API中需要使用这个字段作为请求资源的类型
Group: "apps"
Version: "v1"
Resource: "deployments"
ObjectMeta
ObjectMeta包括资源实例的名称(name), 所属命名空间(namespace), 标签(labels), annotation(内部标签)
// https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go#L111-L121
type ObjectMeta struct {
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
GenerateName string `json:"generateName,omitempty" protobuf:"bytes,2,opt,name=generateName"`
Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`
SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,4,opt,name=selfLink"`
UID types.UID `json:"uid,omitempty" protobuf:"bytes,5,opt,name=uid,casttype=k8s.io/kubernetes/pkg/types.UID"`
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,6,opt,name=resourceVersion"`
CreationTimestamp Time `json:"creationTimestamp,omitempty" protobuf:"bytes,8,opt,name=creationTimestamp"`
Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"`
...
Name: 代表资源名称Namespace: 代表资源所属命名空间Labels: 代表给资源打的标签
DeploymentSpec
DeploymentSpec用于提供给用户创建配置,用户可以按需求设置replicas、selector、Pod的Template
Spec is the object configuration, include replica, podTemplate
// DeploymentSpec is the specification of the desired behavior of the Deployment.
type DeploymentSpec struct {
// Number of desired pods. This is a pointer to distinguish between explicit
// zero and not specified. Defaults to 1.
// +optional
Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`
// Label selector for pods. Existing ReplicaSets whose pods are
// selected by this will be the ones affected by this deployment.
// It must match the pod template's labels.
Selector *metav1.LabelSelector `json:"selector" protobuf:"bytes,2,opt,name=selector"`
// Template describes the pods that will be created.
// The only allowed template.spec.restartPolicy value is "Always".
Template v1.PodTemplateSpec `json:"template" protobuf:"bytes,3,opt,name=template"`
// The deployment strategy to use to replace existing pods with new ones.
// +optional
// +patchStrategy=retainKeys
Strategy DeploymentStrategy `json:"strategy,omitempty" patchStrategy:"retainKeys" protobuf:"bytes,4,opt,name=strategy"`
// Minimum number of seconds for
DeploymentStatus
DeploymentStatus用于表示资源在集群中的当前实际状态
type DeploymentStatus struct {
// The generation observed by the deployment controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,1,opt,name=observedGeneration"`
// Total number of non-terminated pods targeted by this deployment (their labels match the selector).
// +optional
Replicas int32 `json:"replicas,omitempty" protobuf:"varint,2,opt,name=replicas"`
// Total number of non-terminated pods targeted by this deployment that have the desired template spec.
// +optional
UpdatedReplicas int32 `json:"updatedReplicas,omitempty" protobuf:"varint,3,opt,name=updatedReplicas"`
// readyReplicas is the number of pods targeted by this Deployment with a Ready Condition.
// +optional
ReadyReplicas int32 `json:"readyReplicas,omitempty" protobuf:"varint,7,opt,name=readyReplicas"`
// Total number of available pods (ready for at least minReadySeconds) targeted by this deployment.
// +optional
AvailableReplicas int32 `json:"availableReplicas,omitempty" protobuf:"varint,4,opt,name=availableReplicas"`
// Total number of unavailable pods targeted by this deployment. This is the total number of
// pods that are still required for the deployment to have 100% available capacity. They may
// either be pods that are running but not yet available or pods that still have not been created.
// +optional
UnavailableReplicas int32 `json:"unavailableReplicas,omitempty" protobuf:"varint,5,opt,name=unavailableReplicas"`
根据资源定义规范,声明一个Deployment类型的资源
// https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/kubectl/pkg/cmd/create/create_deployment.go#L220
func (o *CreateDeploymentOptions) createDeployment() *appsv1.Deployment {
labels := map[string]string{"app": o.Name}
selector := metav1.LabelSelector{MatchLabels: labels}
namespace := ""
if o.EnforceNamespace {
namespace = o.Namespace
}
deploy := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: appsv1.SchemeGroupVersion.String(),
Kind: "Deployment"
},
ObjectMeta: metav1.ObjectMeta{
Name: o.Name,
Labels: labels,
Namespace: namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: &o.Replicas,
Selector: &selector,
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: labels,
},
Spec: o.buildPodSpec(),
},
},
}
APIVersion: 设置api versionKind: 设置资源类型Name: 设置资源的名称Labels: 为资源添加labelNamespace: 设置资源所属命名空间Replicas: 设置pod的副本数量Selector: 设置资源的标签选择器,用于过滤查询资源使用Template: 配置Pod的template模块
查询集群支持的资源类型
➜ golang k 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
customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition
apiservices apiregistration.k8s.io/v1 false APIService
aplogconfs appprotect.f5.com/v1beta1 true APLogConf
appolicies appprotect.f5.com/v1beta1 true APPolicy
apusersigs appprotect.f5.com/v1beta1 true APUserSig
apdoslogconfs appprotectdos.f5.com/v1beta1 true APDosLogConf
apdospolicies appprotectdos.f5.com/v1beta1 true APDosPolicy
dosprotectedresources pr appprotectdos.f5.com/v1beta1 true DosProtectedResource
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
selfsubjectreviews authentication.k8s.io/v1 false SelfSubjectReview
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
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true Job
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
ingressclassparameterses configuration.konghq.com/v1alpha1 true IngressClassParameters
kongclusterplugins kcp configuration.konghq.com/v1 false KongClusterPlugin
kongconsumergroups kcg configuration.konghq.com/v1beta1 true KongConsumerGroup
kongconsumers kc configuration.konghq.com/v1 true KongConsumer
kongingresses ki configuration.konghq.com/v1 true KongIngress
kongplugins kp configuration.konghq.com/v1 true KongPlugin
tcpingresses configuration.konghq.com/v1beta1 true TCPIngress
udpingresses configuration.konghq.com/v1beta1 true UDPIngress
leases coordination.k8s.io/v1 true Lease
endpointslices discovery.k8s.io/v1 true EndpointSlice
events ev events.k8s.io/v1 true Event
dnsendpoints externaldns.nginx.org/v1 true DNSEndpoint
flowschemas flowcontrol.apiserver.k8s.io/v1 false FlowSchema
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1 false PriorityLevelConfiguration
globalconfigurations gc k8s.nginx.org/v1 true GlobalConfiguration
policies pol k8s.nginx.org/v1 true Policy
transportservers ts k8s.nginx.org/v1 true TransportServer
virtualserverroutes vsr k8s.nginx.org/v1 true VirtualServerRoute
virtualservers vs k8s.nginx.org/v1 true VirtualServer
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
poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget
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
priorityclasses pc scheduling.k8s.io/v1 false PriorityClass
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
csistoragecapacities storage.k8s.io/v1 true CSIStorageCapacity
storageclasses sc storage.k8s.io/v1 false StorageClass
volumeattachments storage.k8s.io/v1 false VolumeAttachment
name表示资源类型的名称short name表示资源类型的简写api version表示资源api所属组和版本namespaced表示资源是否为namespaced范围的资源kind表示资源类型
我们可以通过kubectl的-v参数获取API url的信息
➜ golang kg deploy -v 8
I0324 16:47:40.921694 1522072 loader.go:395] Config loaded from file: /home/going/.kube/config
I0324 16:47:40.930139 1522072 round_trippers.go:463] GET <https://127.0.0.1:46219/apis/apps/v1/namespaces/default/deployments?limit=500>
I0324 16:47:40.930183 1522072 round_trippers.go:469] Request Headers:
I0324 16:47:40.930195 1522072 round_trippers.go:473] Accept: application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json
I0324 16:47:40.930205 1522072 round_trippers.go:473] User-Agent: kubectl/v1.28.5 (linux/amd64) kubernetes/e78a4be
I0324 16:47:40.943334 1522072 round_trippers.go:574] Response Status: 200 OK in 13 milliseconds
I0324 16:47:40.943381 1522072 round_trippers.go:577] Response Headers:
I0324 16:47:40.943393 1522072 round_trippers.go:580] Audit-Id: 8d82fd9c-12cf-4d86-b6a2-23a6c069198a
I0324 16:47:40.943401 1522072 round_trippers.go:580] Cache-Control: no-cache, private
I0324 16:47:40.943408 1522072 round_trippers.go:580] Content-Type: application/json
I0324 16:47:40.943416 1522072 round_trippers.go:580] X-Kubernetes-Pf-Flowschema-Uid: af0a188f-fc8b-4323-ae75-1dc2a930b79c
I0324 16:47:40.943423 1522072 round_trippers.go:580] X-Kubernetes-Pf-Prioritylevel-Uid: 249c1c1a-ab96-42e4-bd75-25fa3d93832f
I0324 16:47:40.943432 1522072 round_trippers.go:580] Date: Sun, 24 Mar 2024 08:47:40 GMT
I0324 16:47:40.943662 1522072 request.go:1212] Response Body: {"kind":"Table","apiVersion":"meta.k8s.io/v1","metadata":{"resourceVersion":"1023944"},"columnDefinitions":[{"name":"Name","type":"string","format":"name","description":"Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: <https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names","priority":0},{"name":"Ready","type":"string","format":"","description":"Number> of the pod with ready state","priority":0},{"name":"Up-to-date","type":"string","format":"","description":"Total number of non-terminated pods targeted by this deployment that have the desired template spec.","priority":0},{"name":"Available","type":"string","format":"","description":"Total number of available pods (ready for at least minReadySeconds) targeted by this deployment.","priority":0},{ [truncated 5979 chars]
NAME READY UP-TO-DATE AVAILABLE AGE
lister 1/1 1 1 23h
nginx-deployment 3/3 3 3 21m
Kubernetes API和GroupVersionKind对应关系
https://127.0.0.1:46219/apis/apps/v1/namespaces/default/deployments?limit=500
// The convention
https://{api-server-ip}/api(s)/{group}/{version}/namespaces/{namespace-value}/{resource-plural}?limit=500
我们可以通过RESTMapping将资源的GroupVersion信息转换为对应的resource信息
// <https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/restmapper/discovery.go#L285>
// RESTMapping identifies a preferred resource mapping for the
// provided group kind.
func (d *DeferredDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (m *meta.RESTMapping, err error) {
del, err := d.getDelegate()
if err != nil {
return nil, err
}
m, err = del.RESTMapping(gk, versions...)
if err != nil && !d.cl.Fresh() {
d.Reset()
m, err = d.RESTMapping(gk, versions...)
}
return
}
也可以通过resource信息转化为对应的GroupVersionKind
// <https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/restmapper/discovery.go#L225>
// KindFor takes a partial resource and returns back the single match.
// It returns an error if there are multiple matches.
func (d *DeferredDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (gvk schema.GroupVersionKind, err error) {
del, err := d.getDelegate()
if err != nil {
return schema.GroupVersionKind{}, err
}
gvk, err = del.KindFor(resource)
if err != nil && !d.cl.Fresh() {
d.Reset()
gvk, err = d.KindFor(resource)
}
return
}
Scheme to convert Go type to HTTP url
// <https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go#L46>
// Scheme defines methods for serializing and deserializing API objects, a type
// registry for converting group, version, and kind information to and from Go
// schemas, and mappings between Go schemas of different versions. A scheme is the
// foundation for a versioned API and versioned configuration over time.
//
// In a Scheme, a Type is a particular Go struct, a Version is a point-in-time
// identifier for a particular representation of that Type (typically backwards
// compatible), a Kind is the unique name for that Type within the Version, and a
// Group identifies a set of Versions, Kinds, and Types that evolve over time. An
// Unversioned Type is one that is not yet formally bound to a type and is promised
// to be backwards compatible (effectively a "v1" of a Type that does not expect
// to break in the future).
//
// Schemes are not expected to change at runtime and are only threadsafe after
// registration is complete.
type Scheme struct {
// gvkToType allows one to figure out the go type of an object with
// the given version and name.
gvkToType map[schema.GroupVersionKind]reflect.Type
// typeToGVK allows one to find metadata for a given go object.
// The reflect.Type we index by should *not* be a pointer.
typeToGVK map[reflect.Type][]schema.GroupVersionKind
// unversionedTypes are transformed without conversion in ConvertToVersion.
unversionedTypes map[reflect.Type]schema.GroupVersionKind
// unversionedKinds are the names of kinds that can be created in the context of any group
// or version
// TODO: resolve the status of unversioned types.
unversionedKinds map[string]reflect.Type
Kubernete对象的接口定义
// <https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go#L323>
// Object interface must be supported by all API types registered with Scheme. Since objects in a scheme are
// expected to be serialized to the wire, the interface an Object must provide to the Scheme allows
// serializers to set the kind, version, and group the object is represented as. An Object may choose
// to return a no-op ObjectKindAccessor in cases where it is not expected to be serialized.
type Object interface {
GetObjectKind() schema.ObjectKind
DeepCopyObject() Object
}
添加Kubernetes对象到scheme
// <https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go#L140>
// AddKnownTypes registers all types passed in 'types' as being members of version 'version'.
// All objects passed to types should be pointers to structs. The name that go reports for
// the struct becomes the "kind" field when encoding. Version may not be empty - use the
// APIVersionInternal constant if you have a type that does not have a formal version.
func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) {
s.addObservedVersion(gv)
for _, obj := range types {
t := reflect.TypeOf(obj)
if t.Kind() != reflect.Pointer {
panic("All types must be pointers to structs.")
}
t = t.Elem()
s.AddKnownTypeWithName(gv.WithKind(t.Name()), obj)
}
}
通过传入Kubernetes对象获得其GroupVersionKind信息
// <https://github1s.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go#L243>
// ObjectKinds returns all possible group,version,kind of the go object, true if the
// object is considered unversioned, or an error if it's not a pointer or is unregistered.
func (s *Scheme) ObjectKinds(obj Object) ([]schema.GroupVersionKind, bool, error) {
// Unstructured objects are always considered to have their declared GVK
if _, ok := obj.(Unstructured); ok {
// we require that the GVK be populated in order to recognize the object
gvk := obj.GetObjectKind().GroupVersionKind()
if len(gvk.Kind) == 0 {
return nil, false, NewMissingKindErr("unstructured object has no kind")
}
if len(gvk.Version) == 0 {
return nil, false, NewMissingVersionErr("unstructured object has no version")
}
return []schema.GroupVersionKind{gvk}, false, nil
}
v, err := conversion.EnforcePtr(obj)
if err != nil {
return nil, false, err
}
t := v.Type()
gvks, ok := s.typeToGVK[t]
if !ok {
return nil, false, NewNotRegisteredErrForType(s.schemeName, t)
}
_, unversionedType := s.unversionedTypes[t]
return gvks, unversionedType, nil
}
In conclusion, the whole view of conversion from Go type to HTTP url goes like: