-
Notifications
You must be signed in to change notification settings - Fork 347
Conversation
b0db171 to
ae91a27
Compare
pkg/server/streaming.go
Outdated
|
|
||
| func (s *streamRuntime) PortForward(podSandboxID string, port int32, stream io.ReadWriteCloser) error { | ||
| return errors.New("not implemented") | ||
| if port < 0 || port > math.MaxUint16 { |
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.
port <= 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.
The orignal code in kubelet is using port < 0. However, you are right, we should check ==0 as well. Will update.
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.
Done.
ae91a27 to
b9505ba
Compare
| "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" | ||
| ) | ||
|
|
||
| // PortForward prepares a streaming endpoint to forward ports from a PodSandbox, and returns the address. |
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.
Comment does not follow what is happening in the api. Currently it's validating that the sandbox is running then returns the serving URL for specified streaming port.
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.
The comment is the same with dockershim https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/dockershim/docker_streaming.go#L115.
And I think it explains what the function is doing. :)
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.
ok I'm confused .. where does the api "prepare a streaming endpoint to forward ports from a PodSandbox" all I see is ensuring the running state for the sandbox and calling GetPortForward which I presume just does a get?
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.
GetPortForward prepares the streaming endpoint and returns the URL.
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.
kk thx!
| } | ||
|
|
||
| // portForward requires `nsenter` and `socat` on the node. | ||
| func (c *criContainerdService) portForward(id string, port int32, stream io.ReadWriteCloser) error { |
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 this api be here or over in streaming.go
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 put attach, portForward and exec in corresponding source file.
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.
Don't understand the answer. There is a PortForward api in streaming.go that calls portForward. The PortForward api in sandbox_portforward.go does not call portForward. Thus my question.
| return nil, errors.New("sandbox container is not running") | ||
| } | ||
| // TODO(random-liu): Verify that ports are exposed. | ||
| return c.streamServer.GetPortForward(r) |
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.
Curious.. why all the above validation on the running status? Are there expected errors if the sandbox isn't running?
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.
Portforward nsenters a the pause container namespace, and running a socat server to do portforwarding.
I believe this requires the pause container is running, because we use the pid to find it's namespace.
We could probably use permanent network namespace to prevent this in the future.
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.
Does the GetPortForward api require we make sure this is the case, or will it return an appropriate error if we have not. IOW are we double checking what the API is going to check anyway?
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.
streamServer doesn't even know CRI, it can't check container status.
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 what I meant but ok..
I presumed you wanted to ensure there is a pid and associated namespace before calling.. and also presumed that the streamServer would also check and return an error message if not vs using a static table of some sort. But I'm not looking at it's code so..
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 see.. one of "those" apis :-) should probably be called Reserve instead of Get.. now it makes sense.
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 understanding :
Even if the task is paused/stopped the namespace is still available to nsenter right?
How is this supposed to work with windows in the future.
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.
Even if the task is paused/stopped the namespace is still available to nsenter right?
Offline talked with @yujuhong. Yeah, we only need network namespace here. I had a concern that we run a pod specific process but only in its network namespace, it means that the process could access other host namespaces. However, socat is on the node, the cluster admin should make sure it's friendly. :)
Actually, there are other issues with the current solution - the socat is not in pod cgroup, so the resource usage will be charged to the system.
How is this supposed to work with windows in the future.
@abhinandanpb Good question. Currently, Kubelet only has limited windows support. Many critical kubelet features doesn't have corresponding windows support, e.g. pod level cgroup, cadvisor monitoring etc. There is an ongoing effort to make kubelet work better on windows.
Actually, we should be able to run a port forward container inside the pod sandbox to do port forward, which makes more sense because:
- The resource overhead will be charged to the pod;
- If containerd container exec support different platforms, this solution could be platform agnostic.
I'll add a TODO here, we could do this in near future. :)
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.
Done.
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.
got it. Thanks for explaining.
pkg/server/sandbox_portforward.go
Outdated
| return c.streamServer.GetPortForward(r) | ||
| } | ||
|
|
||
| // portForward requires `nsenter` and `socat` on the node. |
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.
maybe some explanation about what the api does.
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 do.
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.
Done.
| return fmt.Errorf("unable to find socat: %v", err) | ||
| } | ||
|
|
||
| args := []string{"-t", fmt.Sprintf("%d", pid), "-n", socat, |
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.
maybe a comment or pointer about the options being 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.
Good idea. Will do.
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.
Done.
| if err := cmd.Run(); err != nil { | ||
| return fmt.Errorf("nsenter command returns error: %v, stderr: %q", err, stderr.String()) | ||
| } | ||
|
|
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 use a channel to wait on the go func io.Copy err? Maybe pipe the err in the go func after the in.Close() call and wait on the channel before the final return..?
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 we want the goroutine to keep serving even after the function returns, until the client disconnects.
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.
kk didn't know that was a long running task. Maybe a comment about that..
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'll add some comment to describe what port forward is doing.
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.
Actually, you are correct, we should wait on the go func. Will update.
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.
The implementation is the same with https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/dockershim/docker_streaming.go#L162. And based on the original comment and code analysis, the code should be safe.
I added more logs so that if in the future there are any problem, we could figure it out.
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.
Logging works if we have the right test buckets... hate leaving what might be a dangling pipe thread but at least we'll have an unbalanced lvl 4 log to identify it if it happens.
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.
@mikebrow Run already contains a Wait, and the wait makes sure that the stream will be closed. And there is no context passed in by streaming server, so there is no cancellation, either.
If we don't use Run and a context is passed in, I'd prefer adding a channel and do select. :)
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.
Makes sense.
mikebrow
left a comment
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.
See comments.
|
@mikebrow Addressed comments. |
e414d44 to
40ac337
Compare
mikebrow
left a comment
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.
/LGTM
40ac337 to
0e5404b
Compare
pkg/server/sandbox_portforward.go
Outdated
| } | ||
| id := sandbox.ID | ||
|
|
||
| info, err := c.taskService.Get(ctx, &tasks.GetTaskRequest{ContainerID: id}) |
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 please add a TODO to replace this with client API
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.
or TODO to use permanent network namespace ( discussed below)
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 do.
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.
Done.
|
Minor comments, LGTM |
0e5404b to
ebe41b1
Compare
|
@abhinandanpb Addressed comments. Thanks for reviewing! |
Signed-off-by: Lantao Liu <[email protected]>
ebe41b1 to
f555bb1
Compare
|
Just updated this PR to use the containerd client. |
Add portforward support.
Add port forward support. The implementation is the same with the dockershim.
Signed-off-by: Lantao Liu [email protected]