Skip to content

Conversation

@ianlewis
Copy link

@ianlewis ianlewis commented Dec 8, 2020

This allows shims to implement an optional port forwarding service. This
is useful for runtimes that remove the IP address from the veth for a
user space network stack and can't support port forwarding via the
network namespace.

This implements Option 1b described here: kubernetes/enhancements#1846

Summary:

This PR adds a new optional PortForward grpc service that shims can implement. The service has a single PortForward rpc endpoint that accepts a port number and UDS address. Containerd will attempt to use the PortForward endpoint to initiate port forwarding and fall back to existing logic on the container's network namespace if unsuccessful. Containerd will listen on the UDS address and shims/runtimes are expected to establish a single connection on this address to establish bi-directional communication, forwarding data to/from the container's port to the UDS connection.

As networking is out of scope of containerd itself, a new PortForward plugin is introduced to allow the CRI plugin to make calls to task implementations directly. The CRI plugin uses this plugin to call runtime/v2 implementations directly and returns an error if the task is not a runtime/v2 implementation that implements port forwarding. Only runtime/v2 implementations that are shims are expected to implement this interface.

@k8s-ci-robot
Copy link

Hi @ianlewis. Thanks for your PR.

I'm waiting for a containerd member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Dec 8, 2020

Build succeeded.

@ianlewis ianlewis force-pushed the port-forward branch 2 times, most recently from 1203211 to 92dfc8d Compare December 8, 2020 01:05
@ianlewis
Copy link
Author

ianlewis commented Dec 8, 2020

/cc @mikebrow

@k8s-ci-robot k8s-ci-robot requested a review from mikebrow December 8, 2020 01:05
@theopenlab-ci
Copy link

theopenlab-ci bot commented Dec 8, 2020

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Mar 15, 2021

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Apr 15, 2021

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Apr 26, 2021

Build succeeded.

This allows shims to implement an optional port forwarding service. This
is useful for runtimes that remove the IP address from the veth for a
user space network stack and can't support port forwarding via the
network namespace.
@ianlewis ianlewis changed the title [WIP] Add port forwarding to shim API Add a shim API for port forwarding. Apr 26, 2021
@theopenlab-ci
Copy link

theopenlab-ci bot commented Apr 26, 2021

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Apr 27, 2021

Build succeeded.

Copy link
Member

@mikebrow mikebrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments.. request to get engagement with some more core runtime maintainers

"github.com/containerd/containerd/runtime"
client "github.com/containerd/containerd/runtime/v2/shim"
"github.com/containerd/containerd/runtime/v2/task"
shimapi "github.com/containerd/containerd/runtime/v2/task"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe taskAPI

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started doing this partly because it was given this name in runtime/v2/shim/shim.go and it seems like this package name is becoming dated given that we may be adding more optional services to the shim.

e.g. https://github.com/containerd/containerd/pull/5396/files#diff-a90594dff4315b8444427fbaf0c64c6febd6a08ed6b2db5fb706b53ff3f97f79

if err != nil {
return nil, errors.Wrap(err, "failed to create containerd client")
}
pf, err := getPortForwardService(ic)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we need to figure out a way to make this per runtime?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intention was to allow shims to implement port forward. I don't think we had a need to implement it per "runtime" (i.e. v1, v2, v2/shim). My intention was for 'pf' to return an error in cases where it wasn't supported and fall back to the previous logic. I do that around line 75 in sandbox_portforward_linux.go.

I'm open to thinking about it but I can't really imagine how it would work unless we push the code in localPortForward in sandbox_portforward_linux.go into runtime/v2 somewhere. I don't think we really want to do that.

}
pf, err := getPortForwardService(ic)
if err != nil {
return nil, errors.Wrap(err, "failed to get port forward service")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we ignore if there is no port forward service to fall back to the prior behavior..

@dmcgowan @crosbymichael we should do a call I think with Ian to go over this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it might be good to meet again. I can probably speak more intelligently now that I've taken a stab at implementing this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sent an invite for Wed. Hopefully that works.

}

logrus.Debug("registering ttrpc server")
logrus.Debug("registering task service")
Copy link
Member

@mikebrow mikebrow May 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe registering task service via ttrpc

func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriteCloser) error {
s, err := c.sandboxStore.Get(id)
// Attempt to start port forwarding via the port forwarding client.
// NOTE: Do not use volitile root dir as it amy exceed max length for UDS addr.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"may exceed"

rtTasks: rt,
client: client,
task: shimapi.NewTaskClient(client),
portforward: shimapi.NewPortForwardClient(client),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the shim could just return the client here, then the port forward client could be completely separated here

@dmcgowan dmcgowan added the status/needs-discussion Needs discussion and decision from maintainers label May 27, 2021
@mxpv mxpv mentioned this pull request Jul 15, 2021
}

message PortForwardRequest {
// The container id.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// The container id.
// ID is the container id.

message PortForwardRequest {
// The container id.
string id = 1;
// The port to be forwarded inside the container.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// The port to be forwarded inside the container.
// Port sets the port to be forward inside the container.

string id = 1;
// The port to be forwarded inside the container.
int32 port = 2;
// A Unix domain socket address
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// A Unix domain socket address
// Addr is the unix domain socket address.

rpc PortForward(PortForwardRequest) returns (google.protobuf.Empty);
}

message PortForwardRequest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, make sure to add some documentation to the message type.

@AkihiroSuda
Copy link
Member

Needs rebase

@ianlewis
Copy link
Author

Closing this. @zkoopmans can create a new PR using this as a reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ok-to-test status/needs-discussion Needs discussion and decision from maintainers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants