mirror of https://github.com/kubernetes/kops.git
Merge pull request #6512 from gambol99/launch_templates
Launch Template Feature Flag
This commit is contained in:
commit
a60dc513e9
|
|
@ -32,67 +32,84 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bool returns a pointer to the boolean value
|
const (
|
||||||
func Bool(b bool) *bool {
|
// Name is the name of the environment variable which encapsulates feature flags
|
||||||
return &b
|
Name = "KOPS_FEATURE_FLAGS"
|
||||||
}
|
)
|
||||||
|
|
||||||
// ExperimentalClusterDNS allows for setting the kubelet dns flag to experimental values.
|
|
||||||
// It allows for experiments with alternative DNS configurations - in particular local proxies.
|
|
||||||
var ExperimentalClusterDNS = New("ExperimentalClusterDNS", Bool(false))
|
|
||||||
|
|
||||||
// KeepLaunchConfigurations can be set to prevent garbage collection of old launch configurations
|
|
||||||
var KeepLaunchConfigurations = New("KeepLaunchConfigurations", Bool(false))
|
|
||||||
|
|
||||||
// DNSPreCreate controls whether we pre-create DNS records.
|
|
||||||
var DNSPreCreate = New("DNSPreCreate", Bool(true))
|
|
||||||
|
|
||||||
// DrainAndValidateRollingUpdate if set will use new rolling update code that will drain and validate.
|
|
||||||
var DrainAndValidateRollingUpdate = New("DrainAndValidateRollingUpdate", Bool(true))
|
|
||||||
|
|
||||||
// VPCSkipEnableDNSSupport if set will make that a VPC does not need DNSSupport enabled.
|
|
||||||
var VPCSkipEnableDNSSupport = New("VPCSkipEnableDNSSupport", Bool(false))
|
|
||||||
|
|
||||||
// SkipTerraformFormat if set will mean that we will not `tf fmt` the generated terraform.
|
|
||||||
var SkipTerraformFormat = New("SkipTerraformFormat", Bool(false))
|
|
||||||
|
|
||||||
var VSphereCloudProvider = New("VSphereCloudProvider", Bool(false))
|
|
||||||
|
|
||||||
var EnableExternalDNS = New("EnableExternalDNS", Bool(false))
|
|
||||||
|
|
||||||
//EnableExternalCloudController toggles the use of cloud-controller-manager introduced in v1.7
|
|
||||||
var EnableExternalCloudController = New("EnableExternalCloudController", Bool(false))
|
|
||||||
|
|
||||||
// EnableSeparateConfigBase allows a config-base that is different from the state store
|
|
||||||
var EnableSeparateConfigBase = New("EnableSeparateConfigBase", Bool(false))
|
|
||||||
|
|
||||||
// SpecOverrideFlag allows setting spec values on create
|
|
||||||
var SpecOverrideFlag = New("SpecOverrideFlag", Bool(false))
|
|
||||||
|
|
||||||
// GoogleCloudBucketAcl means the ACL will be set on a bucket when using GCS
|
|
||||||
// In particular, this is the only (?) way to grant the bucket.list permission
|
|
||||||
// However we should no longer need it, with the keyset.yaml fix
|
|
||||||
var GoogleCloudBucketAcl = New("GoogleCloudBucketAcl", Bool(false))
|
|
||||||
|
|
||||||
// EnableNodeAuthorization enables the node authorization features
|
|
||||||
var EnableNodeAuthorization = New("EnableNodeAuthorization", Bool(false))
|
|
||||||
|
|
||||||
// Spotinst toggles the use of Spotinst integration.
|
|
||||||
var Spotinst = New("Spotinst", Bool(false))
|
|
||||||
|
|
||||||
var flags = make(map[string]*FeatureFlag)
|
|
||||||
var flagsMutex sync.Mutex
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ParseFlags(os.Getenv("KOPS_FEATURE_FLAGS"))
|
ParseFlags(os.Getenv(Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
flags = make(map[string]*FeatureFlag)
|
||||||
|
flagsMutex sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DNSPreCreate controls whether we pre-create DNS records.
|
||||||
|
DNSPreCreate = New("DNSPreCreate", Bool(true))
|
||||||
|
// DrainAndValidateRollingUpdate if set will use new rolling update code that will drain and validate.
|
||||||
|
DrainAndValidateRollingUpdate = New("DrainAndValidateRollingUpdate", Bool(true))
|
||||||
|
// EnableLaunchTemplates indicates we wish to switch to using launch templates rather than launchconfigurations
|
||||||
|
EnableLaunchTemplates = New("EnableLaunchTemplates", Bool(false))
|
||||||
|
//EnableExternalCloudController toggles the use of cloud-controller-manager introduced in v1.7
|
||||||
|
EnableExternalCloudController = New("EnableExternalCloudController", Bool(false))
|
||||||
|
// EnableExternalDNS enables external DNS
|
||||||
|
EnableExternalDNS = New("EnableExternalDNS", Bool(false))
|
||||||
|
// EnableNodeAuthorization enables the node authorization features
|
||||||
|
EnableNodeAuthorization = New("EnableNodeAuthorization", Bool(false))
|
||||||
|
// EnableSeparateConfigBase allows a config-base that is different from the state store
|
||||||
|
EnableSeparateConfigBase = New("EnableSeparateConfigBase", Bool(false))
|
||||||
|
// ExperimentalClusterDNS allows for setting the kubelet dns flag to experimental values.
|
||||||
|
ExperimentalClusterDNS = New("ExperimentalClusterDNS", Bool(false))
|
||||||
|
// GoogleCloudBucketACL means the ACL will be set on a bucket when using GCS
|
||||||
|
GoogleCloudBucketACL = New("GoogleCloudBucketAcl", Bool(false))
|
||||||
|
// KeepLaunchConfigurations can be set to prevent garbage collection of old launch configurations
|
||||||
|
KeepLaunchConfigurations = New("KeepLaunchConfigurations", Bool(false))
|
||||||
|
// SkipTerraformFormat if set means we will not `tf fmt` the generated terraform.
|
||||||
|
// However we should no longer need it, with the keyset.yaml fix
|
||||||
|
// In particular, this is the only (?) way to grant the bucket.list permission
|
||||||
|
// It allows for experiments with alternative DNS configurations - in particular local proxies.
|
||||||
|
SkipTerraformFormat = New("SkipTerraformFormat", Bool(false))
|
||||||
|
// SpecOverrideFlag allows setting spec values on create
|
||||||
|
SpecOverrideFlag = New("SpecOverrideFlag", Bool(false))
|
||||||
|
// Spotinst toggles the use of Spotinst integration.
|
||||||
|
Spotinst = New("Spotinst", Bool(false))
|
||||||
|
// VPCSkipEnableDNSSupport if set will make that a VPC does not need DNSSupport enabled.
|
||||||
|
VPCSkipEnableDNSSupport = New("VPCSkipEnableDNSSupport", Bool(false))
|
||||||
|
// VSphereCloudProvider enables the vsphere cloud provider
|
||||||
|
VSphereCloudProvider = New("VSphereCloudProvider", Bool(false))
|
||||||
|
)
|
||||||
|
|
||||||
|
// FeatureFlag defines a feature flag
|
||||||
type FeatureFlag struct {
|
type FeatureFlag struct {
|
||||||
Key string
|
Key string
|
||||||
enabled *bool
|
enabled *bool
|
||||||
defaultValue *bool
|
defaultValue *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a new feature flag
|
||||||
|
func New(key string, defaultValue *bool) *FeatureFlag {
|
||||||
|
flagsMutex.Lock()
|
||||||
|
defer flagsMutex.Unlock()
|
||||||
|
|
||||||
|
f := flags[key]
|
||||||
|
if f == nil {
|
||||||
|
f = &FeatureFlag{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
flags[key] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.defaultValue == nil {
|
||||||
|
f.defaultValue = defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabled checks if the flag is enabled
|
||||||
func (f *FeatureFlag) Enabled() bool {
|
func (f *FeatureFlag) Enabled() bool {
|
||||||
if f.enabled != nil {
|
if f.enabled != nil {
|
||||||
return *f.enabled
|
return *f.enabled
|
||||||
|
|
@ -103,6 +120,12 @@ func (f *FeatureFlag) Enabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bool returns a pointer to the boolean value
|
||||||
|
func Bool(b bool) *bool {
|
||||||
|
return &b
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseFlags responsible for parse out the feature flag usage
|
||||||
func ParseFlags(f string) {
|
func ParseFlags(f string) {
|
||||||
f = strings.TrimSpace(f)
|
f = strings.TrimSpace(f)
|
||||||
for _, s := range strings.Split(f, ",") {
|
for _, s := range strings.Split(f, ",") {
|
||||||
|
|
@ -124,22 +147,3 @@ func ParseFlags(f string) {
|
||||||
ff.enabled = &enabled
|
ff.enabled = &enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(key string, defaultValue *bool) *FeatureFlag {
|
|
||||||
flagsMutex.Lock()
|
|
||||||
defer flagsMutex.Unlock()
|
|
||||||
|
|
||||||
f := flags[key]
|
|
||||||
if f == nil {
|
|
||||||
f = &FeatureFlag{
|
|
||||||
Key: key,
|
|
||||||
}
|
|
||||||
flags[key] = f
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.defaultValue == nil {
|
|
||||||
f.defaultValue = defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,6 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||||
default:
|
default:
|
||||||
tsk.LaunchConfiguration = task.(*awstasks.LaunchConfiguration)
|
tsk.LaunchConfiguration = task.(*awstasks.LaunchConfiguration)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddTask(tsk)
|
c.AddTask(tsk)
|
||||||
|
|
||||||
// @step: add any external load balancer attachments
|
// @step: add any external load balancer attachments
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package awsmodel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/kops/pkg/apis/kops"
|
"k8s.io/kops/pkg/apis/kops"
|
||||||
|
"k8s.io/kops/pkg/featureflag"
|
||||||
"k8s.io/kops/pkg/model"
|
"k8s.io/kops/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,5 +29,15 @@ type AWSModelContext struct {
|
||||||
|
|
||||||
// UseLaunchTemplate checks if we need to use a launch template rather than configuration
|
// UseLaunchTemplate checks if we need to use a launch template rather than configuration
|
||||||
func UseLaunchTemplate(ig *kops.InstanceGroup) bool {
|
func UseLaunchTemplate(ig *kops.InstanceGroup) bool {
|
||||||
return ig.Spec.MixedInstancesPolicy != nil
|
if featureflag.EnableLaunchTemplates.Enabled() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// @note: this mixed instance polices was added before the feature flag, to keep the
|
||||||
|
// same behviour we also check this. But since the feature hasn't been cut into a tagged
|
||||||
|
// release it possible to use just the feature flag??
|
||||||
|
if ig.Spec.MixedInstancesPolicy != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ func (b *StorageAclBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||||
return fmt.Errorf("error fetching ServiceAccount: %v", err)
|
return fmt.Errorf("error fetching ServiceAccount: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if featureflag.GoogleCloudBucketAcl.Enabled() {
|
if featureflag.GoogleCloudBucketACL.Enabled() {
|
||||||
clusterPath := b.Cluster.Spec.ConfigBase
|
clusterPath := b.Cluster.Spec.ConfigBase
|
||||||
p, err := vfs.Context.BuildVfsPath(clusterPath)
|
p, err := vfs.Context.BuildVfsPath(clusterPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -252,10 +252,20 @@ func (v *AutoscalingGroup) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Autos
|
||||||
VPCZoneIdentifier: fi.String(strings.Join(e.AutoscalingGroupSubnets(), ",")),
|
VPCZoneIdentifier: fi.String(strings.Join(e.AutoscalingGroupSubnets(), ",")),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @check are we using a launchconfiguation
|
||||||
if e.LaunchConfiguration != nil {
|
if e.LaunchConfiguration != nil {
|
||||||
request.LaunchConfigurationName = e.LaunchConfiguration.ID
|
request.LaunchConfigurationName = e.LaunchConfiguration.ID
|
||||||
}
|
}
|
||||||
|
// @check are we using launch template
|
||||||
|
if e.LaunchTemplate != nil {
|
||||||
|
request.LaunchTemplate = &autoscaling.LaunchTemplateSpecification{
|
||||||
|
LaunchTemplateName: e.LaunchTemplate.ID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @check if we are using mixed instance policies
|
||||||
if e.UseMixedInstancesPolicy() {
|
if e.UseMixedInstancesPolicy() {
|
||||||
|
// we can zero this out for now and use the mixed instance policy for definition
|
||||||
|
request.LaunchTemplate = nil
|
||||||
request.MixedInstancesPolicy = &autoscaling.MixedInstancesPolicy{
|
request.MixedInstancesPolicy = &autoscaling.MixedInstancesPolicy{
|
||||||
InstancesDistribution: &autoscaling.InstancesDistribution{
|
InstancesDistribution: &autoscaling.InstancesDistribution{
|
||||||
OnDemandPercentageAboveBaseCapacity: e.MixedOnDemandAboveBase,
|
OnDemandPercentageAboveBaseCapacity: e.MixedOnDemandAboveBase,
|
||||||
|
|
@ -464,12 +474,21 @@ func (e *AutoscalingGroup) UseMixedInstancesPolicy() bool {
|
||||||
if e.LaunchTemplate == nil {
|
if e.LaunchTemplate == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
items := []interface{}{e.MixedOnDemandAboveBase, e.MixedOnDemandBase, e.MixedSpotAllocationStrategy, e.MixedSpotInstancePools}
|
// @check if any of the mixed instance policies settings are toggled
|
||||||
|
if e.MixedOnDemandAboveBase != nil {
|
||||||
for _, x := range items {
|
return true
|
||||||
if x != nil {
|
}
|
||||||
return true
|
if e.MixedOnDemandBase != nil {
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
|
if e.MixedSpotAllocationStrategy != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if e.MixedSpotInstancePools != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if len(e.MixedInstanceOverrides) > 0 {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue