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

Add host.containers.internal entry into container's etc/hosts #9972

Conversation

bblenard
Copy link

@bblenard bblenard commented Apr 8, 2021

This change adds the entry host.containers.internal to the /etc/hosts
file within a new containers filesystem. The ip address is determined by
the containers networking configuration and points to the gateway address
for the containers networking namespace.

Closes #5651

Signed-off-by: Baron Lenardson [email protected]

@bblenard bblenard force-pushed the issue-5651-hostname-for-container-gateway branch from 03073cf to 7747541 Compare April 8, 2021 01:52
@mheon
Copy link
Member

mheon commented Apr 8, 2021

/approve

@openshift-ci-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bblenard, mheon

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 8, 2021
@@ -1381,23 +1401,12 @@ func (c *Container) makeBindMounts() error {
// other container. Unless we're not creating both of
// them.
var (
depCtr *Container
nextCtr string
depCtr *Container
Copy link
Member

Choose a reason for hiding this comment

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

Can drop this block and make depCtr, err = c.getRootNetNsDepCtr() a :=

Will be a little cleaner

Copy link
Author

Choose a reason for hiding this comment

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

@@ -1342,6 +1342,26 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return c.save()
}

// Retrieves a container's "root" net namespace container dependency.
Copy link
Member

Choose a reason for hiding this comment

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

Can you note that this returns nil if there is no dependency?

Copy link
Author

@bblenard bblenard Apr 9, 2021

Choose a reason for hiding this comment

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

I don't think this can be null unless there is an error, although I could be wrong. So would you like a note about it returning an nil on error? That being said I am adding some extra error handling in that function based on your comment, but it wont make sense if State.Container interface function can return nil, nil.

@@ -36,7 +36,7 @@ import (
"golang.org/x/sys/unix"
)

const (
var (
Copy link
Member

Choose a reason for hiding this comment

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

Can you keep this block const and then add a separate var block below for the slirp4netns bit?

Copy link
Author

Choose a reason for hiding this comment

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

I have changed this I just don't want to kick off another CICD run until I get the other things sorted out.

@mheon
Copy link
Member

mheon commented Apr 8, 2021

I'd like @AkihiroSuda or someone else familiar with slirp to verify the slirp address calculation bits. Overall looks good, few small comments.

@TomSweeneyRedHat
Copy link
Member

Nothing over @mheon's comments. @giuseppe if you have a spare eyeball for this, that would be great.

run_podman run --network slirp4netns:cidr=192.168.0.0/24,allow_host_loopback=true \
$IMAGE grep 192.168.0.2 /etc/hosts
is "$output" "192.168.0.2 host.gateway.internal" "host.gateway.internal should be the cidr+2 address"
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not feeling this behavior is correct.
The CIDR+2 address isn't useful when slirp4netns is launched with --disable-host-loopback.
And --disable-host-loopback should not be removed, as exposing bare 127.0.0.1 to containers might result in container-breakout.

I suggest exposing the "real" host IP regardless to rootful/rootless.

Copy link
Author

Choose a reason for hiding this comment

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

So what would be the alternative? Are you suggesting to derive all interface ip addresses not including lo?

The issue (#5651) was to add behavior that reflects docker's host.docker.internal.

I had a look through some of the docker code and as far as I can tell that is a configuration option given to the daemon so if a user asks for the host gateway address to be added to their container it is added based on that configuration docker-ce reference

So should podman have a similar configuration option?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Are you suggesting to derive all interface ip addresses not including lo?

The first interface (eth0) would be fine

Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure about this solution.

There can be so many different interfaces in so many different configurations that trying to derive an ip address from one of the interfaces seems unstable. I don't necessarily disagree that exposing the loopback interface to the container could result in a container breakout but this change doesn't give that access it simply puts a /etc/hosts entry for that interface.

Like I said above. I think the only viable alternative is to make the interface a configurable option similar to dockerd's --host-gateway-ip launch option.

Copy link
Author

Choose a reason for hiding this comment

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

@AkihiroSuda bump in case you didn't see my last response

Copy link
Collaborator

Choose a reason for hiding this comment

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

Having an option SGTM

depCtr, _ = c.getRootNetNsDepCtr()
} else if len(c.state.NetworkStatus) != 0 {
depCtr = c
} else {
Copy link
Member

Choose a reason for hiding this comment

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

This last block is not necessary. depCtr will be nil by default.

Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure syntactically how to get rid of that block 😬

I added it because I wanted to ensure mutual exclusion between shared container network namespace configurations and containers with network namespaces created for them. Basically I didn't want the situation where

        var depCtr *Container
	if c.config.NetNsCtr != "" { // **TRUE**
		// ignoring the error because there isn't anything to do
		depCtr, _ = c.getRootNetNsDepCtr()
	} 
	if len(c.state.NetworkStatus) != 0 { // **TRUE**
		depCtr = c
	}

But If that is not possible / something to worry about I can make them both if's and remove the unnecessary block

Copy link
Author

Choose a reason for hiding this comment

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

@rhatdan just in case you didn't see my response.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, that is fine.

} else if c.config.NetMode.IsSlirp4netns() {
hosts += fmt.Sprintf("%s host.gateway.internal\n", slirp4netnsGateway)
} else {
logrus.Debug("unexpected network configuration while determining host.gateway.internal address")
Copy link
Member

Choose a reason for hiding this comment

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

Is this unexpected, or would this just be the situation if I run a container with podman run --net=none ...

IE Is this worth logging?

Copy link
Author

Choose a reason for hiding this comment

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

This would be the case for podman run --net=none so I suppose it isn't that unexpected. Should I just quietly continue or change up the debug message?

Copy link
Author

Choose a reason for hiding this comment

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

@rhatdan bump just in case you didn't see my response

@rhatdan
Copy link
Member

rhatdan commented Apr 16, 2021

@bblenard Thanks for working on this.

@TomSweeneyRedHat
Copy link
Member

@rhatdan can you merge this if it LGTY? I think there was one last "is this OK" type of question for you in the review comments on this one.

@AkihiroSuda
Copy link
Collaborator

Bikeshedding: For consistency with host.docker.internal, the corresponding value for Podman should be host.podman.internal or host.containers.internal rather than host.gateway.internal?

@rhatdan
Copy link
Member

rhatdan commented Apr 27, 2021

Yes lets go with host.containers.internal and then we can merge.

@bblenard bblenard force-pushed the issue-5651-hostname-for-container-gateway branch from 7747541 to 724078f Compare April 28, 2021 00:21
@bblenard
Copy link
Author

I just pushed up some code and assuming the tests all pass there are just a few small things I want to make sure everyone is on the same page about:

  1. this thread. @AkihiroSuda mentioned their concerns about using the slirpns gateway address, we discussed a bit and contemplated using a configuration option to specify an ip address for the host.containers.internal address. @rhatdan / @mheon / @TomSweeneyRedHat thoughts? If that is the route we want to go I'll have to rework most of this code :)

  2. @rhatdan I wasn't sure what "Yes, that is fine." meant exactly so I left the code as it was. I can change it if I mis-interpreted your response though.

@AkihiroSuda
Copy link
Collaborator

The commit message ( host.gateway.internal ) seems to need to be updated

@bblenard bblenard force-pushed the issue-5651-hostname-for-container-gateway branch 2 times, most recently from 971e347 to f5e7b40 Compare May 4, 2021 23:25
@bblenard
Copy link
Author

bblenard commented May 4, 2021

The commit message ( host.gateway.internal ) seems to need to be updated

Fixed f5e7b40d66646b3e6517d989d8078110172808de

@rhatdan rhatdan changed the title Add host.gateway.internal entry into container's etc/hosts Add host.containers.internal entry into container's etc/hosts May 5, 2021
@rhatdan
Copy link
Member

rhatdan commented May 5, 2021

LGTM

@rhatdan
Copy link
Member

rhatdan commented May 5, 2021

@containers/podman-maintainers PTAL

return errors.Wrapf(err, "error calculating expected dns ip for slirp4netns")
}
// Save off calculated address into globals. I don't like this either
slirp4netnsIP = expectedIP.String()
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should use globals, this will fail when used with the podman service.

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I'll look at moving away from the globals. I think when I initially wrote this those were constant values that I changed to variables so I didn't even think about if they should be globals. Thanks for catching that :)

Copy link
Member

@Luap99 Luap99 May 7, 2021

Choose a reason for hiding this comment

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

I think you can add a new field (maybe called slirp4netnsSubnet) to the container struct here

type Container struct {

and add methods like GetSlirp4netnsIP, GetSlirp4netnsGateway and GetSlirp4netnsDNS which returns the correct ip calculated from the stored subnet.

Copy link
Author

@bblenard bblenard May 12, 2021

Choose a reason for hiding this comment

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

Fixed: c0335e77819e23be94bb55d883e18bdd6b742195

I made the helper functions generatl libpod functions that take subnets instead of Container functions that reference internal struct members because I didn't think it was a container specific thing. I also essentially reverted your changes here: f99b7a3 since I had a merge conflict and my changes covered what you did with that commit as far as I could tell.

@Luap99 I'll let you resolve these conversations if you think I properly addressed your comments.

@@ -314,9 +314,53 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
}
return r.setupRootlessPortMappingViaRLK(ctr, netnsPath)
}

// Calculate Slirp addresses now that we are pretty sure the command executed
Copy link
Member

@Luap99 Luap99 May 5, 2021

Choose a reason for hiding this comment

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

This block has to be above if havePortMapping...

Copy link
Author

Choose a reason for hiding this comment

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

I'll fix that once I figure out how to move away from globals like you suggested above.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed: c0335e77819e23be94bb55d883e18bdd6b742195

@bblenard bblenard force-pushed the issue-5651-hostname-for-container-gateway branch from f5e7b40 to 3ce696e Compare May 12, 2021 15:26
@openshift-ci openshift-ci bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 12, 2021
@bblenard bblenard force-pushed the issue-5651-hostname-for-container-gateway branch from 3ce696e to c0335e7 Compare May 12, 2021 16:14
@openshift-ci openshift-ci bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 12, 2021
Copy link
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

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

Thanks this looks good. One small nit.

if err != nil {
return nil, errors.Wrap(err, "failed to determine default slirp4netns DNS address")
}

Copy link
Member

Choose a reason for hiding this comment

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

The block below here should also use GetSlirp4netnsDNS for consistency.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed: ef6027b2db9d7ebd4a294af002c08c0c93d0e5db

hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", slirp4netnsIP, c.Hostname(), c.config.Name)
slirp4netnsIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet)
if err != nil {
logrus.Error("failed to determine slirp4netnsIP: ", err.Error())
Copy link
Member

Choose a reason for hiding this comment

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

This should be a warning not an error, If the user can not do anything about it, then it should just warn.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed: ef6027b2db9d7ebd4a294af002c08c0c93d0e5db

@Luap99
Copy link
Member

Luap99 commented May 12, 2021

@edsantiago PTAL at the system tests.

nameservers = append([]string{slirp4netnsDNS}, nameservers...)
slirp4netnsDNS, err := GetSlirp4netnsDNS(c.slirp4netnsSubnet)
if err != nil {
logrus.Error("failed to determine Slirp4netns DNS: ", err.Error())
Copy link
Member

Choose a reason for hiding this comment

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

Warning not Error.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed: ef6027b2db9d7ebd4a294af002c08c0c93d0e5db

} else if c.config.NetMode.IsSlirp4netns() {
gatewayIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet)
if err != nil {
logrus.Error("failed to determine gatewayIP: ", err.Error())
Copy link
Member

Choose a reason for hiding this comment

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

Warning not error.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed: ef6027b2db9d7ebd4a294af002c08c0c93d0e5db

@rhatdan
Copy link
Member

rhatdan commented May 12, 2021

LGTM once Error->Warnin

@@ -162,6 +162,24 @@ load helpers
done
}

@test "podman run with slirp4ns assigns correct gateway address to host.containers.internal" {
run_podman run --network slirp4netns:cidr=192.168.0.0/24 \
Copy link
Member

Choose a reason for hiding this comment

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

Just curious: what problem does random_rfc1918_subnet() have that prevents you from using it?

Copy link
Author

Choose a reason for hiding this comment

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

I wasn't aware of that function. I added it to the tests I wrote 👍

Copy link
Member

Choose a reason for hiding this comment

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

Thanks! One suggestion, though: I find string concatenation easier to read than stripping. Would you consider:

    subnet=$(random_rfc1918_subnet)
    ... :cidr="$subnet.0/24"
    .... grep "$subnet"
    ... nameserger "${subnet}.3"

That removes the need for all those complicated fragile %.*, and makes life much easier for future maintainers.

Copy link
Author

Choose a reason for hiding this comment

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

Sounds good. Fixed: c8dfcce

@bblenard bblenard force-pushed the issue-5651-hostname-for-container-gateway branch from c0335e7 to ef6027b Compare May 17, 2021 02:44
Copy link
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

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

LGTM

@openshift-ci
Copy link
Contributor

openshift-ci bot commented May 17, 2021

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bblenard, Luap99, mheon

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

This change adds the entry `host.containers.internal` to the `/etc/hosts`
file within a new containers filesystem. The ip address is determined by
the containers networking configuration and points to the gateway address
for the containers networking namespace.

Closes containers#5651

Signed-off-by: Baron Lenardson <[email protected]>
@bblenard bblenard force-pushed the issue-5651-hostname-for-container-gateway branch from ef6027b to c8dfcce Compare May 17, 2021 13:21
@@ -162,6 +162,27 @@ load helpers
done
}

@test "podman run with slirp4ns assigns correct gateway address to host.containers.internal" {
CIDR="$(random_rfc1918_subnet)"
Copy link
Member

Choose a reason for hiding this comment

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

Much better, thank you, but I'm kind of uncomfortable now with the variable name: a CIDR is defined as a full subnet, slash, and mask. A future maintainer may find this a stumbling point, and waste time (e.g. on line 169) wondering how a CIDR can have .2 appended. This is about a 3-out-of-10 gripe, I'm not going to insist on you changing it, but I'd like to bring it to the attention of others in case someone else on the team has a strong opinion either way.

@rhatdan
Copy link
Member

rhatdan commented May 17, 2021

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label May 17, 2021
@rhatdan
Copy link
Member

rhatdan commented May 17, 2021

Thanks @bblenard Nice work.

@openshift-merge-robot openshift-merge-robot merged commit 62a7d4b into containers:master May 17, 2021
@bblenard
Copy link
Author

Thanks @bblenard Nice work.

Thanks! I've been enjoying working on podman :)

@github-actions github-actions bot added the locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. label Sep 23, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

hostname for container gateway
9 participants