Skip to content

Commit

Permalink
chore: k8s Version Provider (#4596)
Browse files Browse the repository at this point in the history
  • Loading branch information
engedaam authored Sep 8, 2023
1 parent 5f450f7 commit 2dfebc9
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 47 deletions.
4 changes: 2 additions & 2 deletions pkg/controllers/nodeclass/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ var _ = Describe("AWSNodeTemplateController", func() {
})
})
It("should resolve amiSelector AMIs and requirements into status", func() {
version := lo.Must(awsEnv.AMIProvider.KubeServerVersion(ctx))
version := lo.Must(awsEnv.VersionProvider.Get(ctx))

awsEnv.SSMAPI.Parameters = map[string]string{
fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2/recommended/image_id", version): "ami-id-123",
Expand Down Expand Up @@ -576,7 +576,7 @@ var _ = Describe("AWSNodeTemplateController", func() {
}, nodeTemplate.Status.AMIs)
})
It("should resolve amiSelector AMis and requirements into status when all SSM aliases don't resolve", func() {
version := lo.Must(awsEnv.AMIProvider.KubeServerVersion(ctx))
version := lo.Must(awsEnv.VersionProvider.Get(ctx))
// This parameter set doesn't include any of the Nvidia AMIs
awsEnv.SSMAPI.Parameters = map[string]string{
fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", version): "ami-id-123",
Expand Down
5 changes: 3 additions & 2 deletions pkg/operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import (
"github.com/aws/karpenter/pkg/providers/pricing"
"github.com/aws/karpenter/pkg/providers/securitygroup"
"github.com/aws/karpenter/pkg/providers/subnet"
"github.com/aws/karpenter/pkg/providers/version"
"github.com/aws/karpenter/pkg/utils/project"
)

Expand Down Expand Up @@ -126,8 +127,8 @@ func NewOperator(ctx context.Context, operator *operator.Operator) (context.Cont
ec2api,
*sess.Config.Region,
)
amiProvider := amifamily.NewProvider(operator.GetClient(), operator.KubernetesInterface, ssm.New(sess), ec2api,
cache.New(awscache.DefaultTTL, awscache.DefaultCleanupInterval), cache.New(awscache.DefaultTTL, awscache.DefaultCleanupInterval))
versionProvider := version.NewProvider(operator.KubernetesInterface, cache.New(awscache.DefaultTTL, awscache.DefaultCleanupInterval))
amiProvider := amifamily.NewProvider(versionProvider, ssm.New(sess), ec2api, cache.New(awscache.DefaultTTL, awscache.DefaultCleanupInterval))
amiResolver := amifamily.New(amiProvider)
launchTemplateProvider := launchtemplate.NewProvider(
ctx,
Expand Down
53 changes: 13 additions & 40 deletions pkg/providers/amifamily/ami.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ import (
"strings"
"time"

"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
Expand All @@ -39,6 +36,7 @@ import (
corev1beta1 "github.com/aws/karpenter-core/pkg/apis/v1beta1"
"github.com/aws/karpenter/pkg/apis/v1alpha1"
"github.com/aws/karpenter/pkg/apis/v1beta1"
"github.com/aws/karpenter/pkg/providers/version"

"github.com/aws/karpenter-core/pkg/cloudprovider"
"github.com/aws/karpenter-core/pkg/scheduling"
Expand All @@ -47,13 +45,11 @@ import (
)

type Provider struct {
cache *cache.Cache
kubernetesVersionCache *cache.Cache
ssm ssmiface.SSMAPI
kubeClient client.Client
ec2api ec2iface.EC2API
cm *pretty.ChangeMonitor
kubernetesInterface kubernetes.Interface
cache *cache.Cache
ssm ssmiface.SSMAPI
ec2api ec2iface.EC2API
cm *pretty.ChangeMonitor
versionProvider *version.Provider
}

type AMI struct {
Expand Down Expand Up @@ -106,37 +102,14 @@ func (a AMIs) MapToInstanceTypes(instanceTypes []*cloudprovider.InstanceType, is
return amiIDs
}

const (
kubernetesVersionCacheKey = "kubernetesVersion"
)

func NewProvider(kubeClient client.Client, kubernetesInterface kubernetes.Interface, ssm ssmiface.SSMAPI, ec2api ec2iface.EC2API,
cache, kubernetesVersionCache *cache.Cache) *Provider {
func NewProvider(versionProvider *version.Provider, ssm ssmiface.SSMAPI, ec2api ec2iface.EC2API, cache *cache.Cache) *Provider {
return &Provider{
cache: cache,
kubernetesVersionCache: kubernetesVersionCache,
ssm: ssm,
kubeClient: kubeClient,
ec2api: ec2api,
cm: pretty.NewChangeMonitor(),
kubernetesInterface: kubernetesInterface,
}
}

func (p *Provider) KubeServerVersion(ctx context.Context) (string, error) {
if version, ok := p.kubernetesVersionCache.Get(kubernetesVersionCacheKey); ok {
return version.(string), nil
}
serverVersion, err := p.kubernetesInterface.Discovery().ServerVersion()
if err != nil {
return "", err
}
version := fmt.Sprintf("%s.%s", serverVersion.Major, strings.TrimSuffix(serverVersion.Minor, "+"))
p.kubernetesVersionCache.SetDefault(kubernetesVersionCacheKey, version)
if p.cm.HasChanged("kubernetes-version", version) {
logging.FromContext(ctx).With("version", version).Debugf("discovered kubernetes version")
cache: cache,
ssm: ssm,
ec2api: ec2api,
cm: pretty.NewChangeMonitor(),
versionProvider: versionProvider,
}
return version, nil
}

// Get Returning a list of AMIs with its associated requirements
Expand Down Expand Up @@ -166,7 +139,7 @@ func (p *Provider) getDefaultAMIs(ctx context.Context, nodeClass *v1beta1.NodeCl
return images.(AMIs), nil
}
amiFamily := GetAMIFamily(nodeClass.Spec.AMIFamily, options)
kubernetesVersion, err := p.KubeServerVersion(ctx)
kubernetesVersion, err := p.versionProvider.Get(ctx)
if err != nil {
return nil, fmt.Errorf("getting kubernetes version %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/providers/amifamily/ami_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ var _ = AfterSuite(func() {
var _ = Describe("AMIProvider", func() {
var version string
BeforeEach(func() {
version = lo.Must(awsEnv.AMIProvider.KubeServerVersion(ctx))
version = lo.Must(awsEnv.VersionProvider.Get(ctx))
nodeClass = test.NodeClass()
})
It("should succeed to resolve AMIs (AL2)", func() {
Expand Down
2 changes: 1 addition & 1 deletion pkg/providers/launchtemplate/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,7 @@ var _ = Describe("LaunchTemplates", func() {
Expect(awsEnv.EC2API.CalledWithCreateLaunchTemplateInput.Len()).To(Equal(0))
})
It("should choose amis from SSM if no selector specified in AWSNodeTemplate", func() {
version := lo.Must(awsEnv.AMIProvider.KubeServerVersion(ctx))
version := lo.Must(awsEnv.VersionProvider.Get(ctx))
awsEnv.SSMAPI.Parameters = map[string]string{
fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2/recommended/image_id", version): "test-ami-123",
}
Expand Down
64 changes: 64 additions & 0 deletions pkg/providers/version/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

import (
"context"
"fmt"
"strings"

"github.com/patrickmn/go-cache"
"k8s.io/client-go/kubernetes"
"knative.dev/pkg/logging"

"github.com/aws/karpenter-core/pkg/utils/pretty"
)

const (
kubernetesVersionCacheKey = "kubernetesVersion"
)

// Provider get the APIServer version. This will be initialized at start up and allows karpenter to have an understanding of the cluster version
// for decision making. The version is cached to help reduce the amount of calls made to the API Server

type Provider struct {
cache *cache.Cache
cm *pretty.ChangeMonitor
kubernetesInterface kubernetes.Interface
}

func NewProvider(kubernetesInterface kubernetes.Interface, cache *cache.Cache) *Provider {
return &Provider{
cm: pretty.NewChangeMonitor(),
cache: cache,
kubernetesInterface: kubernetesInterface,
}
}

func (p *Provider) Get(ctx context.Context) (string, error) {
if version, ok := p.cache.Get(kubernetesVersionCacheKey); ok {
return version.(string), nil
}
serverVersion, err := p.kubernetesInterface.Discovery().ServerVersion()
if err != nil {
return "", err
}
version := fmt.Sprintf("%s.%s", serverVersion.Major, strings.TrimSuffix(serverVersion.Minor, "+"))
p.cache.SetDefault(kubernetesVersionCacheKey, version)
if p.cm.HasChanged("kubernetes-version", version) {
logging.FromContext(ctx).With("version", version).Debugf("discovered kubernetes version")
}
return version, nil
}
6 changes: 5 additions & 1 deletion pkg/test/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/aws/karpenter/pkg/providers/pricing"
"github.com/aws/karpenter/pkg/providers/securitygroup"
"github.com/aws/karpenter/pkg/providers/subnet"
"github.com/aws/karpenter/pkg/providers/version"

coretest "github.com/aws/karpenter-core/pkg/test"

Expand Down Expand Up @@ -60,6 +61,7 @@ type Environment struct {
PricingProvider *pricing.Provider
AMIProvider *amifamily.Provider
AMIResolver *amifamily.Resolver
VersionProvider *version.Provider
LaunchTemplateProvider *launchtemplate.Provider
}

Expand All @@ -82,7 +84,8 @@ func NewEnvironment(ctx context.Context, env *coretest.Environment) *Environment
pricingProvider := pricing.NewProvider(ctx, fakePricingAPI, ec2api, "")
subnetProvider := subnet.NewProvider(ec2api, subnetCache)
securityGroupProvider := securitygroup.NewProvider(ec2api, securityGroupCache)
amiProvider := amifamily.NewProvider(env.Client, env.KubernetesInterface, ssmapi, ec2api, ec2Cache, kubernetesVersionCache)
versionProvider := version.NewProvider(env.KubernetesInterface, kubernetesVersionCache)
amiProvider := amifamily.NewProvider(versionProvider, ssmapi, ec2api, ec2Cache)
amiResolver := amifamily.New(amiProvider)
instanceTypesProvider := instancetype.NewProvider("", instanceTypeCache, ec2api, subnetProvider, unavailableOfferingsCache, pricingProvider)
launchTemplateProvider :=
Expand Down Expand Up @@ -128,6 +131,7 @@ func NewEnvironment(ctx context.Context, env *coretest.Environment) *Environment
PricingProvider: pricingProvider,
AMIProvider: amiProvider,
AMIResolver: amiResolver,
VersionProvider: versionProvider,
LaunchTemplateProvider: launchTemplateProvider,
}
}
Expand Down

0 comments on commit 2dfebc9

Please sign in to comment.