Skip to content

Commit

Permalink
Merge pull request radondb#264 from runkecheng/add_state
Browse files Browse the repository at this point in the history
*: Make the cluster state cover more scenarios. radondb#253
  • Loading branch information
andyli029 authored Oct 18, 2021
2 parents 502994f + 36e7a4d commit 68d361e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 19 deletions.
32 changes: 25 additions & 7 deletions api/v1alpha1/mysqlcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,16 +242,34 @@ type Persistence struct {
Size string `json:"size,omitempty"`
}

// ClusterState defines cluster state.
type ClusterState string

const (
// ClusterInitState indicates whether the cluster is initializing.
ClusterInitState ClusterState = "Initializing"
// ClusterUpdateState indicates whether the cluster is being updated.
ClusterUpdateState ClusterState = "Updating"
// ClusterReadyState indicates whether all containers in the pod are ready.
ClusterReadyState ClusterState = "Ready"
// ClusterCloseState indicates whether the cluster is closed.
ClusterCloseState ClusterState = "Closed"
)

// ClusterConditionType defines type for cluster condition type.
type ClusterConditionType string

const (
// ClusterInit indicates whether the cluster is initializing.
ClusterInit ClusterConditionType = "Initializing"
// ClusterReady indicates whether all containers in the pod are ready.
ClusterReady ClusterConditionType = "Ready"
// ClusterError indicates whether the cluster encountered an error.
ClusterError ClusterConditionType = "Error"
// ConditionInit indicates whether the cluster is initializing.
ConditionInit ClusterConditionType = "Initializing"
// ConditionUpdate indicates whether the cluster is being updated.
ConditionUpdate ClusterConditionType = "Updating"
// ConditionReady indicates whether all containers in the pod are ready.
ConditionReady ClusterConditionType = "Ready"
// ConditionClose indicates whether the cluster is closed.
ConditionClose ClusterConditionType = "Closed"
// ConditionError indicates whether there is an error in the cluster.
ConditionError ClusterConditionType = "Error"
)

// ClusterCondition defines type for cluster conditions.
Expand Down Expand Up @@ -321,7 +339,7 @@ type MysqlClusterStatus struct {
// ReadyNodes represents number of the nodes that are in ready state.
ReadyNodes int `json:"readyNodes,omitempty"`
// State
State ClusterConditionType `json:"state,omitempty"`
State ClusterState `json:"state,omitempty"`
// Conditions contains the list of the cluster conditions fulfilled.
Conditions []ClusterCondition `json:"conditions,omitempty"`
// Nodes contains the list of the node status fulfilled.
Expand Down
1 change: 1 addition & 0 deletions mysqlcluster/syncer/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ func (s *StatefulSetSyncer) applyNWait(ctx context.Context, pod *corev1.Pod) err
if pod.ObjectMeta.Labels["controller-revision-hash"] == s.sfs.Status.UpdateRevision {
log.Info("pod is already updated", "pod name", pod.Name)
} else {
s.Status.State = apiv1alpha1.ClusterUpdateState
log.Info("updating pod", "pod", pod.Name, "key", s.Unwrap())
if pod.DeletionTimestamp != nil {
log.Info("pod is being deleted", "pod", pod.Name, "key", s.Unwrap())
Expand Down
55 changes: 43 additions & 12 deletions mysqlcluster/syncer/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,7 @@ func (s *StatusSyncer) GetOwner() runtime.Object { return s.MysqlCluster }

// Sync persists data into the external store.
func (s *StatusSyncer) Sync(ctx context.Context) (syncer.SyncResult, error) {
clusterCondition := apiv1alpha1.ClusterCondition{
Type: apiv1alpha1.ClusterInit,
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.NewTime(time.Now()),
}
s.Status.State = apiv1alpha1.ClusterInit
clusterCondition := s.updateClusterStatus()

list := corev1.PodList{}
err := s.cli.List(
Expand All @@ -109,23 +104,24 @@ func (s *StatusSyncer) Sync(ctx context.Context) (syncer.SyncResult, error) {
}
case corev1.PodScheduled:
if cond.Reason == corev1.PodReasonUnschedulable {
// When an error occurs, it is first recorded in the condition,
// but the cluster status is not updated immediately.
clusterCondition = apiv1alpha1.ClusterCondition{
Type: apiv1alpha1.ClusterError,
Type: apiv1alpha1.ConditionError,
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.NewTime(time.Now()),
Reason: corev1.PodReasonUnschedulable,
Message: cond.Message,
}
s.Status.State = apiv1alpha1.ClusterError
}
}
}
}

s.Status.ReadyNodes = len(readyNodes)
if s.Status.ReadyNodes == int(*s.Spec.Replicas) {
s.Status.State = apiv1alpha1.ClusterReady
clusterCondition.Type = apiv1alpha1.ClusterReady
if s.Status.ReadyNodes == int(*s.Spec.Replicas) && int(*s.Spec.Replicas) != 0 {
s.Status.State = apiv1alpha1.ClusterReadyState
clusterCondition.Type = apiv1alpha1.ConditionReady
}

if len(s.Status.Conditions) == 0 {
Expand All @@ -140,10 +136,45 @@ func (s *StatusSyncer) Sync(ctx context.Context) (syncer.SyncResult, error) {
s.Status.Conditions = s.Status.Conditions[len(s.Status.Conditions)-maxStatusesQuantity:]
}

// update ready nodes' status.
// Update ready nodes' status.
return syncer.SyncResult{}, s.updateNodeStatus(ctx, s.cli, readyNodes)
}

// updateClusterStatus update the cluster status and returns condition.
func (s *StatusSyncer) updateClusterStatus() apiv1alpha1.ClusterCondition {
clusterCondition := apiv1alpha1.ClusterCondition{
Type: apiv1alpha1.ConditionInit,
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.NewTime(time.Now()),
}

oldState := s.Status.State
// If the state does not exist, the cluster is being initialized.
if oldState == "" {
s.Status.State = apiv1alpha1.ClusterInitState
return clusterCondition
}
// If the expected number of replicas and the actual number
// of replicas are both 0, the cluster has been closed.
if int(*s.Spec.Replicas) == 0 && s.Status.ReadyNodes == 0 {
clusterCondition.Type = apiv1alpha1.ConditionClose
s.Status.State = apiv1alpha1.ClusterCloseState
return clusterCondition
}
// When the cluster is ready or closed, the number of replicas changes,
// indicating that the cluster is updating nodes.
if oldState == apiv1alpha1.ClusterReadyState || oldState == apiv1alpha1.ClusterCloseState {
if int(*s.Spec.Replicas) != s.Status.ReadyNodes {
clusterCondition.Type = apiv1alpha1.ConditionUpdate
s.Status.State = apiv1alpha1.ClusterUpdateState
return clusterCondition
}
}

clusterCondition.Type = apiv1alpha1.ClusterConditionType(oldState)
return clusterCondition
}

// updateNodeStatus update the node status.
func (s *StatusSyncer) updateNodeStatus(ctx context.Context, cli client.Client, pods []corev1.Pod) error {
sctName := s.GetNameForResource(utils.Secret)
Expand Down

0 comments on commit 68d361e

Please sign in to comment.