From 264c64ec0dd6e98f17591462fe9e0ec4c77e4444 Mon Sep 17 00:00:00 2001 From: Piotr Szczesniak Date: Mon, 15 Feb 2016 15:00:40 +0100 Subject: [PATCH] Enabled autoscaling API group in apiserver --- cmd/kube-apiserver/app/server.go | 41 ++++++++++++++++++ pkg/master/master.go | 73 ++++++++++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 3 deletions(-) diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 877ede50b07..69604b3b8f6 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -37,6 +37,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/apimachinery/registered" + "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver/authenticator" @@ -299,6 +300,37 @@ func Run(s *options.APIServer) error { glog.Fatalf("Invalid extensions storage version or misconfigured etcd: %v", err) } storageDestinations.AddAPIGroup(extensions.GroupName, expEtcdStorage) + + // Since HPA has been moved to the autoscaling group, we need to make + // sure autoscaling has a storage destination. If the autoscaling group + // itself is on, it will overwrite this decision below. + storageDestinations.AddAPIGroup(autoscaling.GroupName, expEtcdStorage) + } + + // autoscaling/v1/horizontalpodautoscalers is a move from extensions/v1beta1/horizontalpodautoscalers. + // The storage version needs to be either extensions/v1beta1 or autoscaling/v1. + // Users must roll forward while using 1.2, because we will require the latter for 1.3. + if !apiGroupVersionOverrides["autoscaling/v1"].Disable { + glog.Infof("Configuring autoscaling/v1 storage destination") + autoscalingGroup, err := registered.Group(autoscaling.GroupName) + if err != nil { + glog.Fatalf("Autoscaling API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err) + } + // Figure out what storage group/version we should use. + storageGroupVersion, found := storageVersions[autoscalingGroup.GroupVersion.Group] + if !found { + glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", autoscalingGroup.GroupVersion.Group, storageVersions) + } + + if storageGroupVersion != "autoscaling/v1" && storageGroupVersion != "extensions/v1beta1" { + glog.Fatalf("The storage version for autoscaling must be either 'autoscaling/v1' or 'extensions/v1beta1'") + } + glog.Infof("Using %v for autoscaling group storage version", storageGroupVersion) + autoscalingEtcdStorage, err := newEtcd(s.EtcdServerList, api.Codecs, storageGroupVersion, "extensions/__internal", s.EtcdPathPrefix, s.EtcdQuorumRead) + if err != nil { + glog.Fatalf("Invalid extensions storage version or misconfigured etcd: %v", err) + } + storageDestinations.AddAPIGroup(autoscaling.GroupName, autoscalingEtcdStorage) } updateEtcdOverrides(s.EtcdServersOverrides, storageVersions, s.EtcdPathPrefix, s.EtcdQuorumRead, &storageDestinations, newEtcd) @@ -480,6 +512,15 @@ func parseRuntimeConfig(s *options.APIServer) (map[string]genericapiserver.APIGr } } + disableAutoscaling := disableAllAPIs + autoscalingGroupVersion := "autoscaling/v1" + disableAutoscaling = !getRuntimeConfigValue(s, autoscalingGroupVersion, !disableAutoscaling) + if disableAutoscaling { + apiGroupVersionOverrides[autoscalingGroupVersion] = genericapiserver.APIGroupVersionOverride{ + Disable: true, + } + } + for key := range s.RuntimeConfig { if strings.HasPrefix(key, v1GroupVersion+"/") { return nil, fmt.Errorf("api/v1 resources cannot be enabled/disabled individually") diff --git a/pkg/master/master.go b/pkg/master/master.go index 40d6e50b32d..ddd968fc88f 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -31,6 +31,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/apimachinery/registered" + "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apiserver" apiservermetrics "k8s.io/kubernetes/pkg/apiserver/metrics" @@ -209,6 +210,7 @@ func (m *Master) InstallAPIs(c *Config) { // allGroups records all supported groups at /apis allGroups := []unversioned.APIGroup{} + // Install extensions unless disabled. if !m.ApiGroupVersionOverrides["extensions/v1beta1"].Disable { m.thirdPartyStorage = c.StorageDestinations.APIGroups[extensions.GroupName].Default @@ -250,6 +252,39 @@ func (m *Master) InstallAPIs(c *Config) { } allGroups = append(allGroups, group) } + + // Install autoscaling unless disabled. + if !m.ApiGroupVersionOverrides["autoscaling/v1"].Disable { + autoscalingResources := m.getAutoscalingResources(c) + autoscalingGroupMeta := registered.GroupOrDie(autoscaling.GroupName) + + // Hard code preferred group version to autoscaling/v1 + autoscalingGroupMeta.GroupVersion = unversioned.GroupVersion{Group: "autoscaling", Version: "v1"} + + apiGroupInfo := genericapiserver.APIGroupInfo{ + GroupMeta: *autoscalingGroupMeta, + VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ + "v1": autoscalingResources, + }, + OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion, + Scheme: api.Scheme, + ParameterCodec: api.ParameterCodec, + NegotiatedSerializer: api.Codecs, + } + apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) + + autoscalingGVForDiscovery := unversioned.GroupVersionForDiscovery{ + GroupVersion: autoscalingGroupMeta.GroupVersion.String(), + Version: autoscalingGroupMeta.GroupVersion.Version, + } + group := unversioned.APIGroup{ + Name: autoscalingGroupMeta.GroupVersion.Group, + Versions: []unversioned.GroupVersionForDiscovery{autoscalingGVForDiscovery}, + PreferredVersion: autoscalingGVForDiscovery, + } + allGroups = append(allGroups, group) + } + if err := m.InstallAPIGroups(apiGroupsInfo); err != nil { glog.Fatalf("Error in registering group versions: %v", err) } @@ -586,9 +621,7 @@ func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage { storage := map[string]rest.Storage{} if isEnabled("horizontalpodautoscalers") { - autoscalerStorage, autoscalerStatusStorage := horizontalpodautoscaleretcd.NewREST(dbClient("horizontalpodautoscalers"), storageDecorator) - storage["horizontalpodautoscalers"] = autoscalerStorage - storage["horizontalpodautoscalers/status"] = autoscalerStatusStorage + m.constructHPAResources(c, storage) controllerStorage := expcontrolleretcd.NewStorage(c.StorageDestinations.Get("", "replicationControllers"), storageDecorator) storage["replicationcontrollers"] = controllerStorage.ReplicationController storage["replicationcontrollers/scale"] = controllerStorage.Scale @@ -646,6 +679,40 @@ func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage { return storage } +// constructHPAResources makes HPA resources and adds them to the storage map. +// They're installed in both autoscaling and extensions. It's assumed that +// you've already done the check that they should be on. +func (m *Master) constructHPAResources(c *Config, restStorage map[string]rest.Storage) { + // Note that hpa's storage settings are changed by changing the autoscaling + // group. Clearly we want all hpas to be stored in the same place no + // matter where they're accessed from. + storageDecorator := m.StorageDecorator() + dbClient := func(resource string) storage.Interface { + return c.StorageDestinations.Search([]string{autoscaling.GroupName, extensions.GroupName}, resource) + } + autoscalerStorage, autoscalerStatusStorage := horizontalpodautoscaleretcd.NewREST(dbClient("horizontalpodautoscalers"), storageDecorator) + restStorage["horizontalpodautoscalers"] = autoscalerStorage + restStorage["horizontalpodautoscalers/status"] = autoscalerStatusStorage +} + +// getAutoscalingResources returns the resources for autoscaling api +func (m *Master) getAutoscalingResources(c *Config) map[string]rest.Storage { + resourceOverrides := m.ApiGroupVersionOverrides["autoscaling/v1"].ResourceOverrides + isEnabled := func(resource string) bool { + // Check if the resource has been overriden. + if enabled, ok := resourceOverrides[resource]; ok { + return enabled + } + return !m.ApiGroupVersionOverrides["autoscaling/v1"].Disable + } + + storage := map[string]rest.Storage{} + if isEnabled("horizontalpodautoscalers") { + m.constructHPAResources(c, storage) + } + return storage +} + // findExternalAddress returns ExternalIP of provided node with fallback to LegacyHostIP. func findExternalAddress(node *api.Node) (string, error) { var fallback string