-
Notifications
You must be signed in to change notification settings - Fork 17
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 tests for distroless image #7
base: master
Are you sure you want to change the base?
Add tests for distroless image #7
Conversation
@danwinship any chance you can take a look? 🙏🏻 |
test/Dockerfile.test-distroless
Outdated
ebtables \ | ||
ipset \ | ||
iptables \ | ||
kmod && \ |
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.
You don't need any of those except iptables.
Also, I would just install iptables normally, without trying to do any weird optimizations. We don't need to optimize the size of the test image, and we don't want to be making any sorts of guarantees to users that "this is a supported way of optimizing the size of your image". They can figure that out on their own. (Or copy kubernetes on their own.)
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.
Changed, it only installs iptables now.
I kept the installations scripts I copied because that was faster than re-rewriting the dpkg stuff myself, so the weird optimization is still there (I guess you were referring to filtering everything except libraries and copyrights?). Please, take a look to the new version and if this still feels too complicated I'll rewrite the staging script.
test/Dockerfile.test-distroless
Outdated
iptables \ | ||
kmod && \ | ||
`# below binaries and dash are used by iptables-wrapper-installer.sh` \ | ||
/stage-binary-and-deps.sh "${STAGE_DIR}" /bin/dash \ |
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.
This is just the build image; none of these files should be needed in the final image, so there's no reason to do anything tricky with them, right? Just install the packages we need, run iptables-wrapper-installer.sh
, and then copy stuff to the final image.
Hm... I guess it's tricky to define exactly what "stuff" you need to copy to the final image though. (You want to copy all the iptables-package-related stuff, but nothing else.) Maybe we should have a binary installer for the distroless case. We don't even need that much. Just say that you copy iptables-wrapper
to the same directory as iptables
(presumably /sbin
) and then run iptables-wrapper --install
, and it will make the 6 necessary symlinks. (You already have most of the code to do that in the binary anyway...) Everything else in iptables-wrapper-installer.sh
is either superfluous (detecting fedora-vs-debian-vs-other) or optional (sanity-checking the iptables version).
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.
Ah that's a good idea, I added this.
Now the wrapper can be run like iptables-wrapper install <path>
and it will create symlink pointing to itself in the given path.
I went with the path being an explicit argument to avoid having to auto detect where iptables is. Depending on how you build the image, iptables
might not exist neither in /sbin
or /usr/sbin
. In that case, I would then need to start looking for iptables-nft
or iptables-legacy
, which adds a bit more complexity. Or create a fake iptables
executable somwhere, which is equivalent to passing the path explicitly. Let me know what you think.
test/Dockerfile.test-distroless
Outdated
|
||
FROM scratch | ||
|
||
COPY --from=intermediate / / |
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.
If you copy everything from intermediate
into the final image, then why not just use the "intermediate" image as the final result?
Anyway, I think Dockerfile.test-distroless
should look something like:
FROM debian:bullseye-slim as build
# FIXME install iptables
# FIXME use dpkg to figure out all the packages that iptables depends on
# FIXME use dpkg to figure out all of the files in all of the packages from the previous list
# FIXME copy all of those files to ${STAGE_DIR}
FROM gcr.io/distroless/static
COPY --from=build "${STAGE_DIR}" /
COPY bin/iptables-wrapper /sbin
RUN /sbin/iptables-wrapper --install
COPY bin/tests /
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.
Yeah this was great feedback. This is more or less what the dockerfile does now. But as I wrote in a previous comment, I kept the staging scripts.
fi | ||
if ! docker run --privileged "iptables-wrapper-test-${tag}" /tests -test.v -test.run "^TestIPTablesWrapperNFT$" ; then | ||
FAIL "failed nft iptables" | ||
fi |
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.
Is there some reason for running them separately like this rather than just doing a single docker run
for the whole test suite?
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.
Yeah, running one test modifies the container (the symlinks are altered to point to a particular mode).
So instead of building some kind of cleanup in the tests that try to undo all the changes and restore the initial state, I just run them in different containers. It seemed simpler.
if err != nil { | ||
tb.Fatal(err.Error()) | ||
} | ||
} |
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.
so... yeah, I just think this is far too complicated. The existing shell-based test is short and simple. This is a lot more complex, and the only reason for doing it this way is that you can test that iptables-wrapper
works correctly in an image that doesn't contain /bin/sh
, which is something that we have no reason to believe would actually be a problem, given that iptables-wrapper
never execs anything except iptables.
If we really want to test that case, a simpler way to do it would be to have a normal debian or alpine or whatever install at the top level, and have the "install" image still be in /opt/stage
or whatever, and change test.sh
so that instead of calling iptables ...
, it calls chroot /opt/stage iptables ...
. Then test.sh
can depend on whatever it wants, but iptables-wrapper
is forced to only use the things in its chroot.
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's fair. Although this also adds tests for IPv6, which I think it represents a different codepath and wasn't tested before IIRC, so some of the complexity comes from there.
That said, I would prefer to keep this unless you feel extremely against it. I understand what you are saying about not needing to validate that this works in an image without shell. And for it is worth, I agree with you, we have no reason to think it wouldn't work. However, isn't that what the distroless test is trying to verify? That the iptables-wrapper works in a distroless image.
The Kubernetes project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
/remove-lifecycle stale |
The Kubernetes project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
The Kubernetes project currently lacks enough active contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
/remove-lifecycle rotten |
The Kubernetes project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
The Kubernetes project currently lacks enough active contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
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.
re: test image: Let's just take the upstream distroless-iptables image as a base image and substitute in the new wrapper script/binary for testing?
that seems less fragile than maintaining a near-copy of it here.
We don't want to test "it works with the current distroless-iptables that has all sorts of stuff to support the old iptables-wrappers" though, we want to test "it works in a distroless image". The image that gets built by the current version of this PR is much more complicated than it needs to be, and I suggested some changes in review comments. |
Hey folks! Sorry I completely forgot about this. |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: g-gaston The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
--slave /usr/sbin/ip6tables iptables /usr/sbin/iptables-wrapper \ | ||
--slave /usr/sbin/ip6tables-restore iptables-restore /usr/sbin/iptables-wrapper \ | ||
--slave /usr/sbin/ip6tables-save iptables-save /usr/sbin/iptables-wrapper | ||
--slave /usr/sbin/ip6tables ip6tables /usr/sbin/iptables-wrapper \ |
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 could be wrong here bu I think before this change it wasn't creating symlinks for ip6tables-*
because the name overlapped with the previous slaves. Or at least that's what I found during testing.
@@ -19,11 +19,11 @@ FROM debian:buster | |||
ARG INSTALL_ARGS= | |||
ARG REPO=buster | |||
|
|||
RUN echo deb http://deb.debian.org/debian buster-backports main >> /etc/apt/sources.list; \ | |||
RUN echo deb http://archive.debian.org/debian buster-backports main >> /etc/apt/sources.list; \ |
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.
they changed this url for buster and that broke the test
/remove-lifecycle rotten |
@danwinship addressed comments, pls take a look when you have some time |
Follow up on #6
In order to run the tests in a distroless image, I rewrote them in Go so we can compile them to a static binary and just copy to the image. They work pretty much like the bash version. In addition they also check that the ip6tables binary resolves correctly. I also added a couple of tests for rules added for ip6.
The distroless image is pretty much a copy of what's used in https://github.com/kubernetes/release/blob/master/images/build/distroless-iptables/distroless, but with a few tweaks to drop the extra dependencies like dash. We could maybe simplify it if we didn't use the installer script.