-
Notifications
You must be signed in to change notification settings - Fork 604
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
feat: resolve special ip host-gateway #1978
Conversation
1256885
to
31e6a78
Compare
cmd/nerdctl/main.go
Outdated
@@ -171,6 +171,7 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, | |||
rootCmd.PersistentFlags().StringSlice("hosts-dir", cfg.HostsDir, "A directory that contains <HOST:PORT>/hosts.toml (containerd style) or <HOST:PORT>/{ca.cert, cert.pem, key.pem} (docker style)") | |||
// Experimental enable experimental feature, see in https://github.com/containerd/nerdctl/blob/main/docs/experimental.md | |||
AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") | |||
rootCmd.PersistentFlags().String("host-gateway-ip", cfg.HostGatewayIP, "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the default bridge") |
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.
Any reason not to just use the host IP?
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 default bridge IP isn't useful for rootless because the slirp is launched with --disable-host-loopback
for the security reason
--disable-host-loopback --port-driver=$CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER \ |
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 suggestion. I just tried to use host ip as default, as the commit I pushed.
I tested the built nerdctl in Lima. The returned host ip can't be used to access host (curl failed).
The static Lima guest IP (192.168.5.15) can be used to access host (curl succeeded). However it seems like a loopback IP which was skipped by the loopback check.
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 tried in ubuntu linux host and it works. I think the host IP is VM has special setup. I will follow the route of making host IP the default as it should work for normal cases. VM users will need to use the config to set the their special IP.
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 finally used env variable the pass the host IP to nsenter. Let me know if you have different thoughts.
3e50c26
to
c818c73
Compare
pkg/testutil/testutil_linux.go
Outdated
@@ -25,6 +25,7 @@ func mirrorOf(s string) string { | |||
|
|||
var ( | |||
AlpineImage = mirrorOf("alpine:3.13") | |||
AmazonLinux2Image = "public.ecr.aws/amazonlinux/amazonlinux:2" |
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 is a new image needed here?
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 need to use curl in tests but alpine doesn't have it and AL2 has it. Let me know if you have suggestions for better image choice.
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. I'm okay with that. The nginx
image should have curl
, can you try 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.
That works. Changed to it.
@@ -130,3 +131,18 @@ func HostsDirs() []string { | |||
filepath.Join(xch, "docker/certs.d"), | |||
} | |||
} | |||
|
|||
func HostGatewayIP() 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.
can you add a comment here? since it's a new export non-test func.
cmd/nerdctl/container_run.go
Outdated
gateway, err := cmd.Flags().GetString("host-gateway-ip") | ||
if err != nil { | ||
return nil, nil, err | ||
} |
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.
host-gateway-ip
has been parsed and passed via globalOptions
right? If so you can use globalOptions.HostGatewayIP
hostGatewayIP, err := cmd.Flags().GetString("host-gateway-ip") | ||
if err != nil { | ||
return types.GlobalCommandOptions{}, err | ||
} |
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 to confirm, HostGatewayIP
will never be empty right? Since the doc mentions it defauts to the IP address of the host.
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.
From nerdctl external it can't be empty.
But it can be empty string "" when passing to here. When there was any issue getting host ip, it would be empty here. In container_run.go, it will return error when it is still "".
if globalOptions.HostGatewayIP == "" {
return nil, nil, fmt.Errorf("unable to derive the IP value for host-gateway")
}
func TestRunAddHostWithCustomHostGatewayIP(t *testing.T) { | ||
// Not parallelizable (https://github.com/containerd/nerdctl/issues/1127) | ||
base := testutil.NewBase(t) | ||
testutil.DockerIncompatible(t) |
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 is it docker incompatible?
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.
docker run --host-gateway-ip "192.168.5.2" --add-host=name:host-gateway -it run amazonlinux bash
unknown flag: --host-gateway-ip
See 'docker run --help'.
Docker has host-gateway-ip in config but not in global flag. From my understanding, there is a convention in nerdctl that transferring all the config to global flag first before using them. So the global flag is docker incompatible.
var found bool | ||
sc := bufio.NewScanner(bytes.NewBufferString(stdout)) | ||
for sc.Scan() { | ||
//removing spaces and tabs separating items | ||
line := strings.ReplaceAll(sc.Text(), " ", "") | ||
line = strings.ReplaceAll(line, "\t", "") | ||
if strings.Contains(line, "192.168.5.2test") { | ||
found = true | ||
} | ||
} | ||
if !found { | ||
return errors.New("host was not added") | ||
} | ||
return nil |
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 a .AssertOutContains("192.168.5.2test")
work?
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.
It should work but not that accurate as this, becuase 192.168.5.2test
can also appear as a host alias instead of IP if the tested code is wrong. (Given tests can't assume tested code is correct)
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, thanks
cmd/nerdctl/main.go
Outdated
@@ -171,6 +171,7 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, | |||
rootCmd.PersistentFlags().StringSlice("hosts-dir", cfg.HostsDir, "A directory that contains <HOST:PORT>/hosts.toml (containerd style) or <HOST:PORT>/{ca.cert, cert.pem, key.pem} (docker style)") | |||
// Experimental enable experimental feature, see in https://github.com/containerd/nerdctl/blob/main/docs/experimental.md | |||
AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") | |||
AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the default bridge") |
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 Docker use HOST_GATEWAY_IP
?
Otherwise:
AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the default bridge") | |
AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "NERDCTL_HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the default bridge") |
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.
Defaults to the IP address of the default bridge
Doesn't seem consistent with the actual implementation
3b653ea
to
6e24ef3
Compare
cmd/nerdctl/container_run.go
Outdated
@@ -57,7 +57,8 @@ import ( | |||
"github.com/containerd/nerdctl/pkg/referenceutil" | |||
"github.com/containerd/nerdctl/pkg/strutil" | |||
"github.com/containerd/nerdctl/pkg/taskutil" | |||
dopts "github.com/docker/cli/opts" | |||
dockercliopts "github.com/docker/cli/opts" | |||
dockerops "github.com/docker/docker/opts" |
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.
typo dockeropts
pkg/defaults/defaults_linux.go
Outdated
} | ||
for _, addr := range addrs { | ||
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { | ||
if ipnet.IP.To4() != nil || ipnet.IP.To16() != nil { |
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.
we do not support ipv6
yet. You should return empty string for ipv6
@@ -130,3 +131,19 @@ func HostsDirs() []string { | |||
filepath.Join(xch, "docker/certs.d"), | |||
} | |||
} | |||
|
|||
// HostGatewayIP returns the non-loop-back host ip if available and returns empty string if running into error. | |||
func HostGatewayIP() 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.
the HostGatewayIP
should be the container network interface IP and not from other network interfaces
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 by defaulit we are returning the host's real ip now instead of any interface IP. The host ip is accessible from containers.
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.
docker is setting the host bridge net interface IP. not sure if the host real IP will fit here, because the host net interface IP that's attached to the container need to be the gateway to route traffic from the container to host.
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.
There are two blockers of using bridge IP.
One is it is not deterministic in nerdctl as I mentioned here For networking, Nerdctl and Docker are using different technology. Nerdctl uses CNI but Docker uses libnetwork, which caused the gap.
The other is it is not useful for rootless based on @AkihiroSuda 's comment.
I guess Docker compatibility is more about consistent user experience instead of implementation details. The default host gateway ip is just something that allows accessing host from containers. Only if the default ip can satisfy this use case, it should be fine.
Let me know if you have better suggestions.
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.
SGTM the real host IP
6e24ef3
to
f80a844
Compare
docs/command-reference.md
Outdated
@@ -1599,6 +1600,7 @@ Flags: | |||
- :nerd_face: `--cgroup-manager=(cgroupfs|systemd|none)`: cgroup manager | |||
- Default: "systemd" on cgroup v2 (rootful & rootless), "cgroupfs" on v1 rootful, "none" on v1 rootless | |||
- :nerd_face: `--insecure-registry`: skips verifying HTTPS certs, and allows falling back to plain HTTP | |||
- :nerd_face: `--host-gateway-ip`: IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host |
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 need to mention that --host-gateway-ip
have no effect without setting --add-host
cc @ningziwen
Signed-off-by: Ziwen Ning <ningziwe@amazon.com>
f80a844
to
a30e765
Compare
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
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
#1979
Tests and docs will be added when the issue got concensus.
Signed-off-by: Ziwen Ning ningziwe@amazon.com