Skip to content

Commit

Permalink
Restructure the update of LBM Conditions
Browse files Browse the repository at this point in the history
Signed-off-by: Felix Breuer <fbreuer@pm.me>
  • Loading branch information
breuerfelix committed May 30, 2023
1 parent 5314b45 commit 22ea777
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 177 deletions.
117 changes: 67 additions & 50 deletions controllers/yawollet/loadbalancer_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import (

"github.com/envoyproxy/go-control-plane/pkg/resource/v3"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -47,100 +49,115 @@ func (r *LoadBalancerReconciler) Reconcile(ctx context.Context, req ctrl.Request
}

lb := &yawolv1beta1.LoadBalancer{}
err := r.Client.Get(ctx, req.NamespacedName, lb)
if err != nil {
if err := r.Client.Get(ctx, req.NamespacedName, lb); err != nil {
return ctrl.Result{}, err
}

lbm := &yawolv1beta1.LoadBalancerMachine{}
err = r.Client.Get(ctx, client.ObjectKey{Name: r.LoadbalancerMachineName, Namespace: req.Namespace}, lbm)
if err := r.Client.Get(
ctx, client.ObjectKey{Name: r.LoadbalancerMachineName, Namespace: req.Namespace}, lbm,
); err != nil {
return ctrl.Result{}, err
}

conditions := map[corev1.NodeConditionType]corev1.NodeCondition{}
if lbm.Status.Conditions != nil {
for _, v := range *lbm.Status.Conditions {
conditions[v.Type] = *v.DeepCopy()
}
}

err := r.reconcile(ctx, lb, lbm, conditions)

metricString, err := helper.GetMetricString(r.KeepalivedStatsFile)
if err != nil {
return ctrl.Result{}, err
}

conditionString, err := helper.GetLBMConditionString(conditions)
if err != nil {
return ctrl.Result{}, err
}

patch := []byte(`{ "status": { "conditions": ` + conditionString + `, "metrics": ` + metricString + `}}`)
if err := r.Client.Status().Patch(ctx, lbm, client.RawPatch(types.MergePatchType, patch)); err != nil {
return ctrl.Result{}, err
}

return ctrl.Result{RequeueAfter: time.Duration(r.RequeueTime) * time.Second}, err
}

func (r *LoadBalancerReconciler) reconcile(
ctx context.Context,
lb *yawolv1beta1.LoadBalancer,
lbm *yawolv1beta1.LoadBalancerMachine,
conditions map[corev1.NodeConditionType]corev1.NodeCondition,
) error {
// enable ad hoc debugging if configured
if err := helper.EnableAdHocDebugging(lb, lbm, r.Recorder, r.LoadbalancerMachineName); err != nil {
return ctrl.Result{}, kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to get current snapshot", err), lbm)
return kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to get current snapshot", err), lbm)
}

// current snapshot
oldSnapshot, err := r.EnvoyCache.GetSnapshot("lb-id")
if err != nil {
return ctrl.Result{}, kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to get current snapshot", err), lbm)
return kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to get current snapshot", err), lbm)
}

// create new snapshot
changed, snapshot, err := helper.CreateEnvoyConfig(r.RecorderLB, oldSnapshot, lb, r.ListenAddress)
if err != nil {
_ = helper.UpdateLBMConditions(ctx, r.Status(), lbm,
helper.ConfigReady, helper.ConditionFalse, "EnvoyConfigurationFailed", "new snapshot cant create successful")
return ctrl.Result{}, kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to create new snapshot", err), lbm)
helper.UpdateLBMConditions(
conditions, helper.ConfigReady, helper.ConditionFalse, "EnvoyConfigurationFailed", "new snapshot cant create successful",
)
return kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to create new snapshot", err), lbm)
}

// update envoy snapshot if changed
if changed {
if err = snapshot.Consistent(); err != nil {
_ = helper.UpdateLBMConditions(ctx, r.Status(), lbm,
helper.ConfigReady, helper.ConditionFalse, "EnvoyConfigurationFailed", "new snapshot is not Consistent")
return ctrl.Result{}, kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: new snapshot is not consistent", err), lbm)
if err := snapshot.Consistent(); err != nil {
helper.UpdateLBMConditions(
conditions, helper.ConfigReady, helper.ConditionFalse, "EnvoyConfigurationFailed", "new snapshot is not Consistent",
)
return kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: new snapshot is not consistent", err), lbm)
}

err = r.EnvoyCache.SetSnapshot(ctx, "lb-id", &snapshot)
if err != nil {
_ = helper.UpdateLBMConditions(ctx, r.Status(), lbm,
helper.ConfigReady, helper.ConditionFalse, "EnvoyConfigurationFailed", "new snapshot cant set to envoy envoycache")
return ctrl.Result{}, kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to set new snapshot", err), lbm)
}
err = helper.UpdateLBMConditions(ctx, r.Status(), lbm,
helper.ConfigReady, helper.ConditionTrue, "EnvoyConfigurationUpToDate", "envoy config is successfully updated")
if err != nil {
return ctrl.Result{}, err
if err := r.EnvoyCache.SetSnapshot(ctx, "lb-id", &snapshot); err != nil {
helper.UpdateLBMConditions(
conditions, helper.ConfigReady, helper.ConditionFalse, "EnvoyConfigurationFailed", "new snapshot cant set to envoy envoycache",
)
return kubernetes.SendErrorAsEvent(r.Recorder, fmt.Errorf("%w: unable to set new snapshot", err), lbm)
}

helper.UpdateLBMConditions(
conditions, helper.ConfigReady, helper.ConditionTrue, "EnvoyConfigurationUpToDate", "envoy config is successfully updated",
)

r.Log.Info("Envoy snapshot updated", "snapshot version", snapshot.GetVersion(resource.ClusterType))
r.Recorder.Event(lbm,
"Normal",
"Update",
fmt.Sprintf("Envoy is updated to new snapshot version: %v", snapshot.GetVersion(resource.ClusterType)))
} else {
err = helper.UpdateLBMConditions(ctx, r.Status(), lbm,
helper.ConfigReady, helper.ConditionTrue, "EnvoyConfigurationCreated", "envoy config is already up to date")
if err != nil {
return ctrl.Result{}, err
}
helper.UpdateLBMConditions(
conditions, helper.ConfigReady, helper.ConditionTrue, "EnvoyConfigurationCreated", "envoy config is already up to date",
)
}

// update envoy status condition
err = helper.UpdateEnvoyStatus(ctx, r.Status(), lbm)
if err != nil {
return ctrl.Result{}, err
}
helper.UpdateEnvoyStatus(conditions)

// check envoy snapshot and update condition
if changed {
err = helper.CheckEnvoyVersion(ctx, r.Status(), lbm, &snapshot)
if err != nil {
return ctrl.Result{}, err
}
helper.CheckEnvoyVersion(conditions, &snapshot)
} else {
err = helper.CheckEnvoyVersion(ctx, r.Status(), lbm, oldSnapshot)
if err != nil {
return ctrl.Result{}, err
}
helper.CheckEnvoyVersion(conditions, oldSnapshot)
}

// update keepalived status condition
err = helper.UpdateKeepalivedStatus(ctx, r.Status(), r.KeepalivedStatsFile, lbm)
if err != nil {
return ctrl.Result{}, err
}

// update Metrics
err = helper.WriteLBMMetrics(ctx, r.Status(), r.KeepalivedStatsFile, lbm)
if err != nil {
return ctrl.Result{}, err
}
helper.UpdateKeepalivedStatus(conditions, r.KeepalivedStatsFile)

return ctrl.Result{RequeueAfter: time.Duration(r.RequeueTime) * time.Second}, nil
return nil
}

// SetupWithManager is used by kubebuilder to init the controller loop
Expand Down
Loading

0 comments on commit 22ea777

Please sign in to comment.