-
Notifications
You must be signed in to change notification settings - Fork 469
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
feat: add RayCluster.status.readyWorkerReplicas
#1930
Conversation
ray-operator/controllers/ray/raycluster_controller_fake_test.go
Outdated
Show resolved
Hide resolved
cc @kevin85421 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I think that's also useful when the RayCluster is in suspended state, in which case it can take a long time the cluster still reports a suspended state despite it's been unsuspended.
I will review this PR because we are approaching the release of KubeRay v1.1.0, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer not to set the state to rayv1.Unhealthy
if not all Pods are running. Both @andrewsykim and @Yicheng-Lu-llll's comments make sense to me.
- https://github.com/ray-project/kuberay/pull/1930/files#r1497794079
- https://github.com/ray-project/kuberay/pull/1930/files#r1498393984
You can think of RayCluster as a collection of K8s ReplicaSets. In this case, only the suspended
ClusterState makes sense to me.
Failed
: I may remove it in the future.Unhealthy
: I may remove it in the future. The ReplicaSetStatus doesn't check the Pod commands which belong to the data plane logic. I also consider removingValidateHeadRayStartParams
and offloading the validation to Ray instead.Ready
: In Kubernetes context,Ready
means that the K8s resource is ready to serve requests. However, in KubeRay context, we require two different definitions forReady
: (1) Whether the head Pod is ready for RayService to create Ray Serve applications or to check the job/serve app status. (2) Whether all Ray Pods are ready for RayJob to submit the job.- This PR can remove
Ready
from the ClusterState, and then (1) add a field in HeadInfo to indicate whether the head Pod is ready or not. (2) add a new field (ReadyWorkerReplicas int32
) in RayClusterStatus which is similar to ReadyReplicas in ReplicaSetStatus.
- This PR can remove
After rethinking this, we can narrow down the scope of this PR a bit to accelerate the merging process. We can add only |
Narrow down the scope of this PR to add |
Is it safe to remove the Ready state? I imagine a lot of people depend on this status already and it would break compatibility |
Good point. I suspect that the RayCluster status is rarely used by users because the ClusterState is not well-defined, yet almost no users have complained about it. |
I agree that it's not well defined, but I don't think that means users are not using it. The reality is that many users will not open issues or complain about something even if they use it. @davidxia opening this PR to change the behavior is one signal that users depend on this field already. If I had to guess, there's probably a lot of (not public) automation that creates a RayCluster and then waits for the |
Your point makes sense to me. I am currently considering the tradeoff:
We can also wait for one or two months to see if users report any issues with the breaking changes in RayJob status. In KubeRay v1.1.0, almost all RayJob statuses have been redefined. If only a few users raise concerns about this, we may be able to infer that using CR status is not common among users. |
Good point that this is also considered a breaking change. I think the technically correct change would be to leave the meaning of |
I would say this is a breaking change. The RayJob before KubeRay v1.1.0 will have a lot of issues with this PR's definition of
|
RayCluster.status.readyWorkerReplicas
@kevin85421 I updated this PR to only add |
@@ -1222,6 +1231,7 @@ func (r *RayClusterReconciler) calculateStatus(ctx context.Context, instance *ra | |||
return nil, err | |||
} | |||
|
|||
newInstance.Status.ReadyWorkerReplicas = utils.CalculateReadyReplicas(runtimePods) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for my own understanding, we can't use the existing AvailableWorkerReplicas
field because that only counts "running" pods and not necessarily "ready" pods, is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
A worker Pod is ready if it has a PodCondition with type == Ready and status == True. See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions
oldStatus.AvailableWorkerReplicas != newStatus.AvailableWorkerReplicas || | ||
oldStatus.DesiredWorkerReplicas != newStatus.DesiredWorkerReplicas || | ||
oldStatus.MinWorkerReplicas != newStatus.MinWorkerReplicas || | ||
oldStatus.MaxWorkerReplicas != newStatus.MaxWorkerReplicas { | ||
logger.Info("inconsistentRayClusterStatus", "detect inconsistency", fmt.Sprintf( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: KubeRay introduced structured logging in KubeRay v1.1.0, which logs messages in JSON format. Hence, we are trying to reduce the use of fmt.Sprintf
. Instead, we want to use key-value pairs. For example,
logger.Info(""inconsistentRayClusterStatus", "detect inconsistency", $KEY1, $VAL1, $KEY2, $VAL2, ...)
so that the logging tools can extract the information from the JSON easily. This is not the scope of this PR. It is not necessary to update this in this PR.
func CalculateReadyReplicas(pods corev1.PodList) int32 { | ||
count := int32(0) | ||
for _, pod := range pods.Items { | ||
if val, ok := pod.Labels["ray.io/node-type"]; !ok || val != string(rayv1.WorkerNode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use RayNodeTypeLabelKey
instead?
if val, ok := pod.Labels["ray.io/node-type"]; !ok || val != string(rayv1.WorkerNode) { | ||
continue | ||
} | ||
for _, cond := range pod.Status.Conditions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use IsRunningAndReady
instead?
func IsRunningAndReady(pod *corev1.Pod) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will merge this PR, and ask others to address:
@MortalHappiness will take #1930 (review). |
A worker Pod is ready if it has a PodCondition with
type == Ready
andstatus == True
. See https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditionsChecks