Skip to content
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

fix: Add used port check for publish flag #2190

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

vsiravar
Copy link
Contributor

Add check for used ports while allocating host port in -p/--publish to make it compatible with docker.

Fixes: #2179

@@ -1,3 +1,4 @@
/*
Copy link
Member

Choose a reason for hiding this comment

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

this line is useless

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed it.

if err != nil {
return nil, err
}
if usedPorts[startHostPort] {
Copy link
Member

Choose a reason for hiding this comment

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

why checking only startHostPort ? why not testing all the range ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, updated.

@@ -302,6 +302,50 @@ func TestUniqueHostPortAssignement(t *testing.T) {
}
}

func TestHostPortAlreadyInUse(t *testing.T) {
if rootlessutil.IsRootless() {
t.Skip("Auto port assign is not supported rootless mode yet")
Copy link
Member

Choose a reason for hiding this comment

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

it is not an auto port assign here, we explicit set port, right ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated, it was leftover from copying code from TestUniqueHostPortAssignement.

pkg/portutil/portutil.go Outdated Show resolved Hide resolved
pkg/portutil/portutil.go Outdated Show resolved Hide resolved
@vsiravar vsiravar force-pushed the vsiravar/fix-2179 branch 3 times, most recently from 879bea2 to 3442f88 Compare April 26, 2023 19:00
@vsiravar vsiravar requested a review from junnplus April 26, 2023 21:15
Comment on lines +71 to +76
if protocol == "tcp" || protocol == "udp" {
netprocData, err := procnet.ReadStatsFileData(protocol)
if err != nil {
return nil, err
}
netprocItems = append(netprocItems, procnet.Parse(netprocData)...)
}
Copy link
Member

Choose a reason for hiding this comment

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

It appears that the SCTP protocol is currently unsupported, therefore no further processing is required.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could be wrong but from this line https://github.com/containerd/nerdctl/blob/main/pkg/portutil/portutil.go#L61, it seems like users could use sctp. There is also a test to check the parsing of sctp https://github.com/containerd/nerdctl/blob/main/pkg/portutil/portutil_test.go#L348.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

I carefully checked the code and did not find an implementation that supports the SCTP protocol. The line just supports parsing command line arguments.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I carefully checked the code and did not find an implementation that supports the SCTP protocol. The line just supports parsing command line arguments.

Additionally there a unit test that checks the parsing of "sctp" https://github.com/containerd/nerdctl/blob/main/pkg/portutil/portutil_test.go#L348, so without the protocol check below, the unit test fails.

        if protocol == "tcp" || protocol == "udp" {
		netprocData, err := procnet.ReadStatsFileData(protocol)
		if err != nil {
			return nil, err
		}
		netprocItems = append(netprocItems, procnet.Parse(netprocData)...)
	}

As a side note, if sctp is not supported then why do we support parsing it in the ParseFlagP ?

Copy link
Member

Choose a reason for hiding this comment

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

Yep..., let it works

Copy link
Member

Choose a reason for hiding this comment

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

I quickly checked, it looks like SCTP is not supported but it is but it is not blocking either. IMHO, we have to add a comment here to highlight this point ( It's misleading without a comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

@junnplus
Copy link
Member

Test failed https://github.com/containerd/nerdctl/actions/runs/4814951537/jobs/8573169644?pr=2190#step:6:982

time="2023-04-27T01:30:38Z" level=fatal msg="failed to load networking flags: bind for :8080 failed: port is already allocated"

@vsiravar
Copy link
Contributor Author

Test failed https://github.com/containerd/nerdctl/actions/runs/4814951537/jobs/8573169644?pr=2190#step:6:982

time="2023-04-27T01:30:38Z" level=fatal msg="failed to load networking flags: bind for :8080 failed: port is already allocated"

This is a test seems is testing TestComposeUpBuild in compose up , not sure if this is related to my change or a flaky test.

@junnplus
Copy link
Member

junnplus commented May 1, 2023

Can you test this case locally? It seems different from what was expected?

$ sudo nerdctl run -p 8080:80 --name=test -d nginx
7f4a2be3bd30eba9d9b5c45ea83213af9728fa456bd3b23783a3352282afc078
$ sudo nerdctl stop test
test
$ sudo nerdctl run -p 8080:80 -d nginx
FATA[0000] failed to load networking flags: bind for :8080 failed: port is already allocated

@@ -39,27 +39,60 @@ func filter(ss []procnet.NetworkDetail, filterFunc func(detail procnet.NetworkDe
}

func portAllocate(protocol string, ip string, count uint64) (uint64, uint64, error) {
netprocData, err := procnet.ReadStatsFileData(protocol)
usedPort, err := getUsedPorts(ip, protocol)

Copy link
Member

Choose a reason for hiding this comment

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

this line is useless

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't quite understand this point? When the user does not specify the host port, we still want to bind an unused port from the host to the container port.

Copy link
Member

Choose a reason for hiding this comment

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

I mean the empty line

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad :(, updated.

Comment on lines +71 to +76
if protocol == "tcp" || protocol == "udp" {
netprocData, err := procnet.ReadStatsFileData(protocol)
if err != nil {
return nil, err
}
netprocItems = append(netprocItems, procnet.Parse(netprocData)...)
}
Copy link
Member

Choose a reason for hiding this comment

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

I quickly checked, it looks like SCTP is not supported but it is but it is not blocking either. IMHO, we have to add a comment here to highlight this point ( It's misleading without a comment)

},
{
hostPort: "5000",
containerPort: "80/udp",
Copy link
Member

@fahedouch fahedouch May 1, 2023

Choose a reason for hiding this comment

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

may be adding a case for SCTP to controller support/behavior of SCTP

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added.

@fahedouch
Copy link
Member

Test failed https://github.com/containerd/nerdctl/actions/runs/4814951537/jobs/8573169644?pr=2190#step:6:982

time="2023-04-27T01:30:38Z" level=fatal msg="failed to load networking flags: bind for :8080 failed: port is already allocated"

This is a test seems is testing TestComposeUpBuild in compose up , not sure if this is related to my change or a flaky test.

Not related. It is a flaky test

@AkihiroSuda
Copy link
Member

@vsiravar Could you confirm this?
#2190 (comment)

@vsiravar
Copy link
Contributor Author

vsiravar commented May 18, 2023

@vsiravar Could you confirm this? #2190 (comment)

Sorry I have been a bit busy. I will have all the comments addressed this weekend.

Can you test this case locally? It seems different from what was expected?

$ sudo nerdctl run -p 8080:80 --name=test -d nginx
7f4a2be3bd30eba9d9b5c45ea83213af9728fa456bd3b23783a3352282afc078
$ sudo nerdctl stop test
test
$ sudo nerdctl run -p 8080:80 -d nginx
FATA[0000] failed to load networking flags: bind for :8080 failed: port is already allocated

I think this is because nerdctl stop does not clean up the network unlike nerdctl remove . I can make a follow up PR to fix this, if it's the behavior we want. cc @junnplus

Edit: Tagged Jun for feeback.

@vsiravar vsiravar force-pushed the vsiravar/fix-2179 branch 2 times, most recently from b86c6ba to f63c2ba Compare May 23, 2023 06:03
}
}

func TestHostPortAlreadyInUseForSctp(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

TestHostPortAlreadyInUseForSctp can simply be added as a case in TestHostPortAlreadyInUse

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated, note though that sctp does not work in rootless mode. Error message failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running hook #0: error running hook: exit status 1, stdout: , stderr: time="2023-05-29T21:35:05Z" level=fatal msg="failed to expose ports in rootless mode: spec was not validated?".

Copy link
Member

Choose a reason for hiding this comment

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

so, we have to skip the sctp case in rootless environnement

Copy link
Contributor Author

@vsiravar vsiravar Jun 6, 2023

Choose a reason for hiding this comment

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

so, we have to skip the sctp case in rootless environnement

Yeah I was just calling out the behavior, it's already skipped in this test in rootless mode

if strings.Contains(tc.containerPort, "sctp") && rootlessutil.IsRootless() {
.

@vsiravar vsiravar force-pushed the vsiravar/fix-2179 branch 2 times, most recently from eded758 to aa8e13d Compare May 29, 2023 21:08
Signed-off-by: Vishwas Siravara <vsiravara@gmail.com>
@fahedouch
Copy link
Member

fahedouch commented Jun 8, 2023

@vsiravar Could you confirm this? #2190 (comment)

Sorry I have been a bit busy. I will have all the comments addressed this weekend.

Can you test this case locally? It seems different from what was expected?

$ sudo nerdctl run -p 8080:80 --name=test -d nginx
7f4a2be3bd30eba9d9b5c45ea83213af9728fa456bd3b23783a3352282afc078
$ sudo nerdctl stop test
test
$ sudo nerdctl run -p 8080:80 -d nginx
FATA[0000] failed to load networking flags: bind for :8080 failed: port is already allocated

I think this is because nerdctl stop does not clean up the network unlike nerdctl remove . I can make a follow up PR to fix this, if it's the behavior we want. cc @junnplus

Edit: Tagged Jun for feeback.

LGTM it is the nerdctl stop responsibility to binded free port(s)

@AkihiroSuda
Copy link
Member

@junnplus LGTY?

@junnplus
Copy link
Member

I think this is because nerdctl stop does not clean up the network unlike nerdctl remove . I can make a follow up PR to fix this, if it's the behavior we want. cc @junnplus

I apologize for just seeing the new update, thank you for your hard work, I will review it this week.

@junnplus
Copy link
Member

junnplus commented Jun 18, 2023

LGTM it is the nerdctl stop responsibility to binded free port(s)

I concur with it, but hold reservations about merging this PR. I believe we should first have nerdctl stop manage the release of ports.

The rest LGTM.

@fahedouch
Copy link
Member

fahedouch commented Jun 24, 2023

LGTM it is the nerdctl stop responsibility to binded free port(s)

I concur with it, but hold reservations about merging this PR. I believe we should first have nerdctl stop manage the release of ports.

The rest LGTM.

cc vsiravar, could you please fix the stop ( it can be a different PR) so we can merge this accordingly? Thanks

@vsiravar
Copy link
Contributor Author

LGTM it is the nerdctl stop responsibility to binded free port(s)

I concur with it, but hold reservations about merging this PR. I believe we should first have nerdctl stop manage the release of ports.
The rest LGTM.

cc vsiravar, could please fix the stop ( it can be a different PR) so we can merge this accordingly? Thanks

Sure, I'll work on it in the next couple of weeks.

@vsiravar
Copy link
Contributor Author

vsiravar commented Jul 5, 2023

LGTM it is the nerdctl stop responsibility to binded free port(s)

I concur with it, but hold reservations about merging this PR. I believe we should first have nerdctl stop manage the release of ports.
The rest LGTM.

cc vsiravar, could you please fix the stop ( it can be a different PR) so we can merge this accordingly? Thanks

Sure. I will have a PR out this week. Cheers!

@AkihiroSuda
Copy link
Member

What's the current status of this?

@vsiravar
Copy link
Contributor Author

vsiravar commented Aug 8, 2023

What's the current status of this?

I think this PR is good. I am still working on the PR to fix the stop to free binded ports on stop.

@AkihiroSuda AkihiroSuda modified the milestones: v1.5.1, v1.5.2 Sep 11, 2023
@AkihiroSuda
Copy link
Member

@junnplus PTAL

Copy link
Member

@fahedouch fahedouch left a comment

Choose a reason for hiding this comment

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

Thanks

@AkihiroSuda AkihiroSuda removed this from the v1.6.1 (tentative) milestone Oct 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

nerdctl run -p <host-port>:<container port> <image> does not check if user defined host port is in use.
4 participants