什么是apimachinery “Package apimachinery contains the generic API machinery code that is common to both server and clients.” apimachinery是对API包及版本管理的一个抽象,主要包含registered和announced两个package:
registered: 定义有DefaultAPIRegistrationManager,管理API包及版本;
announced:包含group_factory和announced两部分,其中group_factory提供了向DefaultAPIRegistrationManager注册的途径;announced部分是还在开发中的接口,用来接管registered包的部分功能。
关于apimachinery的分析,先介绍apimachinery/registered.go中的APIRegistrationManager,再介绍apimachinery/announced/group_factory.go中的groupMetaFactory。
本次将分析APIRegistrationManager。在介绍之前,先来认识下GroupMeta。
GroupMetal结构体定义了Group的基本信息,如Group对应的RESTMapper, Codec, GroupVersions等,定义在/pkg/apimachinery/types.go中:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
type GroupMeta struct {
GroupVersion unversioned.GroupVersion
GroupVersions []unversioned.GroupVersion
Codec runtime.Codec
SelfLinker runtime.SelfLinker
RESTMapper meta.RESTMapper
InterfacesFor func (version unversioned.GroupVersion) (*meta.VersionInterfaces, error)
// InterfacesByVersion stores the per -version interfaces .
InterfacesByVersion map [unversioned .GroupVersion ]*meta .VersionInterfaces
}
APIRegistrationManager APIRegistrationManager主要用来管理GroupMeta,定义在/pgk/apimachinery/registered/registered.go中:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
type APIRegistrationManager struct {
registeredVersions map [unversioned.GroupVersion]struct {}
thirdPartyGroupVersions []unversioned.GroupVersion
enabledVersions map [unversioned.GroupVersion]struct {}
groupMetaMap map [string ]*apimachinery.GroupMeta
envRequestedVersions []unversioned.GroupVersion
}
其中:
registeredGroupVersions存储已经注册的GV,可以使用RegisterVersions()进行注册;
thirdPartyGroupVersions存储第三方的API,可以使用AddThirdPartyAPIGroupVersions()进行注册;
enabledVersions存储处理enabled的GV,可以通过EnableVersions()添加;
groupMetaMap存储Group的GroupMeta信息;
envRequestedVersions存储KUBE_API_VERSIONS环境变量包含的版本,如果未指定,则KUBE_API_VERSIONS为空。
关于APIRegistrationManager和announced包中的APIGroupFactoryRegistry的关系,在announced.go中有注释”(Right now APIRegistrationManager has separate ‘registration’ and ‘enabled’ concepts– APIGroupFactory is going to take over the former function; they will overlap untill the refactoring is finished.)”。所以APIGroupFactoryRegistry还在开发中,估计在以后的版本会完善,并接管APIRegistrationManager对GroupMeta的管理功能。
下面来分析APIRegistrationManager结构体提供的方法。
NewOrDie() NewOrDie()方法可以创建APIRegistrationManager,在registered.go中有DefaultAPIRegistrationManager = NewOrDie(os.Getenv("KUBE_API_VERSIONS"))
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
func NewOrDie (kubeAPIVersions string ) *APIRegistrationManager {
m, err := NewAPIRegistrationManager(kubeAPIVersions)
if err != nil {
glog.Fatalf("Could not construct version manager: %v (KUBE_API_VERSIONS=%q)" , err, kubeAPIVersions)
}
return m
}
func NewAPIRegistrationManager (kubeAPIVersions string ) (*APIRegistrationManager, error) {
m := &APIRegistrationManager{
registeredVersions: map [unversioned.GroupVersion]struct {}{},
thirdPartyGroupVersions: []unversioned.GroupVersion{},
enabledVersions: map [unversioned.GroupVersion]struct {}{},
groupMetaMap: map [string ]*apimachinery.GroupMeta{},
envRequestedVersions: []unversioned.GroupVersion{},
}
if len (kubeAPIVersions) != 0 {
for _, version := range strings.Split(kubeAPIVersions, "," ) {
gv, err := unversioned.ParseGroupVersion(version)
if err != nil {
return nil , fmt.Errorf("invalid api version: %s in KUBE_API_VERSIONS: %s." ,
version, kubeAPIVersions)
}
m.envRequestedVersions = append (m.envRequestedVersions, gv)
}
}
return m, nil
}
RegisterVersions() RegisterVersions()可以向APIRegistrationManager注册GroupVersion,即把GroupVerson作为key加入到registeredVersions map中。1
2
3
4
5
6
func (m *APIRegistrationManager) RegisterVersions (availableVersions []unversioned.GroupVersion) {
for _, v := range availableVersions {
m.registeredVersions[v] = struct {}{}
}
}
RegisterGroup() RegisterGroup()可以向APIRegistrationManager注册groupMeta,即把存入groupMetaMap中。1
2
3
4
5
6
7
8
9
func (m *APIRegistrationManager) RegisterGroup (groupMeta apimachinery.GroupMeta) error {
groupName := groupMeta.GroupVersion.Group
if _, found := m.groupMetaMap[groupName]; found {
return fmt.Errorf("group %v is already registered" , m.groupMetaMap)
}
m.groupMetaMap[groupName] = &groupMeta
return nil
}
EnableVersions() EnableVersions()可以把已经注册的GroupVersion置为enabled。1
2
3
4
5
6
7
8
9
10
11
12
13
14
func (m *APIRegistrationManager) EnableVersions (versions ...unversioned.GroupVersion) error {
var unregisteredVersions []unversioned.GroupVersion
for _, v := range versions {
if _, found := m.registeredVersions[v]; !found {
unregisteredVersions = append (unregisteredVersions, v)
}
m.enabledVersions[v] = struct {}{}
}
if len (unregisteredVersions) != 0 {
return fmt.Errorf("Please register versions before enabling them: %v" , unregisteredVersions)
}
return nil
}
IsAllowedVersion() IsAllowedVersion()用来判断GroupVersion是否在KUBE_API_VERSIONS环境变量的定义中,如果KUBE_API_VERSIONS为空,则允许所有的GroupVersion。1
2
3
4
5
6
7
8
9
10
11
12
func (m *APIRegistrationManager) IsAllowedVersion (v unversioned.GroupVersion) bool {
if len (m.envRequestedVersions) == 0 {
return true
}
for _, envGV := range m.envRequestedVersions {
if v == envGV {
return true
}
}
return false
}
IsEnabledVersion() IsEnabledVersion()用来判断GroupVersion是否为被标记为enabled。1
2
3
4
5
func (m *APIRegistrationManager) IsEnabledVersion (v unversioned.GroupVersion) bool {
_, found := m.enabledVersions[v]
return found
}
EnabledVersions() 返回所有enabled的GroupVersion。1
2
3
4
5
6
7
8
9
10
11
func (m *APIRegistrationManager) EnabledVersions () []unversioned .GroupVersion {
ret := []unversioned.GroupVersion{}
for _, groupMeta := range m.groupMetaMap {
for _, version := range groupMeta.GroupVersions {
if m.IsEnabledVersion(version) {
ret = append (ret, version)
}
}
}
return ret
}
EnabledVersionsForGroup() 返回某一个group下的enabled的GroupVersion。1
2
3
4
5
6
7
8
9
10
11
12
13
14
func (m *APIRegistrationManager) EnabledVersionsForGroup (group string ) []unversioned .GroupVersion {
groupMeta, ok := m.groupMetaMap[group]
if !ok {
return []unversioned.GroupVersion{}
}
ret := []unversioned.GroupVersion{}
for _, version := range groupMeta.GroupVersions {
if m.IsEnabledVersion(version) {
ret = append (ret, version)
}
}
return ret
}
Group() 获取某一group的groupMeta。1
2
3
4
5
6
7
8
func (m *APIRegistrationManager) Group (group string ) (*apimachinery.GroupMeta, error) {
groupMeta, found := m.groupMetaMap[group]
if !found {
return nil , fmt.Errorf("group %v has not been registered" , group)
}
groupMetaCopy := *groupMeta
return &groupMetaCopy, nil
}
IsRegistered() IsRegistered()可以查看某一group是否已经注册。1
2
3
4
func (m *APIRegistrationManager) IsRegistered (group string ) bool {
_, found := m.groupMetaMap[group]
return found
}
IsRegisteredVersion() IsRegisteredVersion()可以查看某一GroupVersion是否已经注册。1
2
3
4
func (m *APIRegistrationManager) IsRegisteredVersion (v unversioned.GroupVersion) bool {
_, found := m.registeredVersions[v]
return found
}
RegisteredGroupVersions() 返回所有GroupVersions。1
2
3
4
5
6
7
func (m *APIRegistrationManager) RegisteredGroupVersions () []unversioned .GroupVersion {
ret := []unversioned.GroupVersion{}
for groupVersion := range m.registeredVersions {
ret = append (ret, groupVersion)
}
return ret
}
IsThirdPartyAPIGroupVersion() 判断是否是第三方的GroupVersion。1
2
3
4
5
6
7
8
func (m *APIRegistrationManager) IsThirdPartyAPIGroupVersion (gv unversioned.GroupVersion) bool {
for ix := range m.thirdPartyGroupVersions {
if m.thirdPartyGroupVersions[ix] == gv {
return true
}
}
return false
}
AddThirdPartyAPIGroupVersions() AddThirdPartyAPIGroupVersions()可以向APIRegistrationManager注册第三方的GroupVersion:先调用RegistrerVersions(),再调用EnableVersions,加入到thirdPartyGroupVersions字段中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func (m *APIRegistrationManager) AddThirdPartyAPIGroupVersions (gvs ...unversioned.GroupVersion) []unversioned .GroupVersion {
filteredGVs := []unversioned.GroupVersion{}
skippedGVs := []unversioned.GroupVersion{}
for ix := range gvs {
if !m.IsRegisteredVersion(gvs[ix]) {
filteredGVs = append (filteredGVs, gvs[ix])
} else {
glog.V(3 ).Infof("Skipping %s, because its already registered" , gvs[ix].String())
skippedGVs = append (skippedGVs, gvs[ix])
}
}
if len (filteredGVs) == 0 {
return skippedGVs
}
m.RegisterVersions(filteredGVs)
m.EnableVersions(filteredGVs...)
m.thirdPartyGroupVersions = append (m.thirdPartyGroupVersions, filteredGVs...)
return skippedGVs
}
InterfacesFor() InterfacesFor()方法先获取GV对应的groupMeta,然后通过groupMeta获取1
2
3
4
5
6
7
8
func (m *APIRegistrationManager) InterfacesFor (version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
groupMeta, err := m.Group(version.Group)
if err != nil {
return nil , err
}
return groupMeta.InterfacesFor(version)
}
GroupOrDie() 获取group对应的GroupMeta。1
2
3
4
5
6
7
8
9
10
11
12
func (m *APIRegistrationManager) GroupOrDie (group string ) *apimachinery .GroupMeta {
groupMeta, found := m.groupMetaMap[group]
if !found {
if group == "" {
panic ("The legacy v1 API is not registered." )
} else {
panic (fmt.Sprintf("Group %s is not registered." , group))
}
}
groupMetaCopy := *groupMeta
return &groupMetaCopy
}
RESTMapper() 收集GroupMeta中的RESTMapper,组成MultiRESTMapper,然后再封装成PriorityRESTMapper返回。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
func (m *APIRegistrationManager) RESTMapper (versionPatterns ...unversioned.GroupVersion) meta .RESTMapper {
unionMapper := meta.MultiRESTMapper{}
unionedGroups := sets.NewString()
for enabledVersion := range m.enabledVersions {
if !unionedGroups.Has(enabledVersion.Group) {
unionedGroups.Insert(enabledVersion.Group)
groupMeta := m.groupMetaMap[enabledVersion.Group]
unionMapper = append (unionMapper, groupMeta.RESTMapper)
}
}
if len (versionPatterns) != 0 {
resourcePriority := []unversioned.GroupVersionResource{}
kindPriority := []unversioned.GroupVersionKind{}
for _, versionPriority := range versionPatterns {
resourcePriority = append (resourcePriority, versionPriority.WithResource(meta.AnyResource))
kindPriority = append (kindPriority, versionPriority.WithKind(meta.AnyKind))
}
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}
if len (m.envRequestedVersions) != 0 {
resourcePriority := []unversioned.GroupVersionResource{}
kindPriority := []unversioned.GroupVersionKind{}
for _, versionPriority := range m.envRequestedVersions {
resourcePriority = append (resourcePriority, versionPriority.WithResource(meta.AnyResource))
kindPriority = append (kindPriority, versionPriority.WithKind(meta.AnyKind))
}
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}
prioritizedGroups := []string {"" , "extensions" , "metrics" }
resourcePriority, kindPriority := m.prioritiesForGroups(prioritizedGroups...)
prioritizedGroupsSet := sets.NewString(prioritizedGroups...)
remainingGroups := sets.String{}
for enabledVersion := range m.enabledVersions {
if !prioritizedGroupsSet.Has(enabledVersion.Group) {
remainingGroups.Insert(enabledVersion.Group)
}
}
remainingResourcePriority, remainingKindPriority := m.prioritiesForGroups(remainingGroups.List()...)
resourcePriority = append (resourcePriority, remainingResourcePriority...)
kindPriority = append (kindPriority, remainingKindPriority...)
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}