mirror of https://github.com/kubernetes/kops.git
- updating the aws model to make use of the aws template and mixed instance policies
This commit is contained in:
parent
39db0816df
commit
761d760c11
|
@ -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"],
|
||||
|
|
|
@ -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"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue