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
- 定义在doc.go中
-
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
- 定义在types.go中的每个对象里
实现 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