Create new clusters with updated control plane IG names

This commit is contained in:
John Gardiner Myers 2022-11-22 20:19:46 -08:00
parent 1b4616c9fb
commit 6c0603991b
14 changed files with 144 additions and 127 deletions

View File

@ -61,18 +61,18 @@ import (
type CreateClusterOptions struct { type CreateClusterOptions struct {
cloudup.NewClusterOptions cloudup.NewClusterOptions
Yes bool Yes bool
Target string Target string
MasterVolumeSize int32 ControlPlaneVolumeSize int32
NodeVolumeSize int32 NodeVolumeSize int32
ContainerRuntime string ContainerRuntime string
OutDir string OutDir string
DisableSubnetTags bool DisableSubnetTags bool
NetworkCIDR string NetworkCIDR string
DNSZone string DNSZone string
NodeSecurityGroups []string NodeSecurityGroups []string
MasterSecurityGroups []string ControlPlaneSecurityGroups []string
AssociatePublicIP *bool AssociatePublicIP *bool
// SSHPublicKeys is a map of the SSH public keys we should configure; required on AWS, not required on GCE // SSHPublicKeys is a map of the SSH public keys we should configure; required on AWS, not required on GCE
SSHPublicKeys map[string][]byte SSHPublicKeys map[string][]byte
@ -85,12 +85,12 @@ type CreateClusterOptions struct {
// CloudLabels are cloud-provider-level tags for instance groups and volumes. // CloudLabels are cloud-provider-level tags for instance groups and volumes.
CloudLabels string CloudLabels string
// Specify tenancy (default or dedicated) for masters and nodes // Specify tenancy (default or dedicated) for control-plane and worker nodes
MasterTenancy string ControlPlaneTenancy string
NodeTenancy string NodeTenancy string
// Allow custom public master name // Allow custom public Kubernetes API name.
MasterPublicName string APIPublicName string
OpenstackNetworkID string OpenstackNetworkID string
@ -126,19 +126,19 @@ var (
--zones=us-east-1a \ --zones=us-east-1a \
--node-count=2 --node-count=2
# Create a cluster in AWS with High Availability masters. This cluster # Create a cluster in AWS with a High Availability control plane. This cluster
# has also been configured for private networking in a kops-managed VPC. # has also been configured for private networking in a kops-managed VPC.
# The bastion flag is set to create an entrypoint for admins to SSH. # The bastion flag is set to create an entrypoint for admins to SSH.
export KOPS_STATE_STORE="s3://my-state-store" export KOPS_STATE_STORE="s3://my-state-store"
export MASTER_SIZE="c5.large" export CONTROL_PLANE_SIZE="c5.large"
export NODE_SIZE="m5.large" export NODE_SIZE="m5.large"
export ZONES="us-east-1a,us-east-1b,us-east-1c" export ZONES="us-east-1a,us-east-1b,us-east-1c"
kops create cluster k8s-cluster.example.com \ kops create cluster k8s-cluster.example.com \
--node-count 3 \ --node-count 3 \
--zones $ZONES \ --zones $ZONES \
--node-size $NODE_SIZE \ --node-size $NODE_SIZE \
--master-size $MASTER_SIZE \ --control-plane-size $CONTROL_PLANE_SIZE \
--master-zones $ZONES \ --control-plane-zones $ZONES \
--networking cilium \ --networking cilium \
--topology private \ --topology private \
--bastion="true" \ --bastion="true" \
@ -150,7 +150,7 @@ var (
kops create cluster k8s-cluster.example.com \ kops create cluster k8s-cluster.example.com \
--cloud digitalocean \ --cloud digitalocean \
--zones $ZONES \ --zones $ZONES \
--master-zones $ZONES \ --control-plane-zones $ZONES \
--node-count 3 \ --node-count 3 \
--yes --yes
@ -237,8 +237,8 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringSliceVar(&options.Zones, "zones", options.Zones, "Zones in which to run the cluster") cmd.Flags().StringSliceVar(&options.Zones, "zones", options.Zones, "Zones in which to run the cluster")
cmd.RegisterFlagCompletionFunc("zones", completeZone(options)) cmd.RegisterFlagCompletionFunc("zones", completeZone(options))
cmd.Flags().StringSliceVar(&options.MasterZones, "master-zones", options.MasterZones, "Zones in which to run masters (must be an odd number)") cmd.Flags().StringSliceVar(&options.ControlPlaneZones, "control-plane-zones", options.ControlPlaneZones, "Zones in which to run control-plane nodes. (must be an odd number)")
cmd.RegisterFlagCompletionFunc("master-zones", completeZone(options)) cmd.RegisterFlagCompletionFunc("control-plane-zones", completeZone(options))
if featureflag.ClusterAddons.Enabled() { if featureflag.ClusterAddons.Enabled() {
cmd.Flags().StringSliceVar(&options.AddonPaths, "add", options.AddonPaths, "Paths to addons we should add to the cluster") cmd.Flags().StringSliceVar(&options.AddonPaths, "add", options.AddonPaths, "Paths to addons we should add to the cluster")
@ -261,24 +261,24 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
return []string{"pub"}, cobra.ShellCompDirectiveFilterFileExt return []string{"pub"}, cobra.ShellCompDirectiveFilterFileExt
}) })
cmd.Flags().Int32Var(&options.MasterCount, "master-count", options.MasterCount, "Number of masters. Defaults to one master per master-zone") cmd.Flags().Int32Var(&options.ControlPlaneCount, "control-plane-count", options.ControlPlaneCount, "Number of control-plane nodes. Defaults to one control-plane node per control-plane-zone")
cmd.Flags().Int32Var(&options.NodeCount, "node-count", options.NodeCount, "Total number of worker nodes. Defaults to one node per zone") cmd.Flags().Int32Var(&options.NodeCount, "node-count", options.NodeCount, "Total number of worker nodes. Defaults to one node per zone")
cmd.Flags().StringVar(&options.Image, "image", options.Image, "Machine image for all instances") cmd.Flags().StringVar(&options.Image, "image", options.Image, "Machine image for all instances")
cmd.RegisterFlagCompletionFunc("image", completeInstanceImage) cmd.RegisterFlagCompletionFunc("image", completeInstanceImage)
cmd.Flags().StringVar(&options.NodeImage, "node-image", options.NodeImage, "Machine image for worker nodes. Takes precedence over --image") cmd.Flags().StringVar(&options.NodeImage, "node-image", options.NodeImage, "Machine image for worker nodes. Takes precedence over --image")
cmd.RegisterFlagCompletionFunc("node-image", completeInstanceImage) cmd.RegisterFlagCompletionFunc("node-image", completeInstanceImage)
cmd.Flags().StringVar(&options.MasterImage, "master-image", options.MasterImage, "Machine image for masters. Takes precedence over --image") cmd.Flags().StringVar(&options.ControlPlaneImage, "control-plane-image", options.ControlPlaneImage, "Machine image for control-plane nodes. Takes precedence over --image")
cmd.RegisterFlagCompletionFunc("master-image", completeInstanceImage) cmd.RegisterFlagCompletionFunc("control-plane-image", completeInstanceImage)
cmd.Flags().StringVar(&options.BastionImage, "bastion-image", options.BastionImage, "Machine image for bastions. Takes precedence over --image") cmd.Flags().StringVar(&options.BastionImage, "bastion-image", options.BastionImage, "Machine image for bastions. Takes precedence over --image")
cmd.RegisterFlagCompletionFunc("bastion-image", completeInstanceImage) cmd.RegisterFlagCompletionFunc("bastion-image", completeInstanceImage)
cmd.Flags().StringVar(&options.NodeSize, "node-size", options.NodeSize, "Machine type for worker nodes") cmd.Flags().StringVar(&options.NodeSize, "node-size", options.NodeSize, "Machine type for worker nodes")
cmd.RegisterFlagCompletionFunc("node-size", completeMachineType) cmd.RegisterFlagCompletionFunc("node-size", completeMachineType)
cmd.Flags().StringVar(&options.MasterSize, "master-size", options.MasterSize, "Machine type for masters") cmd.Flags().StringVar(&options.ControlPlaneSize, "control-plane-size", options.ControlPlaneSize, "Machine type for control-plane nodes")
cmd.RegisterFlagCompletionFunc("master-size", completeMachineType) cmd.RegisterFlagCompletionFunc("control-plane-size", completeMachineType)
cmd.Flags().Int32Var(&options.MasterVolumeSize, "master-volume-size", options.MasterVolumeSize, "Instance volume size (in GB) for masters") cmd.Flags().Int32Var(&options.ControlPlaneVolumeSize, "control-plane-volume-size", options.ControlPlaneVolumeSize, "Instance volume size (in GB) for control-plane nodes")
cmd.Flags().Int32Var(&options.NodeVolumeSize, "node-volume-size", options.NodeVolumeSize, "Instance volume size (in GB) for worker nodes") cmd.Flags().Int32Var(&options.NodeVolumeSize, "node-volume-size", options.NodeVolumeSize, "Instance volume size (in GB) for worker nodes")
cmd.Flags().StringVar(&options.NetworkID, "vpc", options.NetworkID, "Shared Network or VPC to use") cmd.Flags().StringVar(&options.NetworkID, "vpc", options.NetworkID, "Shared Network or VPC to use")
@ -317,14 +317,14 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
}) })
// TODO: Can we deprecate this flag - it is awkward? // TODO: Can we deprecate this flag - it is awkward?
cmd.Flags().BoolVar(&associatePublicIP, "associate-public-ip", false, "Specify --associate-public-ip=[true|false] to enable/disable association of public IP for master ASG and nodes. Default is 'true'.") cmd.Flags().BoolVar(&associatePublicIP, "associate-public-ip", false, "Specify --associate-public-ip=[true|false] to enable/disable association of public IP for control-plane ASG and nodes. Default is 'true'.")
cmd.Flags().BoolVar(&options.IPv6, "ipv6", false, "Use IPv6 for the pod network (AWS only)") cmd.Flags().BoolVar(&options.IPv6, "ipv6", false, "Use IPv6 for the pod network (AWS only)")
cmd.Flags().StringSliceVar(&options.NodeSecurityGroups, "node-security-groups", options.NodeSecurityGroups, "Additional precreated security groups to add to worker nodes.") cmd.Flags().StringSliceVar(&options.NodeSecurityGroups, "node-security-groups", options.NodeSecurityGroups, "Additional pre-created security groups to add to worker nodes.")
cmd.RegisterFlagCompletionFunc("node-security-groups", completeSecurityGroup) cmd.RegisterFlagCompletionFunc("node-security-groups", completeSecurityGroup)
cmd.Flags().StringSliceVar(&options.MasterSecurityGroups, "master-security-groups", options.MasterSecurityGroups, "Additional precreated security groups to add to masters.") cmd.Flags().StringSliceVar(&options.ControlPlaneSecurityGroups, "control-plane-security-groups", options.ControlPlaneSecurityGroups, "Additional pre-created security groups to add to control-plane nodes.")
cmd.RegisterFlagCompletionFunc("master-security-groups", completeSecurityGroup) cmd.RegisterFlagCompletionFunc("control-plane-security-groups", completeSecurityGroup)
cmd.Flags().StringVar(&options.Channel, "channel", options.Channel, "Channel for default versions and configuration to use") cmd.Flags().StringVar(&options.Channel, "channel", options.Channel, "Channel for default versions and configuration to use")
cmd.RegisterFlagCompletionFunc("channel", completeChannel) cmd.RegisterFlagCompletionFunc("channel", completeChannel)
@ -357,9 +357,9 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}) })
// Master and Node Tenancy // Control Plane and Worker Node Tenancy
cmd.Flags().StringVar(&options.MasterTenancy, "master-tenancy", options.MasterTenancy, "Tenancy of the master group (AWS only): default or dedicated") cmd.Flags().StringVar(&options.ControlPlaneTenancy, "control-plane-tenancy", options.ControlPlaneTenancy, "Tenancy of the control-plane group (AWS only): default or dedicated")
cmd.RegisterFlagCompletionFunc("master-tenancy", completeTenancy) cmd.RegisterFlagCompletionFunc("control-plane-tenancy", completeTenancy)
cmd.Flags().StringVar(&options.NodeTenancy, "node-tenancy", options.NodeTenancy, "Tenancy of the node group (AWS only): default or dedicated") cmd.Flags().StringVar(&options.NodeTenancy, "node-tenancy", options.NodeTenancy, "Tenancy of the node group (AWS only): default or dedicated")
cmd.RegisterFlagCompletionFunc("node-tenancy", completeTenancy) cmd.RegisterFlagCompletionFunc("node-tenancy", completeTenancy)
@ -375,9 +375,9 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&options.APISSLCertificate, "api-ssl-certificate", options.APISSLCertificate, "ARN of the SSL Certificate to use for the Kubernetes API load balancer (AWS only)") cmd.Flags().StringVar(&options.APISSLCertificate, "api-ssl-certificate", options.APISSLCertificate, "ARN of the SSL Certificate to use for the Kubernetes API load balancer (AWS only)")
cmd.RegisterFlagCompletionFunc("api-ssl-certificate", completeSSLCertificate) cmd.RegisterFlagCompletionFunc("api-ssl-certificate", completeSSLCertificate)
// Allow custom public master name // Allow custom public Kuberneters API name.
cmd.Flags().StringVar(&options.MasterPublicName, "master-public-name", options.MasterPublicName, "Domain name of the public Kubernetes API") cmd.Flags().StringVar(&options.APIPublicName, "api-public-name", options.APIPublicName, "Domain name of the public Kubernetes API")
cmd.RegisterFlagCompletionFunc("master-public-name", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { cmd.RegisterFlagCompletionFunc("api-public-name", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveNoFileComp
}) })
@ -450,6 +450,22 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
switch name { switch name {
case "override": case "override":
name = "set" name = "set"
case "master-count":
name = "control-plane-count"
case "master-image":
name = "control-plane-image"
case "master-public-name":
name = "api-public-name"
case "master-security-groups":
name = "control-plane-security-groups"
case "master-size":
name = "control-plane-size"
case "master-tenancy":
name = "control-plane-tenancy"
case "master-volume-size":
name = "control-plane-volume-size"
case "master-zones":
name = "control-plane-zones"
} }
return pflag.NormalizedName(name) return pflag.NormalizedName(name)
}) })
@ -528,12 +544,12 @@ func RunCreateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *Cr
cluster := clusterResult.Cluster cluster := clusterResult.Cluster
instanceGroups := clusterResult.InstanceGroups instanceGroups := clusterResult.InstanceGroups
var masters []*api.InstanceGroup var controlPlanes []*api.InstanceGroup
var nodes []*api.InstanceGroup var nodes []*api.InstanceGroup
for _, ig := range instanceGroups { for _, ig := range instanceGroups {
switch ig.Spec.Role { switch ig.Spec.Role {
case api.InstanceGroupRoleControlPlane: case api.InstanceGroupRoleControlPlane:
masters = append(masters, ig) controlPlanes = append(controlPlanes, ig)
case api.InstanceGroupRoleNode: case api.InstanceGroupRoleNode:
nodes = append(nodes, ig) nodes = append(nodes, ig)
} }
@ -553,9 +569,9 @@ func RunCreateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *Cr
} }
} }
if c.MasterTenancy != "" { if c.ControlPlaneTenancy != "" {
for _, group := range masters { for _, group := range controlPlanes {
group.Spec.Tenancy = c.MasterTenancy group.Spec.Tenancy = c.ControlPlaneTenancy
} }
} }
@ -571,15 +587,15 @@ func RunCreateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *Cr
} }
} }
if len(c.MasterSecurityGroups) > 0 { if len(c.ControlPlaneSecurityGroups) > 0 {
for _, group := range masters { for _, group := range controlPlanes {
group.Spec.AdditionalSecurityGroups = c.MasterSecurityGroups group.Spec.AdditionalSecurityGroups = c.ControlPlaneSecurityGroups
} }
} }
if c.MasterVolumeSize != 0 { if c.ControlPlaneVolumeSize != 0 {
for _, group := range masters { for _, group := range controlPlanes {
group.Spec.RootVolumeSize = fi.PtrTo(c.MasterVolumeSize) group.Spec.RootVolumeSize = fi.PtrTo(c.ControlPlaneVolumeSize)
} }
} }
@ -605,8 +621,8 @@ func RunCreateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *Cr
cluster.Spec.TagSubnets = fi.PtrTo(false) cluster.Spec.TagSubnets = fi.PtrTo(false)
} }
if c.MasterPublicName != "" { if c.APIPublicName != "" {
cluster.Spec.API.PublicName = c.MasterPublicName cluster.Spec.API.PublicName = c.APIPublicName
} }
if err := commands.UnsetClusterFields(c.Unsets, cluster); err != nil { if err := commands.UnsetClusterFields(c.Unsets, cluster); err != nil {
@ -782,8 +798,8 @@ func RunCreateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *Cr
if len(nodes) > 0 { if len(nodes) > 0 {
fmt.Fprintf(&sb, " * edit your node instance group: kops edit ig --name=%s %s\n", cluster.Name, nodes[0].ObjectMeta.Name) fmt.Fprintf(&sb, " * edit your node instance group: kops edit ig --name=%s %s\n", cluster.Name, nodes[0].ObjectMeta.Name)
} }
if len(masters) > 0 { if len(controlPlanes) > 0 {
fmt.Fprintf(&sb, " * edit your master instance group: kops edit ig --name=%s %s\n", cluster.Name, masters[0].ObjectMeta.Name) fmt.Fprintf(&sb, " * edit your control-plane instance group: kops edit ig --name=%s %s\n", cluster.Name, controlPlanes[0].ObjectMeta.Name)
} }
fmt.Fprintf(&sb, "\n") fmt.Fprintf(&sb, "\n")
fmt.Fprintf(&sb, "Finally configure your cluster with: kops update cluster --name %s --yes --admin\n", cluster.Name) fmt.Fprintf(&sb, "Finally configure your cluster with: kops update cluster --name %s --yes --admin\n", cluster.Name)

View File

@ -129,7 +129,7 @@ func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
return err return err
} }
// Using EnsureTask as APIInternalName() and MasterPublicName could be the same // Using EnsureTask as APIInternalName() and APIPublicName could be the same
{ {
err := c.EnsureTask(&awstasks.DNSName{ err := c.EnsureTask(&awstasks.DNSName{
Name: fi.PtrTo(b.Cluster.APIInternalName()), Name: fi.PtrTo(b.Cluster.APIInternalName()),

View File

@ -5,7 +5,7 @@ CloudProvider: aws
Networking: cni Networking: cni
KubernetesVersion: v1.24.0 KubernetesVersion: v1.24.0
Image: ami-image Image: ami-image
MasterImage: ami-control-plane ControlPlaneImage: ami-control-plane
NodeImage: ami-worker-image NodeImage: ami-worker-image
Bastion: true Bastion: true
Topology: private Topology: private

View File

@ -1,7 +1,7 @@
ClusterName: gce.example.com ClusterName: gce.example.com
Zones: Zones:
- us-test1-a - us-test1-a
MasterZones: ControlPlaneZones:
- us-test1-a - us-test1-a
CloudProvider: gce CloudProvider: gce
Networking: cni Networking: cni

View File

@ -3,7 +3,7 @@ Zones:
- us-test-1a - us-test-1a
- us-test-1b - us-test-1b
- us-test-1c - us-test-1c
MasterZones: ControlPlaneZones:
- us-test-1a - us-test-1a
- us-test-1b - us-test-1b
- us-test-1c - us-test-1c

View File

@ -3,7 +3,7 @@ Zones:
- us-test-1a - us-test-1a
- us-test-1b - us-test-1b
- us-test-1c - us-test-1c
MasterZones: ControlPlaneZones:
- us-test-1a - us-test-1a
- us-test-1b - us-test-1b
- us-test-1c - us-test-1c

View File

@ -3,7 +3,7 @@ Zones:
- us-test1-a - us-test1-a
- us-test1-b - us-test1-b
- us-test1-c - us-test1-c
MasterZones: ControlPlaneZones:
- us-test1-a - us-test1-a
- us-test1-b - us-test1-b
- us-test1-c - us-test1-c

View File

@ -2,7 +2,7 @@ CloudProvider: hetzner
ClusterName: ha.example.com ClusterName: ha.example.com
Image: ubuntu-20.04 Image: ubuntu-20.04
KubernetesVersion: v1.25.0 KubernetesVersion: v1.25.0
MasterCount: 3 ControlPlaneCount: 3
NetworkCIDR: 10.0.0.0/16 NetworkCIDR: 10.0.0.0/16
Networking: cni Networking: cni
Zones: Zones:

View File

@ -1,7 +1,7 @@
ClusterName: ha.example.com ClusterName: ha.example.com
Zones: Zones:
- us-test-1a - us-test-1a
MasterCount: 3 ControlPlaneCount: 3
CloudProvider: aws CloudProvider: aws
Networking: cni Networking: cni
KubernetesVersion: v1.21.0 KubernetesVersion: v1.21.0

View File

@ -2,7 +2,7 @@ ClusterName: ha.example.com
Zones: Zones:
- us-test-1a - us-test-1a
- us-test-1b - us-test-1b
MasterCount: 5 ControlPlaneCount: 5
CloudProvider: aws CloudProvider: aws
Networking: cni Networking: cni
KubernetesVersion: v1.21.0 KubernetesVersion: v1.21.0

View File

@ -5,4 +5,4 @@ CloudProvider: aws
Networking: cni Networking: cni
KubernetesVersion: v1.26.0 KubernetesVersion: v1.26.0
NodeSize: m6g.xlarge NodeSize: m6g.xlarge
MasterSize: m6g.xlarge ControlPlaneSize: m6g.xlarge

View File

@ -8,7 +8,7 @@ Bastion: true
NodeSecurityGroups: NodeSecurityGroups:
- sg-exampleid - sg-exampleid
- sg-exampleid2 - sg-exampleid2
MasterSecurityGroups: ControlPlaneSecurityGroups:
- sg-exampleid3 - sg-exampleid3
- sg-exampleid4 - sg-exampleid4
KubernetesVersion: v1.21.0 KubernetesVersion: v1.21.0

View File

@ -8,11 +8,11 @@ Bastion: true
NodeSecurityGroups: NodeSecurityGroups:
- sg-exampleid - sg-exampleid
- sg-exampleid2 - sg-exampleid2
MasterSecurityGroups: ControlPlaneSecurityGroups:
- sg-exampleid3 - sg-exampleid3
- sg-exampleid4 - sg-exampleid4
KubernetesVersion: v1.21.0 KubernetesVersion: v1.21.0
cloudLabels: "Owner=John Doe,dn=\"cn=John Doe: dc=example dc=com\", foo/bar=fib+baz" cloudLabels: "Owner=John Doe,dn=\"cn=John Doe: dc=example dc=com\", foo/bar=fib+baz"
Project: testproject Project: testproject
GCEServiceAccount: test-account@testproject.iam.gserviceaccount.com GCEServiceAccount: test-account@testproject.iam.gserviceaccount.com
MasterSize: e2-standard-2 ControlPlaneSize: e2-standard-2

View File

@ -74,8 +74,8 @@ type NewClusterOptions struct {
CloudProvider string CloudProvider string
// Zones are the availability zones in which to run the cluster. // Zones are the availability zones in which to run the cluster.
Zones []string Zones []string
// MasterZones are the availability zones in which to run the masters. Defaults to the list in the Zones field. // ControlPlaneZones are the availability zones in which to run the control-plane nodes. Defaults to the list in the Zones field.
MasterZones []string ControlPlaneZones []string
// Project is the cluster's GCE project. // Project is the cluster's GCE project.
Project string Project string
@ -116,9 +116,9 @@ type NewClusterOptions struct {
AzureRouteTableName string AzureRouteTableName string
AzureAdminUser string AzureAdminUser string
// MasterCount is the number of masters to create. Defaults to the length of MasterZones // ControlPlaneCount is the number of control-plane nodes to create. Defaults to the length of ControlPlaneZones.
// if MasterZones is explicitly nonempty, otherwise defaults to 1. // if ControlPlaneZones is explicitly nonempty, otherwise defaults to 1.
MasterCount int32 ControlPlaneCount int32
// APIServerCount is the number of API servers to create. Defaults to 0. // APIServerCount is the number of API servers to create. Defaults to 0.
APIServerCount int32 APIServerCount int32
// EncryptEtcdStorage is whether to encrypt the etcd volumes. // EncryptEtcdStorage is whether to encrypt the etcd volumes.
@ -154,12 +154,12 @@ type NewClusterOptions struct {
// InstanceManager specifies which manager to use for managing instances. // InstanceManager specifies which manager to use for managing instances.
InstanceManager string InstanceManager string
Image string Image string
NodeImage string NodeImage string
MasterImage string ControlPlaneImage string
BastionImage string BastionImage string
MasterSize string ControlPlaneSize string
NodeSize string NodeSize string
} }
func (o *NewClusterOptions) InitDefaults() { func (o *NewClusterOptions) InitDefaults() {
@ -285,7 +285,7 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
} }
allZones := sets.NewString() allZones := sets.NewString()
allZones.Insert(opt.Zones...) allZones.Insert(opt.Zones...)
allZones.Insert(opt.MasterZones...) allZones.Insert(opt.ControlPlaneZones...)
if opt.CloudProvider == "" { if opt.CloudProvider == "" {
for _, zone := range allZones.List() { for _, zone := range allZones.List() {
@ -382,7 +382,7 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
return nil, err return nil, err
} }
masters, err := setupMasters(opt, &cluster, zoneToSubnetMap) controlPlanes, err := setupControlPlane(opt, &cluster, zoneToSubnetMap)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -420,7 +420,7 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
return nil, err return nil, err
} }
instanceGroups := append([]*api.InstanceGroup(nil), masters...) instanceGroups := append([]*api.InstanceGroup(nil), controlPlanes...)
instanceGroups = append(instanceGroups, apiservers...) instanceGroups = append(instanceGroups, apiservers...)
instanceGroups = append(instanceGroups, nodes...) instanceGroups = append(instanceGroups, nodes...)
instanceGroups = append(instanceGroups, bastions...) instanceGroups = append(instanceGroups, bastions...)
@ -445,7 +445,7 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
if g.Spec.MachineType == "" { if g.Spec.MachineType == "" {
g.Spec.MachineType, err = defaultMachineType(cloud, &cluster, ig) g.Spec.MachineType, err = defaultMachineType(cloud, &cluster, ig)
if err != nil { if err != nil {
return nil, fmt.Errorf("error assigning default machine type for masters: %v", err) return nil, fmt.Errorf("error assigning default machine type for control plane: %v", err)
} }
} }
@ -482,7 +482,7 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
if ig.IsControlPlane() { if ig.IsControlPlane() {
if len(ig.Spec.Subnets) == 0 { if len(ig.Spec.Subnets) == 0 {
return nil, fmt.Errorf("master InstanceGroup %s did not specify any Subnets", g.ObjectMeta.Name) return nil, fmt.Errorf("control-plane InstanceGroup %s did not specify any Subnets", g.ObjectMeta.Name)
} }
} else if ig.IsAPIServerOnly() && cluster.Spec.IsIPv6Only() { } else if ig.IsAPIServerOnly() && cluster.Spec.IsIPv6Only() {
if len(ig.Spec.Subnets) == 0 { if len(ig.Spec.Subnets) == 0 {
@ -811,52 +811,52 @@ func getOpenstackZoneToSubnetProviderID(spec *api.ClusterSpec, zones []string, s
return res, nil return res, nil
} }
func setupMasters(opt *NewClusterOptions, cluster *api.Cluster, zoneToSubnetMap map[string]*api.ClusterSubnetSpec) ([]*api.InstanceGroup, error) { func setupControlPlane(opt *NewClusterOptions, cluster *api.Cluster, zoneToSubnetMap map[string]*api.ClusterSubnetSpec) ([]*api.InstanceGroup, error) {
cloudProvider := cluster.Spec.GetCloudProvider() cloudProvider := cluster.Spec.GetCloudProvider()
var masters []*api.InstanceGroup var controlPlanes []*api.InstanceGroup
// Build the master subnets // Build the control-plane subnets.
// The master zones is the default set of zones unless explicitly set // The control-plane zones is the default set of zones unless explicitly set.
// The master count is the number of master zones unless explicitly set // The control-plane count is the number of control-plane zones unless explicitly set.
// We then round-robin around the zones // We then round-robin around the zones.
{ {
masterCount := opt.MasterCount controlPlaneCount := opt.ControlPlaneCount
masterZones := opt.MasterZones controlPlaneZones := opt.ControlPlaneZones
if len(masterZones) != 0 { if len(controlPlaneZones) != 0 {
if masterCount != 0 && masterCount < int32(len(masterZones)) { if controlPlaneCount != 0 && controlPlaneCount < int32(len(controlPlaneZones)) {
return nil, fmt.Errorf("specified %d master zones, but also requested %d masters. If specifying both, the count should match.", len(masterZones), masterCount) return nil, fmt.Errorf("specified %d control-plane zones, but also requested %d control-plane nodes. If specifying both, the count should match.", len(controlPlaneZones), controlPlaneCount)
} }
if masterCount == 0 { if controlPlaneCount == 0 {
// If master count is not specified, default to the number of master zones // If control-plane count is not specified, default to the number of control-plane zones
masterCount = int32(len(masterZones)) controlPlaneCount = int32(len(controlPlaneZones))
} }
} else { } else {
// masterZones not set; default to same as node Zones // controlPlaneZones not set; default to same as node Zones
masterZones = opt.Zones controlPlaneZones = opt.Zones
if masterCount == 0 { if controlPlaneCount == 0 {
// If master count is not specified, default to 1 // If control-plane count is not specified, default to 1
masterCount = 1 controlPlaneCount = 1
} }
} }
if len(masterZones) == 0 { if len(controlPlaneZones) == 0 {
// Should be unreachable // Should be unreachable
return nil, fmt.Errorf("cannot determine master zones") return nil, fmt.Errorf("cannot determine control-plane zones")
} }
for i := 0; i < int(masterCount); i++ { for i := 0; i < int(controlPlaneCount); i++ {
zone := masterZones[i%len(masterZones)] zone := controlPlaneZones[i%len(controlPlaneZones)]
name := zone name := zone
if cloudProvider == api.CloudProviderDO { if cloudProvider == api.CloudProviderDO {
if int(masterCount) >= len(masterZones) { if int(controlPlaneCount) >= len(controlPlaneZones) {
name += "-" + strconv.Itoa(1+(i/len(masterZones))) name += "-" + strconv.Itoa(1+(i/len(controlPlaneZones)))
} }
} else { } else {
if int(masterCount) > len(masterZones) { if int(controlPlaneCount) > len(controlPlaneZones) {
name += "-" + strconv.Itoa(1+(i/len(masterZones))) name += "-" + strconv.Itoa(1+(i/len(controlPlaneZones)))
} }
} }
@ -864,7 +864,7 @@ func setupMasters(opt *NewClusterOptions, cluster *api.Cluster, zoneToSubnetMap
g.Spec.Role = api.InstanceGroupRoleControlPlane g.Spec.Role = api.InstanceGroupRoleControlPlane
g.Spec.MinSize = fi.PtrTo(int32(1)) g.Spec.MinSize = fi.PtrTo(int32(1))
g.Spec.MaxSize = fi.PtrTo(int32(1)) g.Spec.MaxSize = fi.PtrTo(int32(1))
g.ObjectMeta.Name = "master-" + name g.ObjectMeta.Name = "control-plane-" + name
subnet := zoneToSubnetMap[zone] subnet := zoneToSubnetMap[zone]
if subnet == nil { if subnet == nil {
@ -891,33 +891,33 @@ func setupMasters(opt *NewClusterOptions, cluster *api.Cluster, zoneToSubnetMap
} }
} }
g.Spec.MachineType = opt.MasterSize g.Spec.MachineType = opt.ControlPlaneSize
g.Spec.Image = opt.MasterImage g.Spec.Image = opt.ControlPlaneImage
masters = append(masters, g) controlPlanes = append(controlPlanes, g)
} }
} }
// Build the Etcd clusters // Build the Etcd clusters
{ {
masterAZs := sets.NewString() controlPlaneAZs := sets.NewString()
duplicateAZs := false duplicateAZs := false
for _, ig := range masters { for _, ig := range controlPlanes {
zones, err := model.FindZonesForInstanceGroup(cluster, ig) zones, err := model.FindZonesForInstanceGroup(cluster, ig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, zone := range zones { for _, zone := range zones {
if masterAZs.Has(zone) { if controlPlaneAZs.Has(zone) {
duplicateAZs = true duplicateAZs = true
} }
masterAZs.Insert(zone) controlPlaneAZs.Insert(zone)
} }
} }
if duplicateAZs { if duplicateAZs {
klog.Warningf("Running with masters in the same AZs; redundancy will be reduced") klog.Warningf("Running with control-plane nodes in the same AZs; redundancy will be reduced")
} }
clusters := EtcdClusters clusters := EtcdClusters
@ -933,12 +933,12 @@ func setupMasters(opt *NewClusterOptions, cluster *api.Cluster, zoneToSubnetMap
encryptEtcdStorage = true encryptEtcdStorage = true
} }
for _, etcdCluster := range clusters { for _, etcdCluster := range clusters {
etcd := createEtcdCluster(etcdCluster, masters, encryptEtcdStorage, opt.EtcdStorageType) etcd := createEtcdCluster(etcdCluster, controlPlanes, encryptEtcdStorage, opt.EtcdStorageType)
cluster.Spec.EtcdClusters = append(cluster.Spec.EtcdClusters, etcd) cluster.Spec.EtcdClusters = append(cluster.Spec.EtcdClusters, etcd)
} }
} }
return masters, nil return controlPlanes, nil
} }
func trimCommonPrefix(names []string) []string { func trimCommonPrefix(names []string) []string {
@ -1358,7 +1358,7 @@ func setupAPI(opt *NewClusterOptions, cluster *api.Cluster) error {
cluster.Spec.API.LoadBalancer = &api.LoadBalancerAccessSpec{} cluster.Spec.API.LoadBalancer = &api.LoadBalancerAccessSpec{}
default: default:
return fmt.Errorf("unknown master topology type: %q", cluster.Spec.Topology.ControlPlane) return fmt.Errorf("unknown control-plane topology type: %q", cluster.Spec.Topology.ControlPlane)
} }
} }
@ -1421,7 +1421,7 @@ func initializeOpenstackAPI(opt *NewClusterOptions, cluster *api.Cluster) {
} }
} }
func createEtcdCluster(etcdCluster string, masters []*api.InstanceGroup, encryptEtcdStorage bool, etcdStorageType string) api.EtcdClusterSpec { func createEtcdCluster(etcdCluster string, controlPlanes []*api.InstanceGroup, encryptEtcdStorage bool, etcdStorageType string) api.EtcdClusterSpec {
etcd := api.EtcdClusterSpec{} etcd := api.EtcdClusterSpec{}
etcd.Name = etcdCluster etcd.Name = etcdCluster
@ -1440,17 +1440,18 @@ func createEtcdCluster(etcdCluster string, masters []*api.InstanceGroup, encrypt
etcd.MemoryRequest = &memoryRequest etcd.MemoryRequest = &memoryRequest
var names []string var names []string
for _, ig := range masters { for _, ig := range controlPlanes {
name := ig.ObjectMeta.Name name := ig.ObjectMeta.Name
// We expect the IG to have a `master-` prefix, but this is both superfluous // We expect the IG to have a `control-plane-` or `master-` prefix, but this is both superfluous
// and not how we named things previously // and not how we named things previously
name = strings.TrimPrefix(name, "control-plane-")
name = strings.TrimPrefix(name, "master-") name = strings.TrimPrefix(name, "master-")
names = append(names, name) names = append(names, name)
} }
names = trimCommonPrefix(names) names = trimCommonPrefix(names)
for i, ig := range masters { for i, ig := range controlPlanes {
m := api.EtcdMemberSpec{} m := api.EtcdMemberSpec{}
if encryptEtcdStorage { if encryptEtcdStorage {
m.EncryptedVolume = &encryptEtcdStorage m.EncryptedVolume = &encryptEtcdStorage