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

@ -63,7 +63,7 @@ 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
@ -71,7 +71,7 @@ type CreateClusterOptions struct {
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
@ -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.
@ -156,9 +156,9 @@ type NewClusterOptions struct {
Image string Image string
NodeImage string NodeImage string
MasterImage string ControlPlaneImage string
BastionImage string BastionImage string
MasterSize string ControlPlaneSize string
NodeSize string NodeSize string
} }
@ -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