Skip to content

Commit 6bf9c24

Browse files
committed
Allow running with 0 worker nodes
1 parent 200ce48 commit 6bf9c24

File tree

5 files changed

+45
-26
lines changed

5 files changed

+45
-26
lines changed

pkg/apis/kops/validation/legacy.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,6 @@ func DeepValidate(c *kops.Cluster, groups []*kops.InstanceGroup, strict bool, vf
274274
return fmt.Errorf("must configure at least one ControlPlane InstanceGroup")
275275
}
276276

277-
if nodeGroupCount == 0 {
278-
return fmt.Errorf("must configure at least one Node InstanceGroup")
279-
}
280-
281277
for _, g := range groups {
282278
errs := CrossValidateInstanceGroup(g, c, cloud, strict)
283279

upup/models/cloudup/resources/addons/coredns.addons.k8s.io/k8s-1.12.yaml.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ spec:
138138
- key: "CriticalAddonsOnly"
139139
operator: "Exists"
140140
{{- end }}
141-
{{- if KarpenterEnabled }}
141+
{{- if or IsControlPlaneOnly KarpenterEnabled }}
142142
- key: node-role.kubernetes.io/master
143143
operator: Exists
144144
- key: node-role.kubernetes.io/control-plane

upup/pkg/fi/cloudup/deepvalidate_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ func TestDeepValidate_NoNodeZones(t *testing.T) {
4444
c := buildDefaultCluster(t)
4545
var groups []*kopsapi.InstanceGroup
4646
groups = append(groups, buildMinimalMasterInstanceGroup("subnet-us-test-1a"))
47-
expectErrorFromDeepValidate(t, c, groups, "must configure at least one Node InstanceGroup")
47+
err := validation.DeepValidate(c, groups, true, vfs.Context, nil)
48+
if err != nil {
49+
t.Fatalf("Expected no error from DeepValidate, got %v", err)
50+
}
4851
}
4952

5053
func TestDeepValidate_NoMasterZones(t *testing.T) {

upup/pkg/fi/cloudup/new_cluster.go

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ func (o *NewClusterOptions) InitDefaults() {
176176
o.AdminAccess = []string{"0.0.0.0/0", "::/0"}
177177
o.EtcdClusters = []string{"main", "events"}
178178
o.Networking = "cilium"
179+
o.NodeCount = 1
179180
o.InstanceManager = "cloudgroups"
180181

181182
// Azure-specific
@@ -416,26 +417,27 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
416417
}
417418

418419
var nodes []*api.InstanceGroup
419-
420-
switch opt.InstanceManager {
421-
case "karpenter":
422-
if opt.DiscoveryStore == "" {
423-
return nil, fmt.Errorf("karpenter requires --discovery-store")
424-
}
425-
cluster.Spec.Karpenter = &api.KarpenterConfig{
426-
Enabled: true,
427-
}
428-
nodes, err = setupKarpenterNodes(cluster)
429-
if err != nil {
430-
return nil, err
431-
}
432-
case "cloudgroups":
433-
nodes, err = setupNodes(opt, cluster, zoneToSubnetsMap)
434-
if err != nil {
435-
return nil, err
420+
if opt.NodeCount > 0 {
421+
switch opt.InstanceManager {
422+
case "karpenter":
423+
if opt.DiscoveryStore == "" {
424+
return nil, fmt.Errorf("karpenter requires --discovery-store")
425+
}
426+
cluster.Spec.Karpenter = &api.KarpenterConfig{
427+
Enabled: true,
428+
}
429+
nodes, err = setupKarpenterNodes(cluster)
430+
if err != nil {
431+
return nil, err
432+
}
433+
case "cloudgroups":
434+
nodes, err = setupNodes(opt, cluster, zoneToSubnetsMap)
435+
if err != nil {
436+
return nil, err
437+
}
438+
default:
439+
return nil, fmt.Errorf("invalid value %q for --instance-manager", opt.InstanceManager)
436440
}
437-
default:
438-
return nil, fmt.Errorf("invalid value %q for --instance-manager", opt.InstanceManager)
439441
}
440442

441443
apiservers, err := setupAPIServers(opt, cluster, zoneToSubnetsMap)
@@ -1080,7 +1082,7 @@ func setupNodes(opt *NewClusterOptions, cluster *api.Cluster, zoneToSubnetsMap m
10801082
// We then divvy up amongst the zones
10811083
numZones := len(opt.Zones)
10821084
nodeCount := opt.NodeCount
1083-
if nodeCount == 0 {
1085+
if nodeCount == 1 {
10841086
// If node count is not specified, default to the number of zones
10851087
nodeCount = int32(numZones)
10861088
}

upup/pkg/fi/cloudup/template_functions.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap, secretStore fi.SecretS
399399

400400
dest["ParseTaint"] = util.ParseTaint
401401

402+
dest["IsControlPlaneOnly"] = tf.IsControlPlaneOnly
403+
402404
dest["KarpenterEnabled"] = func() bool {
403405
return cluster.Spec.Karpenter != nil && cluster.Spec.Karpenter.Enabled
404406
}
@@ -511,6 +513,22 @@ func (tf *TemplateFunctions) HasHighlyAvailableControlPlane() bool {
511513
return false
512514
}
513515

516+
// IsControlPlaneOnly returns true if the cluster has only control plane node(s). False otherwise.
517+
func (tf *TemplateFunctions) IsControlPlaneOnly() bool {
518+
var cp, wn int
519+
for _, ig := range tf.InstanceGroups {
520+
switch ig.Spec.Role {
521+
case kops.InstanceGroupRoleControlPlane:
522+
cp++
523+
case kops.InstanceGroupRoleNode:
524+
wn++
525+
default:
526+
// Ignore Bastion and APIServer
527+
}
528+
}
529+
return cp > 0 && wn == 0
530+
}
531+
514532
// CloudControllerConfigArgv returns the args to external cloud controller
515533
func (tf *TemplateFunctions) CloudControllerConfigArgv() ([]string, error) {
516534
cluster := tf.Cluster

0 commit comments

Comments
 (0)