Skip to content

Commit

Permalink
fix: do not allow scaling down controlplane to zero
Browse files Browse the repository at this point in the history
Doing that is pretty pointless as it's going to destroy a cluster.
Instead of doing that cluster should be deleted and recreated.

And with the new approach without init nodes scaling cluster back up
won't be able to succeed as bootstrap is done only a single time.

Still allowing user to set replicas to zero, but block scaling in the
controller with error messages when there's only a single node
remaining.

Signed-off-by: Artem Chernyshev <artem.chernyshev@talos-systems.com>
  • Loading branch information
Unix4ever committed Nov 26, 2021
1 parent 8a73e6a commit a24dad3
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
8 changes: 8 additions & 0 deletions controllers/taloscontrolplane_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ func (r *TalosControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Re
"Scaling down control plane to %d replicas (actual %d)",
desiredReplicas, numMachines)

if numMachines == 1 {
conditions.MarkFalse(tcp, controlplanev1.ResizedCondition, controlplanev1.ScalingDownReason, clusterv1.ConditionSeverityError,
"Cannot scale down control plane nodes to 0",
desiredReplicas, numMachines)

return res, nil
}

if err := r.ensureNodesBooted(ctx, cluster, ownedMachines); err != nil {
logger.Info("Waiting for all nodes to finish boot sequence", "error", err)

Expand Down
41 changes: 41 additions & 0 deletions internal/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ import (
"gopkg.in/yaml.v3"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
clusterv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
logf "sigs.k8s.io/cluster-api/cmd/clusterctl/log"
"sigs.k8s.io/cluster-api/util/conditions"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"

controlplanev1 "github.com/talos-systems/cluster-api-control-plane-provider-talos/api/v1alpha3"
)

var (
Expand Down Expand Up @@ -286,6 +290,43 @@ func (suite *IntegrationSuite) Test04ScaleControlPlaneNoWait() {
suite.Require().NoError(err)
}

// Test05ScaleControlPlaneToZero try to scale control plane to zero and check that it never does that.
func (suite *IntegrationSuite) Test05ScaleControlPlaneToZero() {
ctx, cancel := context.WithCancel(suite.ctx)

go func() {
time.Sleep(time.Second * 5)

cancel()
}()

suite.cluster.Scale(ctx, 0, capi.ControlPlaneNodes) //nolint:errcheck

err := retry.Constant(time.Second*20, retry.WithUnits(time.Second)).Retry(func() error {
controlplane, err := suite.cluster.ControlPlanes(suite.ctx)
if err != nil {
return err
}

var tcp controlplanev1.TalosControlPlane

err = runtime.DefaultUnstructuredConverter.
FromUnstructured(controlplane.UnstructuredContent(), &tcp)
if err != nil {
return err
}

if !conditions.Has(&tcp, controlplanev1.ResizedCondition) &&
conditions.GetMessage(&tcp, controlplanev1.ResizedCondition) != "Cannot scale down control plane nodes to 0" {
return retry.ExpectedErrorf("node resized conditions error status hasn't updated")
}

return nil
})

suite.Require().NoError(err)
}

// TestIntegration runs integration tests.
func TestIntegration(t *testing.T) {
version := os.Getenv("WORKLOAD_TALOS_VERSION")
Expand Down

0 comments on commit a24dad3

Please sign in to comment.