Skip to content

Support for troubleshooting distroless containers  #27140

Closed

Description

@verb

I favor running distroless container images in production, usually built from SCRATCH with the binary and bare minimum of libraries. This has a number of benefits and works well the vast majority of the time, but it's difficult on the occasion where I need to troubleshoot something in production.

It'd be nice if there was a way to enable some sort of debug mode for a running pod where a set of tools could be attached that I could then exec within the container.

I'm willing to do the work to develop this feature, if necessary, but I'm not exactly sure what the next steps should be. I'm opening this issue to find out if anyone is working on something similar and/or get early guidance on how this could fit into the Kubernetes road map.

If it's the case that no one else is working on something similar and such a feature would be welcomed, my expectation is the next step would be to write a design proposal.

Tracking issue: kubernetes/enhancements#277
KEP: https://git.k8s.io/enhancements/keps/sig-node/20190212-ephemeral-containers.md
PRs:

Activity

  1. therc commented on Jun 13, 2016

    @therc
    Contributor

    Maybe just use shared PID namespaces in Docker 1.12 (and rkt's equivalent, if/when it's there): moby/moby#10163

    You'd create a new container with a debug image (or one of many) and attach it to the existing pod.

  2. verb commented on Jun 13, 2016

    @verb
    ContributorAuthor

    Ah, that would be perfect! I see that #1615 exists for sharing a PID namespace in a pod, which also led me to discover this issue may very well be a dupe of #24957 (though @smarterclayton only mentions debugging as one of many possible uses).

    Before I close this issue as a dupe, I just want to make sure I understand how it would work. I see two possibilities --

    1. We attach a new container to a running pod. I assume this would look something like a kubectl attach, but if I try to do this in 1.2 I get the error spec.containers: Forbidden: pod updates may not add or remove containers. (am I doing this incorrectly?)
    2. We create a new pod using the PID namespace of the target pod we want to debug, in which case we would want support for that in the implementation of shared PID namespaces.

    Though not as useful as a debug container, something that could work in the interim would be to attach a volume to a running container, if that were possible. (In 1.2 it doesn't seem to be: spec: Forbidden: pod updates may not change fields other than containers[*].image or spec.activeDeadlineSeconds)

  3. smarterclayton commented on Jun 13, 2016

    @smarterclayton
    Contributor

    Today, it's not possible to mutate a running pod. Attach connects to an existing container (if the Stdin and/or TTY flags were set).

    Another option beyond those you mention above would be to allow adhoc container execution inside of a pod that mounts the majority of the namespaces of another container. I.e.:

    1. Have pod 1 with containers A and B
    2. Launch a transient container C that attaches to container A inside of pod 1:
      1. C shares the pid namespace of A
      2. C mounts the filesystem of A at /mnt/attach (or similar)
      3. C also joins other namespaces of A as necessary, esp. cgroup (or pod cgroup)

    Scheduling a new pod doesn't convey to the runtime that C should be cleaned up if 1/A is removed (which we want, probably). However, in the flow above C would have to share resources with A so there are various edge cases around guaranteed pods having no more CPU to spare for C.

    Another option would be to implement container volumes #831 and mount your debug tools into your bare bones image. That's not adhoc though, so it doesn't quite fit your use case.

  4. davidopp commented on Jun 24, 2016

    @davidopp
    Contributor

    General observation: if we're going to make it possible to add containers to pods, we should do it in a general way, not just to cover this use case.

    I can't imagine we're going to implement adding containers to pods soon though.

  5. verb commented on Jul 8, 2016

    @verb
    ContributorAuthor

    I've gotten a lot of great suggestions so far, so I thought I'd summarize them:

    1. Volume solutions make binaries available for kubectl exec inside of a running container
      1. Allow mutation of a running container (via kubectl patch or equivalent) to add volumes. This would be especially useful in conjunction with Image volumes and container volumes #831 to support container images as volumes.
      2. Implicitly create a unique, empty volume attached to every container that's run. Tools can be unpacked into this volume at debug time, perhaps using an existing package solution like nix or SNAP. (credit: @thockin)
    2. Container solutions run a new container process in shared namespaces. The debug container image (obviously) brings its own filesystem, so the filesystem roots (including volume mounts) of other containers must be made available to the debug container somehow.
      1. Extend kubectl exec to allow executing commands from arbitrary container images which are then automatically fetched and run within the existing pod cgroup/pid/net/etc namespaces. (e.g. kubectl exec 123456-7890 -X gcr.io/debug-image -i -t -- bash)
      2. Allow permanent mutation of a running pod to add a new container using the standard shared pod namespaces (requires at least Shared PID and UTS namespaces #1615 for a pod shared PID namespace).
      3. Support creating a new, standalone pod that uses the same namespace as the target pods.
    3. Node solutions (for lack of a better term) are independent of the pod/container constructs.
      1. Support running binaries provided by the node inside the container namespaces (Make it possible to shell into any container, even if it has no shell #10834). This could be an extension of kubectl as well (e.g. kubectl exec 123456-7890 -H /bin/busybox -i -t)

    I'm not yet familiar with the kubernetes implementation, but the volume solutions strike me as the easiest to implement and those requiring mutation of pods the most difficult.

    The solutions that extend kubectl exec "feel" the most natural to me as a user. The backend steps (read: docker commands to run) seem conceptually straightforward, but there may be some technical hurdles (e.g. I'm getting ptrace not permitted when attempting to strace across container images, but that's happening within the same image as well).

    I don't like coupling this functionality to the node, so I'll start down the road of writing a proposal to support kubectl exec of arbitrary container images (2i in the above list).

  6. thockin commented on Jul 8, 2016

    @thockin
    Member

    The idea of running a "toolbox" container that is not part of a pod, but has the same namespaces as the pod is cute, but a little scary and opaque.

    If we allowed adding a container to a pod, it could just be a shiny form of that.

    Another option might be to include a container in the pod that is "inactive" until later activated.

  7. erictune commented on Jul 8, 2016

    @erictune
    Contributor

    How far do you get if you have your build system produce "debug" and "stripped" versions of your container image ("debug" has a base image with a debugger, and "stripped" does not)?

    Normally, your service just has "stripped" containers, but if there is an active bug, you deploy one or more extra containers for that service which are "debug images", and wait for the problem to happen again.

    Doesn't help if the problem only happens once, but who has time to debug that kind of problem anyhow?

  8. erictune commented on Jul 8, 2016

    @erictune
    Contributor

    The key question I think is whether you do this by making a new pod, and pods stay immutable, or if we make pods mutable.

  9. verb commented on Jul 8, 2016

    @verb
    ContributorAuthor

    @thockin I'll grant you scary, but I'm not yet willing to concede that pulling in a different userland for a binary is any more opaque than your run-of-the-mill kubectl exec. Both seem solvable.

    I'd be happy with an inactive container as long as it (optionally) automatically updates prior to activating so I'm not tied to an old debug image. The downside here is the extra boilerplate config in every pod I run.

  10. smarterclayton commented on Jul 8, 2016

    @smarterclayton
    Contributor

    I should note that we've had very good feedback from the "debug" command
    (which spawns a copy of the pod with a shell, or other command, as the
    target). It doesn't address the "I created a pod that has nothing useful
    in it to debug", but it does address the bulk of the practical "w.t.h. is
    this not starting up correctly" problems.

    On Fri, Jul 8, 2016 at 7:16 PM, verb notifications@github.com wrote:

    @thockin https://github.com/thockin I'll grant you scary, but I'm not
    willing to concede that pulling in a different userland for a binary is any
    more opaque than your run-of-the-mill kubectl exec. Both seem solvable.

    I'd be happy with an inactive container as long as it (optionally)
    automatically updates prior to activating so I'm not tied to an old debug
    image. The downside here is the extra boilerplate config in every pod I run.

    —
    You are receiving this because you were mentioned.
    Reply to this email directly, view it on GitHub
    #27140 (comment),
    or mute the thread
    https://github.com/notifications/unsubscribe/ABG_p2uVpzBsO1U8z8rTGXRCBPFQimVuks5qTtpXgaJpZM4IyRHU
    .

  11. smarterclayton commented on Jul 8, 2016

    @smarterclayton
    Contributor

    Debug also leads naturally to other hooks like
    "--attach-and-mount=IMAGENAME" for getting access to debug tools.

    On Fri, Jul 8, 2016 at 7:31 PM, Clayton Coleman ccoleman@redhat.com wrote:

    I should note that we've had very good feedback from the "debug" command
    (which spawns a copy of the pod with a shell, or other command, as the
    target). It doesn't address the "I created a pod that has nothing useful
    in it to debug", but it does address the bulk of the practical "w.t.h. is
    this not starting up correctly" problems.

    On Fri, Jul 8, 2016 at 7:16 PM, verb notifications@github.com wrote:

    @thockin https://github.com/thockin I'll grant you scary, but I'm not
    willing to concede that pulling in a different userland for a binary is any
    more opaque than your run-of-the-mill kubectl exec. Both seem solvable.

    I'd be happy with an inactive container as long as it (optionally)
    automatically updates prior to activating so I'm not tied to an old debug
    image. The downside here is the extra boilerplate config in every pod I run.

    —
    You are receiving this because you were mentioned.
    Reply to this email directly, view it on GitHub
    #27140 (comment),
    or mute the thread
    https://github.com/notifications/unsubscribe/ABG_p2uVpzBsO1U8z8rTGXRCBPFQimVuks5qTtpXgaJpZM4IyRHU
    .

  12. verb commented on Jul 8, 2016

    @verb
    ContributorAuthor

    @erictune Certainly workable, but I'm concerned about some downsides:

    1. We'd want use the same image for QA as in prod, but then how do we QA the debug image? What if the stripped and debug images differ somehow?
    2. We're coupled with the debug environment we had at build time rather than the ones available at debug time
    3. The goal is minimal dependencies, but I'd have to include the debug tools (and all of their ongoing updates) as dependencies, which would be hard to track. (i.e. I need to apply a security update for an image that's not currently running but could be running if I needed to debug something in the future)

    Even if I can't think of it right now, I'm confident there will eventually be a reason that I'll need to connect to a stripped container and it seems like a bit of a gap in the toolbox.

  13. added
    priority/backlogHigher priority than priority/awaiting-more-evidence.
    sig/nodeCategorizes an issue or PR as relevant to SIG Node.
    on Jul 18, 2016
  14. 35 remaining items

  15. verb commented on Jan 28, 2020

    @verb
    ContributorAuthor

    /remove-lifecycle stale

  16. removed
    lifecycle/staleDenotes an issue or PR has remained open with no activity and has become stale.
    on Jan 28, 2020
  17. fejta-bot commented on Apr 27, 2020

    @fejta-bot

    Issues go stale after 90d of inactivity.
    Mark the issue as fresh with /remove-lifecycle stale.
    Stale issues rot after an additional 30d of inactivity and eventually close.

    If this issue is safe to close now please do so with /close.

    Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
    /lifecycle stale

  18. added
    lifecycle/staleDenotes an issue or PR has remained open with no activity and has become stale.
    on Apr 27, 2020
  19. verb commented on Apr 27, 2020

    @verb
    ContributorAuthor

    /remove-lifecycle stale

  20. fejta-bot commented on May 27, 2020

    @fejta-bot

    Stale issues rot after 30d of inactivity.
    Mark the issue as fresh with /remove-lifecycle rotten.
    Rotten issues close after an additional 30d of inactivity.

    If this issue is safe to close now please do so with /close.

    Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
    /lifecycle rotten

  21. added
    lifecycle/rottenDenotes an issue or PR that has aged beyond stale and will be auto-closed.
    and removed
    lifecycle/staleDenotes an issue or PR has remained open with no activity and has become stale.
    on May 27, 2020
  22. warmchang commented on May 28, 2020

    @warmchang
    Contributor

    /remove-lifecycle rotten

  23. removed
    lifecycle/rottenDenotes an issue or PR that has aged beyond stale and will be auto-closed.
    on May 28, 2020
  24. fejta-bot commented on Aug 26, 2020

    @fejta-bot

    Issues go stale after 90d of inactivity.
    Mark the issue as fresh with /remove-lifecycle stale.
    Stale issues rot after an additional 30d of inactivity and eventually close.

    If this issue is safe to close now please do so with /close.

    Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
    /lifecycle stale

  25. added
    lifecycle/staleDenotes an issue or PR has remained open with no activity and has become stale.
    on Aug 26, 2020
  26. verb commented on Aug 27, 2020

    @verb
    ContributorAuthor

    This issue has become a sort of tracking issue for the overall problem of troubleshooting distroless containers, but tracking issues are a poor fit for k/k: the discussion dies down and it just into fighting lifecycle.

    This issue motivated two enhancements: kubernetes/enhancements#277 (Ephemeral containers) and kubernetes/enhancements#1441 (kubectl debug). Let's track these efforts in their feature issues and consider this k/k issue closed.

  27. added a commit that references this issue on Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

lifecycle/staleDenotes an issue or PR has remained open with no activity and has become stale.priority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to complete.sig/nodeCategorizes an issue or PR as relevant to SIG Node.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions