Skip to content

apimachinery

apimachinery

  • https://github.com/kubernetes/apimachinery
  • https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/apimachinery

回顾GKV

  • Group
  • Kind
  • Version
    • Internel version 和External version
    • 版本转换

如何定义 Group

pkg/apis/core/register.go
定义 group
GroupName
定义 groupversion
var SchemeGroupVersion = schema .GroupVersion{Group: GroupName, Version:
runtime .APIVersionInternal}

定义SchemeBuilder

var (
    SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
    AddToScheme   = SchemeBuilder.AddToScheme
)

将对象加入SchemeBuild

func addKnownTypes(scheme *runtime.Scheme) error {
    if err := scheme.AddIgnoredConversionType(&metav1.TypeMeta{}, &metav1.TypeMeta{}); err != nil {
        return err
    }
    scheme.AddKnownTypes(SchemeGroupVersion,
        &Pod{},
        &PodList{},
}}

定义对象类型 types.go

  • List
  • 单一对象数据结构
    • TypeMeta
    • ObjectMeta
    • Spec
    • Status

代码生成 Tags

  • Global Tags

    • 定义在doc.go中
      • // +k8s:deepcopy-gen=package
  • Local Tags

    • 定义在types.go中的每个对象里
      • // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
      • // +genclient
        // +genclient:nonNamespaced
        // +genclient:noVerbs
        // +genclient:onlyVerbs=create,delete
        // +genclient:skipVerbs=get,list,create,update,patch,delete,deleteCollection,watch
        // +genclient:method=Create,verb=create,result=k8s.io/apimachinery/pkg/apis/meta/v1.Status

实现 etcd storage

pkg/registry/core/configmap/storage/storage.go

func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
    store := &genericregistry.Store{
        NewFunc:                  func() runtime.Object { return &api.ConfigMap{} },
        NewListFunc:              func() runtime.Object { return &api.ConfigMapList{} },
        DefaultQualifiedResource: api.Resource("configmaps"),
        CreateStrategy: configmap.Strategy,
        UpdateStrategy: configmap.Strategy,
        DeleteStrategy: configmap.Strategy,
        TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
    }
    options := &generic.StoreOptions{RESTOptions: optsGetter}
    if err := store.CompleteWithOptions(options); err != nil {
        panic(err) // TODO: Propagate error up
    }
    return &REST{store}
}

创建和更新对象时的业务逻辑-Strategy

func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
    _ = obj.(*api.ConfigMap)
}
func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
    cfg := obj.(*api.ConfigMap)
    return validation.ValidateConfigMap(cfg)
}
func (strategy) PrepareForUpdate(ctx context.Context, newObj, oldObj runtime.Object) {
    _ = oldObj.(*api.ConfigMap)
    _ = newObj.(*api.ConfigMap)
}

subresource

什么是 subresource, 内嵌在 kubernetes 对象中, 有独立的操作逻辑的属性集合, 如 podstatus

statusStore.UpdateStrategy = pod.StatusStrategy
var StatusStrategy = podStatusStrategy{Strategy}

func (podStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object)
{
    newPod := obj.(*api.Pod)
    oldPod := old.(*api.Pod)
    newPod.Spec = oldPod.Spec
    newPod.DeletionTimestamp = nil

    // don't allow the pods/status endpoint to touch owner references since old kubelets corrupt them in a way
    // that breaks garbage collection
    newPod.OwnerReferences = oldPod.OwnerReferences
}

注册 APIGroup

定义 Storage

configMapStorage := configmapstore.NewREST(restOptionsGetter)
restStorageMap := map[string]rest.Storage{
    "configMaps":                    configMapStorage,
}

定义对象的 StorageMap

apiGroupInfo.VersionedResourcesStorageMap["v1"] = restStorageMap

将对象注册至 APIServer (挂载 handler)

if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil {
    klog.Fatalf("Error in registering group versions: %v", err)
}

代码生成

  • deepcopy-gen
    • 为对象生成 DeepCopy 方法, 用于创建对象副本
  • client-gen
    • 创建 Clientset, 用于操作对象的 CRUD
  • informer-gen
    • 为对象创建 Informer 框架, 用于监听对象变化
  • lister-gen
    • 为对象构建 Lister 框架, 用于为 Get 和 List 操作, 构建客户端缓存
  • coversion-gen
    • 为对象构建 Conversion 方法, 用于内外版本转换以及不同版本号的转换

https://github.com/kubernetes/code-generator

hack/update-codegen.sh

依赖

BUILD_TARGETS=(
    vendor/k8s.io/code-generator/cmd/client-gen
    vendor/k8s.io/code-generator/cmd/lister-gen
    vendor/k8s.io/code-generator/cmd/informer-gen
)

生成命令

${GOPATH}/bin/deepcopy-gen --input-dirs {versioned-package-pach} 
-O zz_generated.deepcopy \
--bounding-dirs {output-package-path} \
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt

APIServer代码走读

https://cncamp.notion.site/kube-apiserver-10d5695cbbb14387b60c6d622005583d