-
Notifications
You must be signed in to change notification settings - Fork 511
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
[Feature][RayService] Set default ports #3262
[Feature][RayService] Set default ports #3262
Conversation
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
port can be set different name in yaml -e Signed-off-by: machichima <[email protected]>
for name, defaultPort := range defaultPorts { | ||
// ensure client port value overwrite | ||
if name == utils.ClientPortName { | ||
assert.Equalf(t, 12345, int(svcPorts[name]), "Expected `%v` as `%v` port value but got `%v`", 12345, name, svcPorts[name]) |
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.
assert.Equalf(t, 12345, int(svcPorts[name]), "Expected `%v` as `%v` port value but got `%v`", 12345, name, svcPorts[name]) | |
assert.Equal(t, 12345, int(svcPorts[name])) |
The message is not very useful. Simple assertion is enough.
ports: | ||
- containerPort: 6379 | ||
name: gcs-server | ||
- containerPort: 8265 # Ray dashboard | ||
name: dashboard | ||
- containerPort: 10001 | ||
name: client | ||
- containerPort: 8000 | ||
name: serve |
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.
Also remove this section in other ray-service.*.yaml
files.
// Only assign defaultPort if the port is not already in use | ||
if !usedPorts[defaultPort] { | ||
ports[name] = defaultPort | ||
usedPorts[defaultPort] = true // Mark this port as used | ||
} |
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.
Should return error instead of do nothing if ports conflict with defaultPort.
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.
What I was thinking here is that if user set the port with different name, the user's setting will be used.
For instance, when running tests, I encountered the issue that the default is:
- containerPort: 6379
name: gcs-server
While test set:
- containerPort: 6379
name: gcs
In this case, user's setting with name gcs
will be applied.
Do we need error for this? Or probably a warning is enough? Update on below comments
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.
Update:
This problem is actually caused by different naming for gcs-server
(some named it as gcs
)
For example:
kuberay/ray-operator/controllers/ray/common/service_test.go
Lines 71 to 72 in e672376
ContainerPort: 6379, | |
Name: "gcs", |
Default gcs-server name should be:
GcsServerPortName = "gcs-server" |
I would like to confirm if it is ok to change all port name "gcs" into "gcs-server"?
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. We should use the same value across the codebase.
svcPorts := make(map[string]int32) | ||
usedPorts := make(map[int32]bool) | ||
for _, port := range ports { | ||
if *port.AppProtocol != utils.DefaultServiceAppProtocol { | ||
t.Fatalf("Expected `%v` but got `%v`", expectedResult, *port.AppProtocol) | ||
} | ||
svcPorts[port.Name] = port.Port | ||
usedPorts[port.Port] = true | ||
} | ||
|
||
for name, defaultPort := range defaultPorts { | ||
// ensure client port value overwrite | ||
if name == utils.ClientPortName { | ||
assert.Equalf(t, 12345, int(svcPorts[name]), "Expected `%v` as `%v` port value but got `%v`", 12345, name, svcPorts[name]) | ||
} else if !usedPorts[defaultPort] { | ||
// Ensure the default port value is applied | ||
t.Fatalf("Port `%v` not set", defaultPort) | ||
} | ||
} | ||
|
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.
In tests, we should simply assert the final result, and the expected outcome should be easy to construct. It's hard to read a test that loops over constructed values and makes assertions.
We may want to split the test into several test cases if the expected value is hard to construct. For example, one with duplicated ports and another without.
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 for the advice! I moved into a new test function so that it is easier to read
cc @rueian for review |
ports[utils.MetricsPortName] = utils.DefaultMetricsPort | ||
// 1. If a value is provided in the YAML file, overwrite the default value | ||
// 2. If no port value is provided, use the default name and port | ||
// 3. If a port value is provided in the YAML file, retain the original name |
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.
Will k8s throw an error when there are duplicated port values? If not, can we just preserve them all?
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, I encountered the following error when there's duplicate port value 6379 (for gcs-server).
Warning FailedToCreateService 47s (x16 over 3m31s) raycluster-controller Failed creating service test-ns-hgtnx/raycluster-gcsft-head-svc, Service "raycluster-gcsft-head-svc" is invalid: spec.ports[3]: Duplicate value: core.ServicePort{Name:"", Protocol:"TCP", AppProtocol:(*string)(nil), Port:6379, TargetPort:intstr.IntOrString{Type:0, IntVal:0, StrVal:""}, NodePort:0}
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.
👌
…service-default-ports -e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
svcPort := corev1.ServicePort{Name: utils.ServingPortName, Port: portsInt[utils.ServingPortName]} | ||
// Only include serve port | ||
ports := []corev1.ServicePort{svcPort} |
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.
Should we still include the svcPort
if utils.ServingPortName
is not in the portsInt
?
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 think it will always be there as we will assign default value. And now if user trying to use name other than utils.ServingPortName
for serving port, the error will be raised.
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
This also raise error if the default port is set with name different to default name -e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
Hi @MortalHappiness , Otherwise, the "gcs" port name need to be renamed as "gcs-server" (default port name) so that the error will not be raised. |
Yes. They'll be removed in #3245 |
-e Signed-off-by: machichima <[email protected]>
for name, port := range testCase.expectResult { | ||
assert.Equal(t, port, svcPorts[name]) | ||
} |
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.
for name, port := range testCase.expectResult { | |
assert.Equal(t, port, svcPorts[name]) | |
} | |
assert.Equal(t, testCase.expectResult, svcPorts) |
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.
Fixed. Thank you!
-e Signed-off-by: machichima <[email protected]>
ports = append(ports, svcPort) | ||
break | ||
} | ||
ports := []corev1.ServicePort{} |
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.
ports
seems to have at most one element? If this is correct, maybe we can use var servePort corev1.ServicePort
instead.
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.
In the code below we need to assign ports
to serveService.Spec.Ports
, so I think it's better to keep it as slice here. I will set its capacity into 1 then.
serveService.Spec.Ports = ports |
@@ -40,10 +40,3 @@ spec: | |||
requests: | |||
cpu: 500m | |||
memory: 2Gi | |||
ports: |
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.
Why should we update this RayCluster YAML?
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.
Oh sorry, I modified this accidentally. Let me change it back.
"dashboard": "8265", | ||
"gcs": "6379", | ||
"metrics": "8080", | ||
"client": "10001", |
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.
Not necessarily in this PR, but would you mind using constant variables instead of hard-coded strings?
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.
No problem, I will add a new PR for this as there's multiple places to modify
@@ -125,7 +125,7 @@ func headPodTemplateApplyConfiguration() *corev1ac.PodTemplateSpecApplyConfigura | |||
WithName("ray-head"). | |||
WithImage(GetRayImage()). | |||
WithPorts( | |||
corev1ac.ContainerPort().WithName("gcs").WithContainerPort(6379), | |||
corev1ac.ContainerPort().WithName("gcs-server").WithContainerPort(6379), |
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.
Not necessarily in this PR, but would you mind using constant variables instead of hard-coded strings?
@@ -98,7 +98,7 @@ func headPodTemplateApplyConfiguration() *corev1ac.PodTemplateSpecApplyConfigura | |||
WithName("ray-head"). | |||
WithImage(GetRayImage()). | |||
WithPorts( | |||
corev1ac.ContainerPort().WithName("gcs").WithContainerPort(6379), | |||
corev1ac.ContainerPort().WithName("gcs-server").WithContainerPort(6379), |
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.
Not necessarily in this PR, but would you mind using constant variables instead of hard-coded strings?
// BuildServiceForHeadPod should generate a headless service for a Head Pod by default. | ||
if svc.Spec.ClusterIP != corev1.ClusterIPNone { | ||
t.Fatalf("Expected `%v` but got `%v`", corev1.ClusterIPNone, svc.Spec.ClusterIP) | ||
} | ||
} | ||
|
||
// Test if default ports is applied and can be overwritten by config |
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.
What's the relationship between this test and this PR? The tests seem irrelevant and don't cover all cases. Perhaps we can remove this from the PR and open another one to add tests with sufficient coverage.
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.
This test ensures the default ports are set if user does not specify ports in yaml. As we are trying to remove all ports
section in rayservice sample yaml file, I think this test is needed.
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
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.
Left small comments. Otherwise, LGTM.
name string | ||
expectResult map[string]int32 | ||
ports []corev1.ContainerPort | ||
expectError 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.
Currently, expectError
is false in all tests, so we can remove it for now.
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.
Fixed. Thanks!
// BuildServiceForHeadPod should generate a headless service for a Head Pod by default. | ||
if svc.Spec.ClusterIP != corev1.ClusterIPNone { | ||
t.Fatalf("Expected `%v` but got `%v`", corev1.ClusterIPNone, svc.Spec.ClusterIP) | ||
} | ||
} | ||
|
||
// Test if default ports is applied and can be overwritten by config | ||
func TestBuildServiceForHeadPodDefaultPorts(t *testing.T) { | ||
type testCase struct { |
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.
Can you add comments here to summarize the behavior of setting ports?
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.
Sure, I added:
"Test that default ports are applied when none are specified. The metrics port is always added if not explicitly set."
-e Signed-off-by: machichima <[email protected]>
-e Signed-off-by: machichima <[email protected]>
Changes
ports
section inray-service.*.yaml
BuildServeService
when assigning service portmetrics
does not, the defaultmetrics
port is setWhy are these changes needed?
Currently, many sample YAML files define the
ports
section, while in code the default ports will be set if no ports defined.kuberay/ray-operator/controllers/ray/common/service.go
Lines 379 to 382 in b6db7a5
Those
ports
section inray-service.*.yaml
file can be removed.Related issue number
Closes #3246
Checks