- updating the aws model to make use of the aws template and mixed instance policies

This commit is contained in:
Rohith 2018-12-28 15:39:37 +00:00
parent 39db0816df
commit 761d760c11
8 changed files with 361 additions and 346 deletions

View File

@ -6,7 +6,6 @@ go_library(
"api_loadbalancer.go",
"autoscalinggroup.go",
"context.go",
"convenience.go",
],
importpath = "k8s.io/kops/pkg/model/awsmodel",
visibility = ["//visibility:public"],

View File

@ -21,27 +21,31 @@ import (
"sort"
"time"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/dns"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
"k8s.io/kops/upup/pkg/fi/fitasks"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/util/sets"
)
// LoadBalancerDefaultIdleTimeout is the default idle time for the ELB
const LoadBalancerDefaultIdleTimeout = 5 * time.Minute
// APILoadBalancerBuilder builds a LoadBalancer for accessing the API
type APILoadBalancerBuilder struct {
*AWSModelContext
Lifecycle *fi.Lifecycle
SecurityLifecycle *fi.Lifecycle
}
var _ fi.ModelBuilder = &APILoadBalancerBuilder{}
// Build is responsible for building the KubeAPI tasks for the aws model
func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// Configuration where an ELB fronts the API
if !b.UseLoadBalancerForAPI() {
@ -116,10 +120,10 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
}
elb = &awstasks.LoadBalancer{
Name: s("api." + b.ClusterName()),
Name: fi.String("api." + b.ClusterName()),
Lifecycle: b.Lifecycle,
LoadBalancerName: s(loadBalancerName),
LoadBalancerName: fi.String(loadBalancerName),
SecurityGroups: []*awstasks.SecurityGroup{
b.LinkToELBSecurityGroup("api"),
},
@ -128,21 +132,21 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// Configure fast-recovery health-checks
HealthCheck: &awstasks.LoadBalancerHealthCheck{
Target: s("SSL:443"),
Timeout: i64(5),
Interval: i64(10),
HealthyThreshold: i64(2),
UnhealthyThreshold: i64(2),
Target: fi.String("SSL:443"),
Timeout: fi.Int64(5),
Interval: fi.Int64(10),
HealthyThreshold: fi.Int64(2),
UnhealthyThreshold: fi.Int64(2),
},
ConnectionSettings: &awstasks.LoadBalancerConnectionSettings{
IdleTimeout: i64(int64(idleTimeout.Seconds())),
IdleTimeout: fi.Int64(int64(idleTimeout.Seconds())),
},
}
switch lbSpec.Type {
case kops.LoadBalancerTypeInternal:
elb.Scheme = s("internal")
elb.Scheme = fi.String("internal")
case kops.LoadBalancerTypePublic:
elb.Scheme = nil
default:
@ -156,12 +160,11 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
var lbSG *awstasks.SecurityGroup
{
lbSG = &awstasks.SecurityGroup{
Name: s(b.ELBSecurityGroupName("api")),
Name: fi.String(b.ELBSecurityGroupName("api")),
Lifecycle: b.SecurityLifecycle,
VPC: b.LinkToVPC(),
Description: s("Security group for api ELB"),
Description: fi.String("Security group for api ELB"),
RemoveExtraRules: []string{"port=443"},
VPC: b.LinkToVPC(),
}
lbSG.Tags = b.CloudTags(*lbSG.Name, false)
@ -176,12 +179,11 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow traffic from ELB to egress freely
{
t := &awstasks.SecurityGroupRule{
Name: s("api-elb-egress"),
Name: fi.String("api-elb-egress"),
Lifecycle: b.SecurityLifecycle,
SecurityGroup: lbSG,
CIDR: fi.String("0.0.0.0/0"),
Egress: fi.Bool(true),
CIDR: s("0.0.0.0/0"),
SecurityGroup: lbSG,
}
c.AddTask(t)
}
@ -189,18 +191,16 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow traffic into the ELB from KubernetesAPIAccess CIDRs
{
for _, cidr := range b.Cluster.Spec.KubernetesAPIAccess {
// Allow https traffic
c.AddTask(&awstasks.SecurityGroupRule{
Name: s("https-api-elb-" + cidr),
t := &awstasks.SecurityGroupRule{
Name: fi.String("https-api-elb-" + cidr),
Lifecycle: b.SecurityLifecycle,
CIDR: fi.String(cidr),
FromPort: fi.Int64(443),
Protocol: fi.String("tcp"),
SecurityGroup: lbSG,
CIDR: s(cidr),
FromPort: i64(443),
ToPort: i64(443),
Protocol: s("tcp"),
})
ToPort: fi.Int64(443),
}
c.AddTask(t)
// Allow ICMP traffic required for PMTU discovery
c.AddTask(&awstasks.SecurityGroupRule{
@ -221,10 +221,9 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
for _, id := range b.Cluster.Spec.API.LoadBalancer.AdditionalSecurityGroups {
t := &awstasks.SecurityGroup{
Name: fi.String(id),
Lifecycle: b.SecurityLifecycle,
ID: fi.String(id),
Shared: fi.Bool(true),
Lifecycle: b.SecurityLifecycle,
}
if err := c.EnsureTask(t); err != nil {
return err
@ -242,17 +241,15 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
{
for _, masterGroup := range masterGroups {
suffix := masterGroup.Suffix
t := &awstasks.SecurityGroupRule{
Name: s(fmt.Sprintf("https-elb-to-master%s", suffix)),
c.AddTask(&awstasks.SecurityGroupRule{
Name: fi.String(fmt.Sprintf("https-elb-to-master%s", suffix)),
Lifecycle: b.SecurityLifecycle,
FromPort: fi.Int64(443),
Protocol: fi.String("tcp"),
SecurityGroup: masterGroup.Task,
SourceGroup: lbSG,
FromPort: i64(443),
ToPort: i64(443),
Protocol: s("tcp"),
}
c.AddTask(t)
ToPort: fi.Int64(443),
})
}
}
@ -273,15 +270,12 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// is already done as part of the Elastigroup's creation, if needed.
if !featureflag.Spotinst.Enabled() {
for _, ig := range b.MasterInstanceGroups() {
t := &awstasks.LoadBalancerAttachment{
Name: s("api-" + ig.ObjectMeta.Name),
c.AddTask(&awstasks.LoadBalancerAttachment{
Name: fi.String("api-" + ig.ObjectMeta.Name),
Lifecycle: b.Lifecycle,
LoadBalancer: b.LinkToELB("api"),
AutoscalingGroup: b.LinkToAutoscalingGroup(ig),
}
c.AddTask(t)
LoadBalancer: b.LinkToELB("api"),
})
}
}

View File

@ -50,176 +50,196 @@ var _ fi.ModelBuilder = &AutoscalingGroupModelBuilder{}
// Build is responsible for constructing the aws autoscaling group from the kops spec
func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
var err error
for _, ig := range b.InstanceGroups {
name := b.AutoscalingGroupName(ig)
// LaunchConfiguration
var launchConfiguration *awstasks.LaunchConfiguration
{
volumeSize := fi.Int32Value(ig.Spec.RootVolumeSize)
if volumeSize == 0 {
volumeSize, err = defaults.DefaultInstanceGroupVolumeSize(ig.Spec.Role)
// @check if his instancegroup is backed by a fleet and overide with a launch template
task, err := func() (fi.Task, error) {
switch UseLaunchTemplate(ig) {
case true:
return b.buildLaunchTemplateTask(c, name, ig)
default:
return b.buildLaunchConfigurationTask(c, name, ig)
}
}()
if err != nil {
return err
}
c.AddTask(task)
// @step: now lets build the autoscaling group task
tsk, err := b.buildAutoScalingGroupTask(c, name, ig)
if err != nil {
return err
}
switch UseLaunchTemplate(ig) {
case true:
tsk.LaunchTemplate = task.(*awstasks.LaunchTemplate)
default:
tsk.LaunchConfiguration = task.(*awstasks.LaunchConfiguration)
}
c.AddTask(tsk)
// @step: add any external load balancer attachments
if err := b.buildExternalLoadBalancerTasks(c, ig); err != nil {
return err
}
}
volumeType := fi.StringValue(ig.Spec.RootVolumeType)
if volumeType == "" {
volumeType = DefaultVolumeType
}
return nil
}
volumeIops := fi.Int32Value(ig.Spec.RootVolumeIops)
if volumeIops <= 0 {
volumeIops = DefaultVolumeIops
}
link, err := b.LinkToIAMInstanceProfile(ig)
// buildLaunchTemplateTask is responsible for creating the template task into the aws model
func (b *AutoscalingGroupModelBuilder) buildLaunchTemplateTask(c *fi.ModelBuilderContext, name string, ig *kops.InstanceGroup) (*awstasks.LaunchTemplate, error) {
lc, err := b.buildLaunchConfigurationTask(c, name, ig)
if err != nil {
return fmt.Errorf("unable to find IAM profile link for instance group %q: %v", ig.ObjectMeta.Name, err)
return nil, err
}
var sgLink *awstasks.SecurityGroup
if ig.Spec.SecurityGroupOverride != nil {
glog.V(1).Infof("WARNING: You are overwriting the Instance Groups, Security Group. When this is done you are responsible for ensure the correct rules!")
// @TODO check if there any a better way of doing this .. initially I had a type LaunchTemplate which included
// LaunchConfiguration as an anonymous field, bit given up the task dependency walker works this caused issues, due
// to the creation of a implict dependency
return &awstasks.LaunchTemplate{
Name: fi.String(name),
Lifecycle: b.Lifecycle,
AssociatePublicIP: lc.AssociatePublicIP,
IAMInstanceProfile: lc.IAMInstanceProfile,
ImageID: lc.ImageID,
InstanceMonitoring: lc.InstanceMonitoring,
InstanceType: lc.InstanceType,
RootVolumeOptimization: lc.RootVolumeOptimization,
RootVolumeSize: lc.RootVolumeSize,
RootVolumeIops: lc.RootVolumeIops,
RootVolumeType: lc.RootVolumeType,
SSHKey: lc.SSHKey,
SecurityGroups: lc.SecurityGroups,
SpotPrice: lc.SpotPrice,
Tenancy: lc.Tenancy,
UserData: lc.UserData,
}, nil
}
// buildLaunchConfigurationTask is responsible for building a launch configuration task into the model
func (b *AutoscalingGroupModelBuilder) buildLaunchConfigurationTask(c *fi.ModelBuilderContext, name string, ig *kops.InstanceGroup) (*awstasks.LaunchConfiguration, error) {
// @step: add the volume type, size and spec
volumeType := &DefaultVolumeType
var volumeIops *int64
size, err := defaults.DefaultInstanceGroupVolumeSize(ig.Spec.Role)
if err != nil {
return nil, err
}
volumeSize := fi.Int64(int64(size))
if ig.Spec.RootVolumeSize != nil {
volumeSize = fi.Int64(int64(fi.Int32Value(ig.Spec.RootVolumeSize)))
}
if ig.Spec.RootVolumeType != nil {
volumeType = ig.Spec.RootVolumeType
}
if fi.StringValue(volumeType) == ec2.VolumeTypeIo1 {
volumeIops = DefaultVolumeIops
if ig.Spec.RootVolumeIops != nil {
volumeIops = fi.Int64(int64(fi.Int32Value(ig.Spec.RootVolumeIops)))
}
}
// @step: if required we add the override for the security group for this instancegroup
sgLink := b.LinkToSecurityGroup(ig.Spec.Role)
if ig.Spec.SecurityGroupOverride != nil {
sgName := fmt.Sprintf("%v-%v", fi.StringValue(ig.Spec.SecurityGroupOverride), ig.Spec.Role)
sgLink = &awstasks.SecurityGroup{
Name: &sgName,
ID: ig.Spec.SecurityGroupOverride,
Name: &sgName,
Shared: fi.Bool(true),
}
} else {
sgLink = b.LinkToSecurityGroup(ig.Spec.Role)
}
// @step: add the iam instance profile
link, err := b.LinkToIAMInstanceProfile(ig)
if err != nil {
return nil, fmt.Errorf("unable to find iam profile link for instance group %q: %v", ig.ObjectMeta.Name, err)
}
t := &awstasks.LaunchConfiguration{
Name: s(name),
Name: fi.String(name),
Lifecycle: b.Lifecycle,
IAMInstanceProfile: link,
ImageID: s(ig.Spec.Image),
ImageID: fi.String(ig.Spec.Image),
InstanceMonitoring: ig.Spec.DetailedInstanceMonitoring,
InstanceType: s(strings.Split(ig.Spec.MachineType, ",")[0]),
InstanceType: fi.String(strings.Split(ig.Spec.MachineType, ",")[0]),
RootVolumeOptimization: ig.Spec.RootVolumeOptimization,
RootVolumeSize: i64(int64(volumeSize)),
RootVolumeType: s(volumeType),
RootVolumeSize: volumeSize,
RootVolumeIops: volumeIops,
RootVolumeType: volumeType,
SecurityGroups: []*awstasks.SecurityGroup{sgLink},
}
if volumeType == ec2.VolumeTypeIo1 {
t.RootVolumeIops = i64(int64(volumeIops))
}
if ig.Spec.Tenancy != "" {
t.Tenancy = s(ig.Spec.Tenancy)
t.Tenancy = fi.String(ig.Spec.Tenancy)
}
// @step: add any additional security groups to the instance
// @step: add any additional security groups to the instancegroup
for _, id := range ig.Spec.AdditionalSecurityGroups {
sgTask := &awstasks.SecurityGroup{
Name: fi.String(id),
ID: fi.String(id),
Lifecycle: b.SecurityLifecycle,
Name: fi.String(id),
Shared: fi.Bool(true),
}
if err := c.EnsureTask(sgTask); err != nil {
return err
return nil, err
}
t.SecurityGroups = append(t.SecurityGroups, sgTask)
}
// @step: add any additional block devices to the launch configuration
for _, x := range ig.Spec.Volumes {
if x.Type == "" {
x.Type = DefaultVolumeType
}
if x.Type == ec2.VolumeTypeIo1 {
if x.Iops == nil {
x.Iops = fi.Int64(DefaultVolumeIops)
}
} else {
x.Iops = nil
}
t.BlockDeviceMappings = append(t.BlockDeviceMappings, &awstasks.BlockDeviceMapping{
DeviceName: fi.String(x.Device),
EbsDeleteOnTermination: fi.Bool(true),
EbsEncrypted: x.Encrypted,
EbsVolumeIops: x.Iops,
EbsVolumeSize: fi.Int64(x.Size),
EbsVolumeType: fi.String(x.Type),
})
}
// @step: attach the ssh key to the instancegroup
if t.SSHKey, err = b.LinkToSSHKey(); err != nil {
return err
return nil, err
}
// @step: add the instancegroup userdata
if t.UserData, err = b.BootstrapScript.ResourceNodeUp(ig, b.Cluster); err != nil {
return err
return nil, err
}
// @step: set up instnce spot pricing
if fi.StringValue(ig.Spec.MaxPrice) != "" {
spotPrice := fi.StringValue(ig.Spec.MaxPrice)
t.SpotPrice = spotPrice
}
{
// TODO: Wrapper / helper class to analyze clusters
subnetMap := make(map[string]*kops.ClusterSubnetSpec)
for i := range b.Cluster.Spec.Subnets {
subnet := &b.Cluster.Spec.Subnets[i]
subnetMap[subnet.Name] = subnet
// @step: check the subnets are ok and pull together an array for us
subnets, err := b.GatherSubnets(ig)
if err != nil {
return nil, err
}
var subnetType kops.SubnetType
for _, subnetName := range ig.Spec.Subnets {
subnet := subnetMap[subnetName]
if subnet == nil {
return fmt.Errorf("InstanceGroup %q uses subnet %q that does not exist", ig.ObjectMeta.Name, subnetName)
}
if subnetType != "" && subnetType != subnet.Type {
return fmt.Errorf("InstanceGroup %q cannot be in subnets of different Type", ig.ObjectMeta.Name)
}
subnetType = subnet.Type
}
associatePublicIP := true
switch subnetType {
// @step: check if we can add an public ip to this subnet
switch subnets[0].Type {
case kops.SubnetTypePublic, kops.SubnetTypeUtility:
associatePublicIP = true
if ig.Spec.AssociatePublicIP != nil {
associatePublicIP = *ig.Spec.AssociatePublicIP
}
t.AssociatePublicIP = ig.Spec.AssociatePublicIP
case kops.SubnetTypePrivate:
associatePublicIP = false
if ig.Spec.AssociatePublicIP != nil {
// This isn't meaningful - private subnets can't have public ip
//associatePublicIP = *ig.Spec.AssociatePublicIP
if *ig.Spec.AssociatePublicIP {
if fi.BoolValue(ig.Spec.AssociatePublicIP) {
glog.Warningf("Ignoring AssociatePublicIP=true for private InstanceGroup %q", ig.ObjectMeta.Name)
}
}
default:
return fmt.Errorf("unknown subnet type %q", subnetType)
}
t.AssociatePublicIP = &associatePublicIP
}
c.AddTask(t)
launchConfiguration = t
}
// AutoscalingGroup
{
return t, nil
}
// buildAutoscalingGroupTask is responsible for building the autoscaling task into the model
func (b *AutoscalingGroupModelBuilder) buildAutoScalingGroupTask(c *fi.ModelBuilderContext, name string, ig *kops.InstanceGroup) (*awstasks.AutoscalingGroup, error) {
t := &awstasks.AutoscalingGroup{
Name: s(name),
Name: fi.String(name),
Lifecycle: b.Lifecycle,
Granularity: s("1Minute"),
Granularity: fi.String("1Minute"),
Metrics: []string{
"GroupDesiredCapacity",
"GroupInServiceInstances",
@ -230,7 +250,6 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
"GroupTerminatingInstances",
"GroupTotalInstances",
},
LaunchConfiguration: launchConfiguration,
}
minSize := int32(1)
@ -246,15 +265,15 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
maxSize = 2
}
t.MinSize = i64(int64(minSize))
t.MaxSize = i64(int64(maxSize))
t.MinSize = fi.Int64(int64(minSize))
t.MaxSize = fi.Int64(int64(maxSize))
subnets, err := b.GatherSubnets(ig)
if err != nil {
return err
return nil, err
}
if len(subnets) == 0 {
return fmt.Errorf("could not determine any subnets for InstanceGroup %q; subnets was %s", ig.ObjectMeta.Name, ig.Spec.Subnets)
return nil, fmt.Errorf("could not determine any subnets for InstanceGroup %q; subnets was %s", ig.ObjectMeta.Name, ig.Spec.Subnets)
}
for _, subnet := range subnets {
t.Subnets = append(t.Subnets, b.LinkToSubnet(subnet))
@ -262,7 +281,7 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
tags, err := b.CloudTagsForInstanceGroup(ig)
if err != nil {
return fmt.Errorf("error building cloud tags: %v", err)
return nil, fmt.Errorf("error building cloud tags: %v", err)
}
t.Tags = tags
@ -272,34 +291,40 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
}
t.SuspendProcesses = &processes
c.AddTask(t)
// @step: are we using a mixed instance policy
if ig.Spec.MixedInstancesPolicy != nil {
spec := ig.Spec.MixedInstancesPolicy
t.MixedInstanceOverrides = spec.Instances
t.MixedOnDemandAboveBase = spec.OnDemandAboveBase
t.MixedOnDemandAllocationStrategy = spec.OnDemandAllocationStrategy
t.MixedOnDemandBase = spec.OnDemandBase
t.MixedSpotAllocationStrategy = spec.SpotAllocationStrategy
t.MixedSpotInstancePools = spec.SpotInstancePools
}
// External Load Balancer/TargetGroup Attachments
{
for _, lb := range ig.Spec.ExternalLoadBalancers {
if lb.LoadBalancerName != nil {
t := &awstasks.ExternalLoadBalancerAttachment{
Name: s("extlb-" + *lb.LoadBalancerName + "-" + ig.Name),
return t, nil
}
// buildExternlLoadBalancerTasks is responsible for adding any ELB attachment tasks to the model
func (b *AutoscalingGroupModelBuilder) buildExternalLoadBalancerTasks(c *fi.ModelBuilderContext, ig *kops.InstanceGroup) error {
for _, x := range ig.Spec.ExternalLoadBalancers {
if x.LoadBalancerName != nil {
c.AddTask(&awstasks.ExternalLoadBalancerAttachment{
Name: fi.String("extlb-" + *x.LoadBalancerName + "-" + ig.Name),
Lifecycle: b.Lifecycle,
LoadBalancerName: *lb.LoadBalancerName,
LoadBalancerName: *x.LoadBalancerName,
AutoscalingGroup: b.LinkToAutoscalingGroup(ig),
})
}
c.AddTask(t)
}
if lb.TargetGroupARN != nil {
t := &awstasks.ExternalTargetGroupAttachment{
Name: s("exttg-" + *lb.TargetGroupARN + "-" + ig.Name),
if x.TargetGroupARN != nil {
c.AddTask(&awstasks.ExternalTargetGroupAttachment{
Name: fi.String("exttg-" + *x.TargetGroupARN + "-" + ig.Name),
Lifecycle: b.Lifecycle,
TargetGroupARN: *lb.TargetGroupARN,
TargetGroupARN: *x.TargetGroupARN,
AutoscalingGroup: b.LinkToAutoscalingGroup(ig),
}
c.AddTask(t)
}
}
})
}
}

View File

@ -16,8 +16,17 @@ limitations under the License.
package awsmodel
import "k8s.io/kops/pkg/model"
import (
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/model"
)
// AWSModelContext provides the context for the aws model
type AWSModelContext struct {
*model.KopsModelContext
}
// UseLaunchTemplate checks if we need to use a launch template rather than configuration
func UseLaunchTemplate(ig *kops.InstanceGroup) bool {
return ig.Spec.MixedInstancesPolicy != nil
}

View File

@ -1,34 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
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 awsmodel
import "k8s.io/kops/upup/pkg/fi"
// s is a helper that builds a *string from a string value
func s(v string) *string {
return fi.String(v)
}
// i64 is a helper that builds a *int64 from an int64 value
func i64(v int64) *int64 {
return fi.Int64(v)
}
// i32 is a helper that builds a *int32 from an int32 value
func i32(v int32) *int32 {
return fi.Int32(v)
}

View File

@ -96,6 +96,7 @@ func (m *KopsModelContext) GetELBName32(prefix string) string {
return s
}
// ClusterName returns the cluster name
func (m *KopsModelContext) ClusterName() string {
return m.Cluster.ObjectMeta.Name
}
@ -103,6 +104,8 @@ func (m *KopsModelContext) ClusterName() string {
// GatherSubnets maps the subnet names in an InstanceGroup to the ClusterSubnetSpec objects (which are stored on the Cluster)
func (m *KopsModelContext) GatherSubnets(ig *kops.InstanceGroup) ([]*kops.ClusterSubnetSpec, error) {
var subnets []*kops.ClusterSubnetSpec
var subnetType kops.SubnetType
for _, subnetName := range ig.Spec.Subnets {
var matches []*kops.ClusterSubnetSpec
for i := range m.Cluster.Spec.Subnets {
@ -118,7 +121,18 @@ func (m *KopsModelContext) GatherSubnets(ig *kops.InstanceGroup) ([]*kops.Cluste
return nil, fmt.Errorf("found multiple subnets with name: %q", subnetName)
}
subnets = append(subnets, matches[0])
// @step: check the instance is not cross subnet types
switch subnetType {
case "":
subnetType = matches[0].Type
default:
if matches[0].Type != subnetType {
return nil, fmt.Errorf("found subnets of different types: %v", strings.Join([]string{string(subnetType), string(matches[0].Type)}, ","))
}
}
}
return subnets, nil
}
@ -285,7 +299,7 @@ func (m *KopsModelContext) UseLoadBalancerForAPI() bool {
return m.Cluster.Spec.API.LoadBalancer != nil
}
// If true then we will use the created loadbalancer for internal kubelet
// UseLoadBalancerForInternalAPI check if true then we will use the created loadbalancer for internal kubelet
// connections. The intention here is to make connections to apiserver more
// HA - see https://github.com/kubernetes/kops/issues/4252
func (m *KopsModelContext) UseLoadBalancerForInternalAPI() bool {
@ -313,8 +327,8 @@ func (m *KopsModelContext) UsePrivateDNS() bool {
}
// UseEtcdTLS checks to see if etcd tls is enabled
func (c *KopsModelContext) UseEtcdTLS() bool {
for _, x := range c.Cluster.Spec.EtcdClusters {
func (m *KopsModelContext) UseEtcdTLS() bool {
for _, x := range m.Cluster.Spec.EtcdClusters {
if x.EnableEtcdTLS {
return true
}
@ -324,10 +338,10 @@ func (c *KopsModelContext) UseEtcdTLS() bool {
}
// KubernetesVersion parses the semver version of kubernetes, from the cluster spec
func (c *KopsModelContext) KubernetesVersion() semver.Version {
func (m *KopsModelContext) KubernetesVersion() semver.Version {
// TODO: Remove copy-pasting c.f. https://github.com/kubernetes/kops/blob/master/pkg/model/components/context.go#L32
kubernetesVersion := c.Cluster.Spec.KubernetesVersion
kubernetesVersion := m.Cluster.Spec.KubernetesVersion
if kubernetesVersion == "" {
glog.Fatalf("KubernetesVersion is required")
@ -342,20 +356,21 @@ func (c *KopsModelContext) KubernetesVersion() semver.Version {
}
// IsKubernetesGTE checks if the kubernetes version is at least version, ignoring prereleases / patches
func (c *KopsModelContext) IsKubernetesGTE(version string) bool {
return util.IsKubernetesGTE(version, c.KubernetesVersion())
func (m *KopsModelContext) IsKubernetesGTE(version string) bool {
return util.IsKubernetesGTE(version, m.KubernetesVersion())
}
func (c *KopsModelContext) WellKnownServiceIP(id int) (net.IP, error) {
return components.WellKnownServiceIP(&c.Cluster.Spec, id)
// WellKnownServiceIP returns a service ip with the service cidr
func (m *KopsModelContext) WellKnownServiceIP(id int) (net.IP, error) {
return components.WellKnownServiceIP(&m.Cluster.Spec, id)
}
// NodePortRange returns the range of ports allocated to NodePorts
func (c *KopsModelContext) NodePortRange() (utilnet.PortRange, error) {
func (m *KopsModelContext) NodePortRange() (utilnet.PortRange, error) {
// defaultServiceNodePortRange is the default port range for NodePort services.
defaultServiceNodePortRange := utilnet.PortRange{Base: 30000, Size: 2768}
kubeApiServer := c.Cluster.Spec.KubeAPIServer
kubeApiServer := m.Cluster.Spec.KubeAPIServer
if kubeApiServer != nil && kubeApiServer.ServiceNodePortRange != "" {
err := defaultServiceNodePortRange.Set(kubeApiServer.ServiceNodePortRange)
if err != nil {

View File

@ -23,9 +23,12 @@ import (
)
const (
DefaultVolumeSizeNode = 128
DefaultVolumeSizeMaster = 64
// DefaultVolumeSizeBastion is the default root disk size of a bastion
DefaultVolumeSizeBastion = 32
// DefaultVolumeSizeMaster is the default root disk size of a master
DefaultVolumeSizeMaster = 64
// DefaultVolumeSizeNode is the default root disk size of a node
DefaultVolumeSizeNode = 128
)
// DefaultInstanceGroupVolumeSize returns the default volume size for nodes in an InstanceGroup with the specified role

View File

@ -20,14 +20,15 @@ import (
"fmt"
"regexp"
"github.com/golang/glog"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/pki"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
"github.com/golang/glog"
)
// SecurityGroupName returns the security group name for the specific role
func (b *KopsModelContext) SecurityGroupName(role kops.InstanceGroupRole) string {
switch role {
case kops.InstanceGroupRoleBastion:
@ -42,11 +43,13 @@ func (b *KopsModelContext) SecurityGroupName(role kops.InstanceGroupRole) string
}
}
// LinkToSecurityGroup creates a task link the security group to the instncegroup
func (b *KopsModelContext) LinkToSecurityGroup(role kops.InstanceGroupRole) *awstasks.SecurityGroup {
name := b.SecurityGroupName(role)
return &awstasks.SecurityGroup{Name: &name}
}
// AutoscalingGroupName derives the autoscaling group name for us
func (b *KopsModelContext) AutoscalingGroupName(ig *kops.InstanceGroup) string {
switch ig.Spec.Role {
case kops.InstanceGroupRoleMaster:
@ -77,6 +80,7 @@ func (b *KopsModelContext) LinkToELBSecurityGroup(prefix string) *awstasks.Secur
return &awstasks.SecurityGroup{Name: &name}
}
// ELBName returns ELB name plus cluster name
func (b *KopsModelContext) ELBName(prefix string) string {
return prefix + "." + b.ClusterName()
}