-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Fix: setup user chains during libnetwork controller initialization #48577
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
Conversation
b5c757e
to
3590816
Compare
Thanks for working on this @am97! Since most of our iptables rules live in the Unfortunately, the bridge driver has the same weird logic: create ipt chains during driver initialization, and then insert the appropriate JUMP rules when a network is created. We'll refactor that package soon to initialize all rules during driver init (we've work in progress in this area). As such, could you move the |
I considered The
The problem is the
instead of
I can duplicate a part of the logic in |
Yikes, you're right! Let's keep this change as is, and we'll move this rule to the bridge driver once we shuffle things around. |
3590816
to
f0f9dfc
Compare
I see the test fails on rootless, that seems normal, as the daemon sets up an unprivileged network stack and has not access to iptables. Is it OK if I just skip the test for rootless ? There is also this failure: https://github.com/moby/moby/actions/runs/11212045759/job/31163919736?pr=48577 |
I'm also seeing this flaky test on one of my PR, so I think it's safe to ignore:
I don't recall exactly how rootless mode interacts with iptables. I'll have a look and keep you posted. |
This looks good to me - it just needs the skip for rootless mode (the iptables rules live in a network namespace belonging to rootlesskit, and the test is looking in the host namespace, so it just doesn't see them - I don't think the |
ac6b5cd
to
48b7adc
Compare
I added the skip for rootless mode. Let me know if I should squash my commits. |
Great - thank you! And yes, please squash them. Just to check, in the second commit, that swaps an error return for a log line to avoid an error in tests ... what was the error? (As far as I can see, SetupUserChains only returns an error from setupUserChain, which checks whether rules already exist before it tries to change things.) |
In the changelog comment, it'd be good to say why the change is needed. Maybe something like ... "After a daemon restart with live-restore, ensure an iptables jump to the DOCKER-USER chain is placed before other rules." |
Ok ! I'll squash them after the discussion.
In
Here is the full The host was a Debian 11 with a default installation of Docker 27.3.1, which doesn't enable IPv6, so the
That's better, thanks ! I updated the description. |
Thanks @am97, that makes sense. The error was only logged the error before, so we should keep it that way ... the change looks fine as it is. |
Currently, the DOCKER-USER chains are set up on firewall reload or network creation. If there are running containers at startup, configureNetworking won't be called (daemon/daemon_unix.go), so the user chains won't be setup. This commit puts the setup logic on a separate function, and calls it on the original place and on initNetworkController. Signed-off-by: Andrés Maldonado <[email protected]>
48b7adc
to
a8bfa83
Compare
Ok ! I squashed my commits, the PR is ready to be merged |
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 - thank you.
} | ||
|
||
if err := daemon.netController.SetupUserChains(); err != nil { | ||
log.G(context.TODO()).WithError(err).Warnf("initNetworkController") |
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 it's not a good idea to just log this error, even if that was the old behavior.
Based on previous messages, it's not entirely clear why integration tests were failing.
The host was a Debian 11 with a default installation of Docker 27.3.1, which doesn't enable IPv6
Since IPv6 is now enabled by default, making IPv6-ness a requirement for running integration tests seems to be reasonable. Even with net.ipv6.conf.default.disable_ipv6=1
set on the host, make shell
should offer an IPv6-capable dev container. Also, IPv6-ness doesn't imply IPv6 connectivity - so it should be fine in most cases.
We also support running integration tests outside of make shell
dev containers, but then it's dev's responsibility to correctly configure their host.
IMHO initNetworkController
should error out if user chains can't be configured.
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.
After discussing with @robmry internally, I think that's something we should fix separately.
#47918 turned some IPv6 errors into logs to allow users with non-IPv6-capable hosts to still start the daemon, even without --ip6tables=false
specified. If we error out when SetupUserChains
fails, we'll break that.
We should look at auto-detecting IPv6-ness and disabling ip6tables when it's not supported in a follow-up PR. Then, if the host is found to be IPv6-capable, but SetupUserChains
fails, it'd be a hard error.
fixes #48560
Currently, the
DOCKER-USER
chains are set up when the firewall is reloaded or when a network is created:moby/libnetwork/controller.go
Lines 709 to 715 in 4001d07
During a normal startup, the daemon creates the
bridge
network, so theDOCKER-USER
chains are set up.But when
live-restore
is enabled, there may be running containers when the daemon starts. If that's the case, theconfigureNetworking
function will not be called:moby/daemon/daemon_unix.go
Lines 848 to 852 in 4001d07
configureNetworking
callsinitBridgeDriver
, which callsNewNetwork
, which callssetupUserChain
, so ifconfigureNetworking
isn't called the user chains won't be set up.This is a problem if the iptables rules change while the daemon is stopped.
- What I did
I made sure the user chains are set up on startup, even if the
configureNetworking
function is not called- How I did it
I put the logic for setting up user chains for IPv4 and IPv6 in a separate function, which is called in the original place in
NewNetwork
, but also ininitNetworkController
even if there are running containers.- How to verify it
I still didn't write an integration test, I'll add it when I have some time.
To manually test:
dockerd --live-restore
docker run -d busybox sleep 300
FORWARD
chain:iptables -F FORWARD
dockerd --live-restore
iptables -S FORWARD
-A FORWARD -j DOCKER-USER
should be there- Description for the changelog
- A picture of a cute animal (not mandatory but encouraged)