anvil-verifier/anvil

Reconciliation workflow related to `.status`

marshtompsxd opened this issue · 0 comments

Zookeeper

The status of the cr object:

// ZookeeperClusterStatus defines the observed state of ZookeeperCluster
type ZookeeperClusterStatus struct {
	// Members is the zookeeper members in the cluster
	Members MembersStatus `json:"members,omitempty"`

	// Replicas is the number of number of desired replicas in the cluster
	Replicas int32 `json:"replicas,omitempty"`

	// ReadyReplicas is the number of number of ready replicas in the cluster
	ReadyReplicas int32 `json:"readyReplicas,omitempty"`

	// InternalClientEndpoint is the internal client IP and port
	InternalClientEndpoint string `json:"internalClientEndpoint,omitempty"`

	// ExternalClientEndpoint is the internal client IP and port
	ExternalClientEndpoint string `json:"externalClientEndpoint,omitempty"`

	MetaRootCreated bool `json:"metaRootCreated,omitempty"`

	// CurrentVersion is the current cluster version
	CurrentVersion string `json:"currentVersion,omitempty"`

	TargetVersion string `json:"targetVersion,omitempty"`

	// Conditions list all the applied conditions
	Conditions []ClusterCondition `json:"conditions,omitempty"`
}

Some of the fields above come from the status of other objects. Like ReadyReplicas comes from the stateful set object's status.

Meanwhile, the status of other state objects also affects the controller's behavior. In each reconciliation round, the controller checks whether all the zookeeper replicas are up-to-date by checking the stateful set's .Status.UpdateRevision and .Status.CurrentRevision. If the two are inconsistent for more than 10 minutes, meaning the upgrading lasts for that long time, then the controller will mark this upgrading as failed (in its .Status.Conditions). If the upgrading is marked as failed, the controller will stop updating the stateful set object even if new changes from the CR come. The upgrading failure mark will be resolved soon as .Status.UpdateRevision becomes the same as .Status.CurrentRevision, and then the controller can continue to update the stateful set. See:

func (r *ZookeeperClusterReconciler) upgradeStatefulSet(instance *zookeeperv1beta1.ZookeeperCluster, foundSts *appsv1.StatefulSet) (err error) {
    ...
    // Setting the upgrade condition to true to trigger the upgrade
    // When the zk cluster is upgrading Statefulset CurrentRevision and UpdateRevision are not equal and zk cluster image tag is not equal to CurrentVersion
    ...
    // checking if the upgrade is in progress
    if upgradeCondition.Status == corev1.ConditionTrue {
        ...
        // updating the upgradecondition if upgrade is in progress
        if foundSts.Status.CurrentRevision != foundSts.Status.UpdateRevision {
            ...
            err = checkSyncTimeout(instance, zookeeperv1beta1.UpdatingZookeeperReason, foundSts.Status.UpdatedReplicas, 10*time.Minute)
            if err != nil {
                instance.Status.SetErrorConditionTrue("UpgradeFailed", err.Error())
                return r.Client.Status().Update(context.TODO(), instance)
            }
            ...
        }
    }
    ...
}

func (r *ZookeeperClusterReconciler) reconcileStatefulSet(instance *zookeeperv1beta1.ZookeeperCluster) (err error) {
    // we cannot upgrade if cluster is in UpgradeFailed
    if instance.Status.IsClusterInUpgradeFailedState() {
        return nil
    }
    ...
}

Rabbitmq

The status of the cr object:

// Status presents the observed state of RabbitmqCluster
type RabbitmqClusterStatus struct {
	// Set of Conditions describing the current state of the RabbitmqCluster
	Conditions []status.RabbitmqClusterCondition `json:"conditions"`

	// Identifying information on internal resources
	DefaultUser *RabbitmqClusterDefaultUser `json:"defaultUser,omitempty"`

	// Binding exposes a secret containing the binding information for this
	// RabbitmqCluster. It implements the service binding Provisioned Service
	// duck type. See: https://github.com/servicebinding/spec#provisioned-service
	Binding *corev1.LocalObjectReference `json:"binding,omitempty"`

	// observedGeneration is the most recent successful generation observed for this RabbitmqCluster. It corresponds to the
	// RabbitmqCluster's generation, which is updated on mutation by the API Server.
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

The rabbitmq controller checks the status of the stateful set object to see if all replicas are ready and updated before running rabbitmq commands (commands for rebalance or reset plugins). See:

func allReplicasReadyAndUpdated(sts *appsv1.StatefulSet) bool {
    return sts.Status.ReadyReplicas == *sts.Spec.Replicas && !statefulSetBeingUpdated(sts)
}

func statefulSetBeingUpdated(sts *appsv1.StatefulSet) bool {
    return sts.Status.CurrentRevision != sts.Status.UpdateRevision
}

func (r *RabbitmqClusterReconciler) runRabbitmqCLICommandsIfAnnotated(ctx context.Context, rmq *rabbitmqv1beta1.RabbitmqCluster) (requeueAfter time.Duration, err error) {
    logger := ctrl.LoggerFrom(ctx)
    sts, err := r.statefulSet(ctx, rmq)
    if err != nil {
        return 0, err
    }
    if !allReplicasReadyAndUpdated(sts) {
        logger.V(1).Info("not all replicas ready yet; requeuing request to run RabbitMQ CLI commands")
        return 15 * time.Second, nil
    }
     ...
}

Fluent

It does not have any status:

// FluentBitStatus defines the observed state of FluentBit
type FluentBitStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file
}

and does not check the status of other objects.