Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🌱 [WIP] [DNR] Reproduce clusterctl upgrade e2e test flake #8120

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,49 @@ limitations under the License.
package v1beta1

import (
"context"
"fmt"

apierrors "k8s.io/apimachinery/pkg/api/errors"
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

func (r *KubeadmConfigTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
WithDefaulter(&KubeadmConfigTemplateWebhook{}).
Complete()
}

// KubeadmConfigTemplateWebhook implements a custom defaulting webhook for KubeadmConfigTemplate.
// +kubebuilder:object:generate=false
type KubeadmConfigTemplateWebhook struct{}

// +kubebuilder:webhook:verbs=create;update,path=/mutate-bootstrap-cluster-x-k8s-io-v1beta1-kubeadmconfigtemplate,mutating=true,failurePolicy=fail,groups=bootstrap.cluster.x-k8s.io,resources=kubeadmconfigtemplates,versions=v1beta1,name=default.kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1

var _ webhook.Defaulter = &KubeadmConfigTemplate{}
var _ webhook.CustomDefaulter = &KubeadmConfigTemplateWebhook{}

// Default implements webhook.Defaulter so a webhook will be registered for the type.
func (r *KubeadmConfigTemplate) Default() {
DefaultKubeadmConfigSpec(&r.Spec.Template.Spec)
func (k KubeadmConfigTemplateWebhook) Default(ctx context.Context, raw runtime.Object) error {
obj, ok := raw.(*KubeadmConfigTemplate)
if !ok {
return apierrors.NewBadRequest(fmt.Sprintf("expected a KubeadmConfigTemplate but got a %T", obj))
}

req, err := admission.RequestFromContext(ctx)
if err != nil {
return apierrors.NewBadRequest(fmt.Sprintf("expected a admission.Request inside context: %v", err))
}

if req.UserInfo.Username != "kubernetes-admin" {
DefaultKubeadmConfigSpec(&obj.Spec.Template.Spec)
}

return nil
}

// +kubebuilder:webhook:verbs=create;update,path=/validate-bootstrap-cluster-x-k8s-io-v1beta1-kubeadmconfigtemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=bootstrap.cluster.x-k8s.io,resources=kubeadmconfigtemplates,versions=v1beta1,name=validation.kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
Expand Down
17 changes: 17 additions & 0 deletions bootstrap/kubeadm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ import (

// +kubebuilder:scaffold:imports
"github.com/spf13/pflag"
"go.uber.org/zap/zapcore"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/leaderelection/resourcelock"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/component-base/logs"
logsv1 "k8s.io/component-base/logs/api/v1"
logsjson "k8s.io/component-base/logs/json"
_ "k8s.io/component-base/logs/json/register"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -154,6 +156,21 @@ func main() {
os.Exit(1)
}

if logOptions.Format == logsv1.JSONLogFormat {
log, flush := logsjson.NewJSONLogger(logOptions.Verbosity, zapcore.Lock(logsjson.AddNopSync(os.Stderr)), nil, &zapcore.EncoderConfig{
MessageKey: "msg",
CallerKey: "caller",
NameKey: "logger",
TimeKey: "ts",
EncodeTime: func(_ time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(time.Now().Format("15:04:05.999Z07"))
},
EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
})
klog.SetLoggerWithOptions(log, klog.ContextualLogger(false), klog.FlushLogger(flush))
}

// klog.Background will automatically use the right logger.
ctrl.SetLogger(klog.Background())
if profilerAddress != "" {
Expand Down
12 changes: 6 additions & 6 deletions controlplane/kubeadm/internal/control_plane.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ func (c *ControlPlane) FailureDomainWithMostMachines(machines collections.Machin
}

// NextFailureDomainForScaleUp returns the failure domain with the fewest number of up-to-date machines.
func (c *ControlPlane) NextFailureDomainForScaleUp() *string {
func (c *ControlPlane) NextFailureDomainForScaleUp(ctx context.Context) *string {
if len(c.Cluster.Status.FailureDomains.FilterControlPlane()) == 0 {
return nil
}
return failuredomains.PickFewest(c.FailureDomains().FilterControlPlane(), c.UpToDateMachines())
return failuredomains.PickFewest(c.FailureDomains().FilterControlPlane(), c.UpToDateMachines(ctx))
}

// InitialControlPlaneConfig returns a new KubeadmConfigSpec that is to be used for an initializing control plane.
Expand Down Expand Up @@ -163,21 +163,21 @@ func (c *ControlPlane) GetKubeadmConfig(machineName string) (*bootstrapv1.Kubead
}

// MachinesNeedingRollout return a list of machines that need to be rolled out.
func (c *ControlPlane) MachinesNeedingRollout() collections.Machines {
func (c *ControlPlane) MachinesNeedingRollout(ctx context.Context) collections.Machines {
// Ignore machines to be deleted.
machines := c.Machines.Filter(collections.Not(collections.HasDeletionTimestamp))

// Return machines if they are scheduled for rollout or if with an outdated configuration.
return machines.Filter(
NeedsRollout(&c.reconciliationTime, c.KCP.Spec.RolloutAfter, c.KCP.Spec.RolloutBefore, c.infraResources, c.kubeadmConfigs, c.KCP),
NeedsRollout(ctx, &c.reconciliationTime, c.KCP.Spec.RolloutAfter, c.KCP.Spec.RolloutBefore, c.infraResources, c.kubeadmConfigs, c.KCP),
)
}

// UpToDateMachines returns the machines that are up to date with the control
// plane's configuration and therefore do not require rollout.
func (c *ControlPlane) UpToDateMachines() collections.Machines {
func (c *ControlPlane) UpToDateMachines(ctx context.Context) collections.Machines {
return c.Machines.Filter(
collections.Not(NeedsRollout(&c.reconciliationTime, c.KCP.Spec.RolloutAfter, c.KCP.Spec.RolloutBefore, c.infraResources, c.kubeadmConfigs, c.KCP)),
collections.Not(NeedsRollout(ctx, &c.reconciliationTime, c.KCP.Spec.RolloutAfter, c.KCP.Spec.RolloutBefore, c.infraResources, c.kubeadmConfigs, c.KCP)),
)
}

Expand Down
2 changes: 1 addition & 1 deletion controlplane/kubeadm/internal/controllers/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ func (r *KubeadmControlPlaneReconciler) reconcile(ctx context.Context, cluster *
}

// Control plane machines rollout due to configuration changes (e.g. upgrades) takes precedence over other operations.
needRollout := controlPlane.MachinesNeedingRollout()
needRollout := controlPlane.MachinesNeedingRollout(ctx)
switch {
case len(needRollout) > 0:
log.Info("Rolling out Control Plane machines", "needRollout", needRollout.Names())
Expand Down
4 changes: 2 additions & 2 deletions controlplane/kubeadm/internal/controllers/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (r *KubeadmControlPlaneReconciler) initializeControlPlane(ctx context.Conte
}

bootstrapSpec := controlPlane.InitialControlPlaneConfig()
fd := controlPlane.NextFailureDomainForScaleUp()
fd := controlPlane.NextFailureDomainForScaleUp(ctx)
if err := r.cloneConfigsAndGenerateMachine(ctx, cluster, kcp, bootstrapSpec, fd); err != nil {
logger.Error(err, "Failed to create initial control plane Machine")
r.recorder.Eventf(kcp, corev1.EventTypeWarning, "FailedInitialization", "Failed to create initial control plane Machine for cluster %s/%s control plane: %v", cluster.Namespace, cluster.Name, err)
Expand All @@ -75,7 +75,7 @@ func (r *KubeadmControlPlaneReconciler) scaleUpControlPlane(ctx context.Context,

// Create the bootstrap configuration
bootstrapSpec := controlPlane.JoinControlPlaneConfig()
fd := controlPlane.NextFailureDomainForScaleUp()
fd := controlPlane.NextFailureDomainForScaleUp(ctx)
if err := r.cloneConfigsAndGenerateMachine(ctx, cluster, kcp, bootstrapSpec, fd); err != nil {
logger.Error(err, "Failed to create additional control plane Machine")
r.recorder.Eventf(kcp, corev1.EventTypeWarning, "FailedScaleUp", "Failed to create additional control plane Machine for cluster %s/%s control plane: %v", cluster.Namespace, cluster.Name, err)
Expand Down
2 changes: 1 addition & 1 deletion controlplane/kubeadm/internal/controllers/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (r *KubeadmControlPlaneReconciler) updateStatus(ctx context.Context, kcp *c
log.Error(err, "failed to initialize control plane")
return err
}
kcp.Status.UpdatedReplicas = int32(len(controlPlane.UpToDateMachines()))
kcp.Status.UpdatedReplicas = int32(len(controlPlane.UpToDateMachines(ctx)))

replicas := int32(len(ownedMachines))
desiredReplicas := *kcp.Spec.Replicas
Expand Down
Loading