Skip to content

Commit dd36bc0

Browse files
committed
Introduce --reconcile flag to kOps
Kubernetes 1.31 now stops nodes joining a cluster if the minor version of the node is greater than the minor version of the control plane. The addition of the instance-group-roles flag to update means that we can now update / rolling-update the control plane first. However, we must now issue four commands: * Update control plane * Rolling update control plane * Update nodes * Rolling update nodes This adds a flag to automate this process. It is implemented by executing those 4 steps in sequence. Update is also smart enough to not update the nodes if this would violate the skew policy, but we do this explicitly in the reconcile command to be clearer and safer.
1 parent 3a8a13f commit dd36bc0

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

cmd/kops/reconcile_cluster.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"io"
23+
24+
"k8s.io/kops/cmd/kops/util"
25+
"k8s.io/kops/pkg/apis/kops"
26+
)
27+
28+
// ReconcileCluster updates the cluster to the desired state, including rolling updates where necessary.
29+
// To respect skew policy, it updates the control plane first, then updates the nodes.
30+
// "update" is probably now smart enough to automatically not update the control plane if it is already at the desired version,
31+
// but we do it explicitly here to be clearer / safer.
32+
func ReconcileCluster(ctx context.Context, f *util.Factory, out io.Writer, c *UpdateClusterOptions) error {
33+
fmt.Fprintf(out, "Updating control plane configuration\n")
34+
{
35+
opt := *c
36+
opt.Reconcile = false // Prevent infinite loop
37+
opt.InstanceGroupRoles = []string{
38+
string(kops.InstanceGroupRoleAPIServer),
39+
string(kops.InstanceGroupRoleControlPlane),
40+
}
41+
if _, err := RunUpdateCluster(ctx, f, out, &opt); err != nil {
42+
return err
43+
}
44+
}
45+
46+
fmt.Fprintf(out, "Doing rolling-update for control plane\n")
47+
{
48+
opt := &RollingUpdateOptions{}
49+
opt.InitDefaults()
50+
opt.ClusterName = c.ClusterName
51+
opt.InstanceGroupRoles = []string{
52+
string(kops.InstanceGroupRoleAPIServer),
53+
string(kops.InstanceGroupRoleControlPlane),
54+
}
55+
opt.Yes = c.Yes
56+
if err := RunRollingUpdateCluster(ctx, f, out, opt); err != nil {
57+
return err
58+
}
59+
}
60+
61+
fmt.Fprintf(out, "Updating node configuration\n")
62+
{
63+
opt := *c
64+
opt.Reconcile = false // Prevent infinite loop
65+
// Do all roles this time, though we only expect changes to node & bastion roles
66+
opt.InstanceGroupRoles = nil
67+
if _, err := RunUpdateCluster(ctx, f, out, &opt); err != nil {
68+
return err
69+
}
70+
}
71+
72+
fmt.Fprintf(out, "Doing rolling-update for nodes\n")
73+
{
74+
opt := &RollingUpdateOptions{}
75+
opt.InitDefaults()
76+
opt.ClusterName = c.ClusterName
77+
// Do all roles this time, though we only expect changes to node & bastion roles
78+
opt.InstanceGroupRoles = nil
79+
opt.Yes = c.Yes
80+
if err := RunRollingUpdateCluster(ctx, f, out, opt); err != nil {
81+
return err
82+
}
83+
}
84+
85+
return nil
86+
}

cmd/kops/update_cluster.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ type UpdateClusterOptions struct {
103103
// The goal is that the cluster can keep running even during more disruptive
104104
// infrastructure changes.
105105
Prune bool
106+
107+
// Reconcile is true if we should reconcile the cluster by rolling the control plane and nodes sequentially
108+
Reconcile bool
106109
}
107110

108111
func (o *UpdateClusterOptions) InitDefaults() {
@@ -117,6 +120,7 @@ func (o *UpdateClusterOptions) InitDefaults() {
117120
o.CreateKubecfg = true
118121

119122
o.Prune = false
123+
o.Reconcile = false
120124

121125
o.RunTasksOptions.InitDefaults()
122126
}
@@ -193,6 +197,16 @@ type UpdateClusterResults struct {
193197
}
194198

195199
func RunUpdateCluster(ctx context.Context, f *util.Factory, out io.Writer, c *UpdateClusterOptions) (*UpdateClusterResults, error) {
200+
if c.Reconcile {
201+
if !c.Yes {
202+
return nil, fmt.Errorf("--reconcile is only supported with --yes")
203+
}
204+
if c.Target == cloudup.TargetTerraform {
205+
return nil, fmt.Errorf("--reconcile is not supported with terraform")
206+
}
207+
return nil, ReconcileCluster(ctx, f, out, c)
208+
}
209+
196210
results := &UpdateClusterResults{}
197211

198212
isDryrun := false

docs/cli/kops_update_cluster.md

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)