-
Notifications
You must be signed in to change notification settings - Fork 103
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: allow to propagate the address specified in -p option #477
fix: allow to propagate the address specified in -p option #477
Conversation
When containerd is running as a root user and an address other than `127.0.0.1`, such as `127.0.0.2`, is specified in `-p` when `nerdctl run` is used to start a container, the combination of the address and port number allows connections to an application running in the container. Specifically, `curl 127.0.0.2:8080` will access a nginx application running on port `80` in the container created by the following command. ``` $ sudo nerdctl run --name nginx -d -p 127.0.0.2:8080:80 nginx 7abce48d42ef809613365ffaa54d9526e8388c78f5f5c2d8a2850628543ca27e $ sudo nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7abce48d42ef docker.io/library/nginx:latest "/docker-entrypoint.…" 3 seconds ago Up 127.0.0.2:8080->80/tcp nginx $ curl 127.0.0.2:8080 <!DOCTYPE html> ... ``` On the other hand, when running containerd as a non-root user, similarly, suppose we start a container with an address other than `127.0.0.1`, such as `127.0.0.2` for -p. In this case, curl `127.0.0.2:8080` will not connect to a nginx application running inside the container. Details are described below. ``` $ nerdctl run --name nginx -d -p 127.0.0.2:8080:80 nginx 7687f9612afe6847fb3946254718fafef935ffdc05f9cbb4496fc40dd35a6abc $ nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7687f9612afe docker.io/library/nginx:latest "/docker-entrypoint.…" 5 seconds ago Up 127.0.0.2:8080->80/tcp nginx $ curl 127.0.0.2:8080 curl: (56) Recv failure: Connection reset by peer ``` When a connection is requested from the outside to the container in Parent NetNS, the rootlesskit port driver relays the connection from Parent NetNS to Child NetNS. When, for example, an address such as `127.0.0.2` is specified in -p, Child NetNS need to establish a connection to the specified address. However, the current implementation will establish a connection to `127.0.0.1` even when `127.0.0.2` is specified in -p. The behavior of not propagating the address specified by -p is assumed at this time, as described in the following document. - https://github.com/rootless-containers/rootlesskit/blob/master/docs/port.md#port-drivers > --port-driver Throughput Source IP > ... > builtin 30.0 Gbps Always 127.0.0.1 > ... > The builtin driver is fast, but be aware that the source IP is not propagated and always set to 127.0.0.1. However, an issue to improve this behavior is reported below. - containerd/nerdctl#3539 Therefore, this commit fixes when running containerd as a non-root user, the address specified in -p will be propagated. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
Thanks, can we have a test? rootlesskit/.github/workflows/main.yaml Lines 40 to 54 in 9c9049a
|
Thanks for the comment!!! My InvestigationI've checked the contents of the integration test in At first I thought we could add the following test to integration-port.sh. test_port builtin http://127.0.0.2:8080 "should success" -p 127.0.0.2:8080:80/tcp However, I have confirmed in my development environment that this test case passes without applying this PR fix. Details
ubuntu@ip-172-31-33-251:~/rootlesskit$ git status
On branch master
Your branch is up to date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
diff.patch
hack/issue_3539.sh
nothing added to commit but untracked files present (use "git add" to track)
# Run this integration test
ubuntu@ip-172-31-33-251:~/rootlesskit$ ls hack/issue_3539.sh
hack/issue_3539.sh
ubuntu@ip-172-31-33-251:~/rootlesskit$ cat hack/issue_3539.sh
#!/bin/bash
source $(realpath $(dirname $0))/common.inc.sh
# test_port PORT_DRIVER CURL_URL EXPECTATION [ROOTLESSKIT ARGS...]
function test_port() {
args="$@"
port_driver="$1"
curl_url="$2"
expectation="$3"
shift
shift
shift
rootlesskit_args="$@"
INFO "Testing port_driver=\"${port_driver}\" curl_url=\"${curl_url}\" expectation=\"${expectation}\" rootlesskit_args=\"${rootlesskit_args}\""
tmp=$(mktemp -d)
state_dir=${tmp}/state
html_dir=${tmp}/html
mkdir -p ${html_dir}
echo "test_port ($args)" >${html_dir}/index.html
$ROOTLESSKIT \
--state-dir=${state_dir} \
--net=slirp4netns \
--disable-host-loopback \
--copy-up=/etc \
--port-driver=${port_driver} \
${rootlesskit_args} \
busybox httpd -f -v -p 80 -h ${html_dir} \
2>&1 &
pid=$!
sleep 1
set +e
curl -fsSL ${curl_url}
code=$?
set -e
if [ "${expectation}" = "should success" ]; then
if [ ${code} != 0 ]; then
ERROR "curl exited with ${code}"
exit ${code}
fi
elif [ "${expectation}" = "should fail" ]; then
if [ ${code} = 0 ]; then
ERROR "curl should not success"
exit 1
fi
else
ERROR "internal error"
exit 1
fi
INFO "Test pasing, stopping httpd (\"exit status 255\" is negligible here)"
kill -SIGTERM $(cat ${state_dir}/child_pid)
wait $pid >/dev/null 2>&1 || true
rm -rf $tmp
}
INFO "===== Port driver: builtin ====="
INFO "=== protocol \"tcp\" listens on both v4 and v6 ==="
test_port builtin http://127.0.0.2:8080 "should success" -p 127.0.0.2:8080:80/tcp
INFO "===== PASSING ====="
# Build rootlesskit and install
ubuntu@ip-172-31-33-251:~/rootlesskit$ make && sudo make install
...
# Build docker image for integration test
ubuntu@ip-172-31-33-251:~/rootlesskit$ DOCKER_BUILDKIT=1 sudo docker build -t rootlesskit:test-integration --target test-integration .
...
# Run the integration test
ubuntu@ip-172-31-33-251:~/rootlesskit$ sudo docker run --rm --privileged rootlesskit:test-integration ./issue_3539.sh
[INFO] ===== Port driver: builtin =====
[INFO] === protocol "tcp" listens on both v4 and v6 ===
[INFO] Testing port_driver="builtin" curl_url="http://127.0.0.2:8080" expectation="should success" rootlesskit_args="-p 127.0.0.2:8080:80/tcp"
[rootlesskit:parent] error: no command specified In the first place, this modification allows QuestionOn the other hand, I think we need to add the following test on the nerdctl side for this fix, what do you think ??? Details
[ec2-user@ip-172-31-40-91 nerdctl]$ git diff cmd/nerdctl/
diff --git a/cmd/nerdctl/container/container_run_linux_test.go b/cmd/nerdctl/container/container_run_linux_test.go
index dc33702e..357ca1cf 100644
--- a/cmd/nerdctl/container/container_run_linux_test.go
+++ b/cmd/nerdctl/container/container_run_linux_test.go
@@ -567,3 +567,42 @@ func TestIssue3568(t *testing.T) {
testCase.Run(t)
}
+
+// TestIssue3568 tests https://github.com/containerd/nerdctl/issues/3539
+func TestIssue3539(t *testing.T) {
+ testCase := nerdtest.Setup()
+
+ const (
+ host = "127.0.0.2"
+ hostPort = 8080
+ )
+ address := fmt.Sprintf("%s:%d", host, hostPort)
+
+ testCase.SubTests = []*test.Case{
+ {
+ Description: "Issue #3539 - Access to a container running when 127.0.0.2 is specified in -p in rootless mode.",
+ Setup: func(data test.Data, helpers test.Helpers) {
+ helpers.Ensure("run", "-d", "--name", data.Identifier(), "-p", fmt.Sprintf("%s:80", address), testutil.NginxAlpineImage)
+ },
+ Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
+ return helpers.Custom("curl", "-s", address)
+ },
+ Cleanup: func(data test.Data, helpers test.Helpers) {
+ helpers.Anyhow("rm", "-f", data.Identifier())
+ },
+ Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
+ return &test.Expected{
+ ExitCode: 0,
+ Errors: []error{},
+ Output: test.All(
+ func(stdout string, info string, t *testing.T) {
+ assert.Assert(t, strings.Contains(string(stdout), testutil.NginxAlpineIndexHTMLSnippet))
+ },
+ ),
+ }
+ },
+ },
+ }
+
+ testCase.Run(t)
+} Note that I've confirmed that this test in nerdctl succeeds after applying the fix for rootkesskit. Details
# applied this fix to rootlesskit
[ec2-user@ip-172-31-40-91 rootlesskit]$ git shortlog -p -1
Hayato Kiwata (1):
fix: allow to propagate the address specified in -p option
# build and install rootlesskit
[ec2-user@ip-172-31-40-91 rootlesskit]$ make && sudo make install
...
# restart containerd
[ec2-user@ip-172-31-40-91 rootlesskit]$ sudo systemctl restart user@1000.service
[ec2-user@ip-172-31-40-91 rootlesskit]$ cd ../nerdctl/
[ec2-user@ip-172-31-40-91 nerdctl]$ go test -p 1 ./cmd/nerdctl/... -run "TestIssue3539.*" -count=1
ok github.com/containerd/nerdctl/v2/cmd/nerdctl 0.011s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/apparmor 0.012s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/builder 0.010s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/completion 0.010s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/compose 0.012s [no tests to run]
# This is the result of passing the above test (TestIssue3539)
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/container 1.247s
? github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers [no test files]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/image 0.011s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/inspect 0.011s [no tests to run]
? github.com/containerd/nerdctl/v2/cmd/nerdctl/internal [no test files]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/ipfs 0.010s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/issues 0.011s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/login 0.016s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/namespace 0.015s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/network 0.011s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/system 0.012s [no tests to run]
ok github.com/containerd/nerdctl/v2/cmd/nerdctl/volume 0.011s [no tests to run] |
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
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
When containerd is running as a root user and an address other than
127.0.0.1
, such as127.0.0.2
, is specified in-p
whennerdctl run
is used to start a container, the combination of the address and port number allows connections to an application running in the container.Specifically,
curl 127.0.0.2:8080
will access a nginx application running on port80
in the container created by the following command.On the other hand, when running containerd as a non-root user, similarly, suppose we start a container with an address other than
127.0.0.1
, such as127.0.0.2
for -p.In this case, curl
127.0.0.2:8080
will not connect to a nginx application running inside the container.Details are described below.
When a connection is requested from the outside to the container in Parent NetNS, the rootlesskit port driver relays the connection from Parent NetNS to Child NetNS.
When, for example, an address such as
127.0.0.2
is specified in -p, Child NetNS need to establish a connection to the specified address.However, the current implementation will establish a connection to
127.0.0.1
even when127.0.0.2
is specified in -p.The behavior of not propagating the address specified by -p is assumed at this time, as described in the following document.
However, an issue to improve this behavior is reported below.
Therefore, this commit fixes when running containerd as a non-root user, the address specified in -p will be propagated.