-
Notifications
You must be signed in to change notification settings - Fork 887
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
Use distroless image to build controller and speaker containers #2418
Conversation
d357807
to
aa930fa
Compare
Also, the cp-tool is a good addition to solve this. Thank you! One thing I thought of that might happen is if you debug twice on the same pod. It'll fail I reckon. Not that I think it'll happen now, but just adding here if someone hits this bug and wants to resolve. Amazing work and I thank you deeply for making the efforts we had come to a reality, I am truly glad |
a04d45e
to
e7746b0
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.
awesome work! thanks a lot
can you also squash your commits into one with the gist of the change?(https://metallb.io/community/#commit-messages)
e2etest/pkg/executor/executor.go
Outdated
if Kubectl == "" { | ||
return "", errors.New("the kubectl parameter is not set") | ||
} | ||
fullargs := append([]string{"debug", "-it", "-n", pd.namespace, pd.name, "-c", "pod-executor-debugger", "--image=busybox", "--", cmd}, args...) |
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 should randomize the container name here pod-executor-debugger-..
, the reason being that if you run the same debug container multiple times it only remembers the first output (the first debug command that caused the container to be terminated) which could cause confusion if the test is ran multiple times on the same cluster
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.
A randomized string (length=5) was added to the pod executor debugger.
// add ephemeral container to deal with distroless image | ||
type podDebugExecutor struct { | ||
namespace string | ||
name 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.
wdyt about addibg an image for the container here (instead of defaulting to busybox)? this will make the call for ForPodDebug
more resemblant to the usual kubectl debug
where the caller specifies the image.
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.
added the randomized string for debugger.
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.
image name is configurable now.
frr-tools/cp-tool/cp-tool.go
Outdated
sourceFile = filepath.Clean(sourceFile) | ||
destinationFile = filepath.Clean(destinationFile) | ||
|
||
err = cp.Copy(sourceFile, destinationFile) |
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.
did you try something that doesn't require importing another dependency? I wonder if we can just do this with some io.Copy
(or anything else from the standard library) that wouldn't be too messy since our usecase is pretty simple
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.
Originally there was file permission issue for the local copy tool when using io.Copy, so I switched to a community package. With the new submission, I've added the preserve permission functionality, so it should be clean now.
frr-tools/cp-tool/cp-tool.go
Outdated
) | ||
|
||
func main() { | ||
logger, err := logging.Init("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.
we don't really need a logger here, let's just panic / fmt.Printf on the few occasions where needed
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.
logger removed.
755b9b4
to
4878b57
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.
left a few small comments, looks really good!
also, please change the commit message to be more about "what is the change" and not "how we changed" :)
approved, cc @fedepaol to also give this a look
frr-tools/cp-tool/cp-tool.go
Outdated
sourceFile = filepath.Clean(sourceFile) | ||
destinationFile = filepath.Clean(destinationFile) |
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.
small nit: this is probably redundant with the one happening inside the function
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.
removed the redundant part.
frr-tools/cp-tool/cp-tool.go
Outdated
func CopyFile(srcFile string, destFile string) error { | ||
srcFile = filepath.Clean(srcFile) | ||
destFile = filepath.Clean(destFile) |
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.
nit: rename the input to src,dst (so the new vars are declared with new names)
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.
renamed the inputs
frr-tools/cp-tool/cp-tool.go
Outdated
} | ||
|
||
srcPerm := srcStat.Mode().Perm() | ||
fmt.Printf("File permission before copying %v \n", srcPerm) |
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.
nit: I think we can remove it (unless you think this adds value)
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.
removed after checking the functionality.
frr-tools/cp-tool/cp-tool.go
Outdated
dstStat, err := os.Stat(destFile) | ||
if err != nil { | ||
err = fmt.Errorf("failed to check stats for %s: %w", destFile, err) | ||
return err | ||
} | ||
|
||
dstPerm := dstStat.Mode().Perm() | ||
fmt.Printf("File permission After copying %v \n", dstPerm) |
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.
same?
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.
removed after checking the functionality.
34d7943
to
7370af4
Compare
e2etest/pkg/executor/executor.go
Outdated
return "", errors.New("the kubectl parameter is not set") | ||
} | ||
|
||
imagearg := "--image=" + pd.image |
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.
nit: imageArg, targetArg, debuggerArg
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
@@ -170,7 +170,7 @@ var _ = ginkgo.Describe("L2-interface selector", func() { | |||
}, 1*time.Minute, 1*time.Second).Should(Not(HaveOccurred())) | |||
speakerPod, err := metallb.SpeakerPodInNode(cs, svcNode.Name) | |||
Expect(err).NotTo(HaveOccurred()) | |||
selectorMac, err := mac.GetIfaceMac(NodeNics[0], executor.ForPod(speakerPod.Namespace, speakerPod.Name, "speaker")) | |||
selectorMac, err := mac.GetIfaceMac(NodeNics[0], executor.ForPodDebug(speakerPod.Namespace, speakerPod.Name, "speaker", "busybox")) |
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 only concern I have here is relying on another image (from dockerhub, also), which may result in hitting the pull limits. How about using the agnhost image we are already using here (assuming it already has all we need to debug)?
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.
good idea! changed.
@@ -288,3 +288,11 @@ Additionally, the status of the service and of the endpoints must be provided: | |||
kubectl get endpointslices <my-service> -o yaml | |||
kubectl get svc <my_service> -o yaml | |||
``` | |||
|
|||
### How to debug a container with distroless image |
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.
### How to debug a container with distroless image | |
### How to debug the speaker and the controller 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.
changed..
|
||
### How to debug a container with distroless image | ||
|
||
With the distroless solution, if someone needs to debug inside speaker container, an ephemeral container should be used: |
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.
With the distroless solution, if someone needs to debug inside speaker container, an ephemeral container should be used: | |
Due to the fact that both the speaker and the controller containers are based on a distroless image, an ephemeral container should be used to debug inside them: |
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.
modified.
Also, I'd reword the release notes section, saying that now the speaker and the controller are based on distroless. |
cf72ae7
to
a998591
Compare
Signed-off-by: Min Zhang <minzhang@redhat.com>
5248b62
to
c3439b7
Compare
LGTM |
Inspired by #2117
fixes #2110
A big thank you to @oribon and @georgettica for the detail discussion in #2117 which is the design document I followed to this solution. Also appreciate @oribon 's help during design implementation, that I was able to run local integration and e2e tests!
Is this a BUG FIX or a FEATURE ?:
/kind feature
What this PR does / why we need it:
gcr.io/distroless/static base image is used to replace the original docker.io/alpine image, for a distroless solution that controller and speaker images will be built from scratch. Since distroless base image has no shell entry, there are two major impacts with this solution:
In this PR, a local copy tool (cp-tool) was introduced to cope with the first concern, and a podDebugExecutor was introduced under e2etest to attach a debug ephemeral container when there is a need to execute additional commands.
Special notes for your reviewer:
Release note: