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

Consider switching to ghcr.io/distroless images #4752

Closed
mattmoor opened this issue Apr 12, 2022 · 15 comments · Fixed by #4765
Closed

Consider switching to ghcr.io/distroless images #4752

mattmoor opened this issue Apr 12, 2022 · 15 comments · Fixed by #4765
Labels
kind/feature Categorizes issue or PR as related to a new feature.

Comments

@mattmoor
Copy link
Member

We have been starting to pursue (with apko) the next generation of "distroless" tooling, and that has made curating images with complex dependencies (e.g. git) much more tractable than the old model. I chased the idea of "distroless git" years ago when we were starting knative/build and the dependency tree made this a nightmare, but with the new tooling, it's actually very tight!

I put together github.com/distroless/git largely based on the Tekton Dockerfile's apk add line: https://github.com/distroless/git/blob/1473a6a03596395baa6e99221405467c94f69798/.apko.yaml#L8-L10

Since this is a "distroless" image, it is actually smaller than what y'all have today (though since the bulk of it is from git, the difference isn't huge):

ls -l *.tar
-rw-r--r--  1 mattmoor  staff  35812864 Apr 12 08:18 bar.tar  <-- apko
-rw-r--r--  1 mattmoor  staff  38889472 Apr 12 08:09 foo.tar  <-- upstream (Dockerfile)

Another place worth considering a switch is your use of gcr.io/distroless/base:debug for your "shell image" here:

# The shell image must be root in order to create directories and copy files to PVCs.
# gcr.io/distroless/base:debug as of February 17, 2022
# image shall not contains tag, so it will be supported on a runtime like cri-o
"-shell-image", "gcr.io/distroless/base@sha256:3cebc059e7e52a4f5a389aa6788ac2b582227d7953933194764ea434f4d70d64",

This uses base:debug vs. static:debug because the latter doesn't exist, but really all you are after is the fact that :debug contains busybox. We created github.com/distroless/busybox for this, which (without glibc) is considerably smaller:

ls -l *.tar
-rw-r--r--  1 mattmoor  staff   5142016 Apr 12 12:52 bar.tar  <-- apko
-rw-r--r--  1 mattmoor  staff  23222272 Apr 12 12:51 foo.tar  <-- upstream distroless

We have been using ghcr.io/distroless/git and ghcr.io/distroless/busybox for each of these in our downstream testing for several days now without issue, and so I wanted to start a discussion around replacing these upstream (and eliminating the need to maintain the git-init Dockerfile + builds)...

cc @vdemeester @imjasonh @dlorenc @bobcatfish

@mattmoor mattmoor added the kind/feature Categorizes issue or PR as related to a new feature. label Apr 12, 2022
@mattmoor
Copy link
Member Author

cc @afrittoli

@imjasonh
Copy link
Member

+1 to smaller images, but especially +1 to simpler, more declarative images.

Just so I can concretely understand the proposal:

  • replace -shell-image with ghcr.io/distroless/busybox -- seems like a simple drop-in replacement 👍
  • replace git-init's base image with ghcr.io/distroless/git
    • delete this Dockerfile, which is the only thing left in images/
    • this lets us delete the dind-based multiarch build for that base image, which means we drop its privilege:

securityContext:
privileged: true

I think it's definitely worth drafting a PR for, to get an idea what else shakes out from this. But I'm definitely happy with what I'm seeing so far. 😍

@mattmoor
Copy link
Member Author

@imjasonh I'd probably split the switchover from deleting the Dockerfile, in case we want a really simple rollback, but that should definitely be the goal!

@vdemeester
Copy link
Member

I do not see any reason not to switch to it so 👍🏼

@mattmoor
Copy link
Member Author

Cool, I will try to draft the first part today. Then I'll stage something to try to remove the rest, which we can merge once we are comfortable with the switchover (I'll need help making sure I caught everything, but I'll start with @imjasonh fantastic list! 🤩 )

@mattmoor
Copy link
Member Author

Alright, I kicked it and it picked up 2.35.2 from edge, so I'll send this shortly:

# docker run -ti ghcr.io/distroless/git --version
Unable to find image 'ghcr.io/distroless/git:latest' locally
latest: Pulling from distroless/git
27865ba1f7a8: Pull complete
Digest: sha256:b8ac8e9fc0b2dcafb666e68f56fe808fa7103da9e8b3d6f23a6cde4d54be22a2
Status: Downloaded newer image for ghcr.io/distroless/git:latest
git version 2.35.2

@mattmoor
Copy link
Member Author

So grepping the code base, I also found tekton/publish.yaml rewrites .ko.yaml for windows support, and also adds (back?) several baseImageOverrides. I think this should be:

  - name: create-ko-yaml
    image: golang:1.17.8
    script: |
      #!/bin/sh
      set -ex

      # Setup docker-auth
      DOCKER_CONFIG=~/.docker
      mkdir -p ${DOCKER_CONFIG}
      cp /workspace/docker-config.json ${DOCKER_CONFIG}/config.json

      # Change to directory with vendor/
      cd ${PROJECT_ROOT}

      # Combine Distroless with a Windows base image, used for the entrypoint image.
      COMBINED_BASE_IMAGE=$(go run ./vendor/github.com/tektoncd/plumbing/cmd/combine/main.go \
        ghcr.io/distroless/busybox \
        mcr.microsoft.com/windows/nanoserver:1809 \
        ${CONTAINER_REGISTRY}/$(params.package)/combined-base-image:latest)

      cat <<EOF > ${PROJECT_ROOT}/.ko.yaml
      # This matches the value configured in .ko.yaml
      defaultBaseImage: gcr.io/distroless/static:nonroot
      baseImageOverrides:
        # Use the combined base image for images that should include Windows support.
        $(params.package)/cmd/entrypoint: ${COMBINED_BASE_IMAGE}
        $(params.package)/cmd/nop: ${COMBINED_BASE_IMAGE}
        $(params.package)/cmd/workingdirinit: ${COMBINED_BASE_IMAGE}

        # This matches values configured in .ko.yaml
        $(params.package)/cmd/git-init: ghcr.io/distroless/git
      EOF

      cat ${PROJECT_ROOT}/.ko.yaml

... but want to sanity check. I'll include this in my PR, but please pay attention and check my work because I kinda doubt this is tested presubmit 😅

mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 13, 2022
This swaps out the use of `gcr.io/distroless/base:debug` for the new `ghcr.io/distroless/busybox` image (since the former was being used exclusively for it having busybox).

This also swaps our the `Dockerfile` based `git-init` base image in favor of `ghcr.io/distroless/git` since it is now possible to produce a `distroless` Git image without losing one's sanity.

This does NOT remove the `Dockerfile` or any logic to build it just yet, in case we want to roll this back, but that should follow in a subsequent change (tracked by the issue below).

Related: tektoncd#4752
@vdemeester
Copy link
Member

That sounds about right 🙃
cc @imjasonh @afrittoli

mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 14, 2022
This swaps out the use of `gcr.io/distroless/base:debug` for the new `ghcr.io/distroless/busybox` image (since the former was being used exclusively for it having busybox).

This also swaps our the `Dockerfile` based `git-init` base image in favor of `ghcr.io/distroless/git` since it is now possible to produce a `distroless` Git image without losing one's sanity.

This does NOT remove the `Dockerfile` or any logic to build it just yet, in case we want to roll this back, but that should follow in a subsequent change (tracked by the issue below).

Related: tektoncd#4752
mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 14, 2022
This swaps our `Dockerfile` based `git-init` base image in favor of `ghcr.io/distroless/git` since it is now possible to produce a `distroless` Git image without losing one's sanity.

This does NOT remove the `Dockerfile` or any logic to build it just yet, in case we want to roll this back, but that should follow in a subsequent change (tracked by the issue below).

Related: tektoncd#4752
mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 14, 2022
This is very similar to tektoncd#4758 and tektoncd#4717 but for `shell-image`.  This switches the default user of the `shell-image` to `nonroot`, which forces Tekton to be explicit about all of the places it needs a shell as `root` using `runAsUser: 0`.

This also switches things over to a much leaner `busybox` image (no `glibc`), which is the main thing we use `base:debug` for with the OG distroless images.

Fixes: tektoncd#4761
Related: tektoncd#4752
mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 14, 2022
This is very similar to tektoncd#4758 and tektoncd#4717 but for `shell-image`.  This switches the default user of the `shell-image` to `nonroot`, which forces Tekton to be explicit about all of the places it needs a shell as `root` using `runAsUser: 0`.

This also switches things over to a much leaner `busybox` image (no `glibc`), which is the main thing we use `base:debug` for with the OG distroless images.

Fixes: tektoncd#4761
Related: tektoncd#4752
mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 14, 2022
This is very similar to tektoncd#4758 and tektoncd#4717 but for `shell-image`.  This switches the default user of the `shell-image` to `nonroot`, which forces Tekton to be explicit about all of the places it needs a shell as `root` using `runAsUser: 0`.

This also switches things over to a much leaner `busybox` image (no `glibc`), which is the main thing we use `base:debug` for with the OG distroless images.

Fixes: tektoncd#4761
Related: tektoncd#4752
mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 14, 2022
This is very similar to tektoncd#4758 and tektoncd#4717 but for `shell-image`.  This switches the default user of the `shell-image` to `nonroot`, which forces Tekton to be explicit about all of the places it needs a shell as `root` using `runAsUser: 0`.

This also switches things over to a much leaner `busybox` image (no `glibc`), which is the main thing we use `base:debug` for with the OG distroless images.

Fixes: tektoncd#4761
Related: tektoncd#4752
@mattmoor
Copy link
Member Author

Landing the first round of these now, please let me know if you see anything weird.

Next order of business will be to stage cleaning up the Dockerfile and such.

tekton-robot pushed a commit that referenced this issue Apr 15, 2022
This swaps our `Dockerfile` based `git-init` base image in favor of `ghcr.io/distroless/git` since it is now possible to produce a `distroless` Git image without losing one's sanity.

This does NOT remove the `Dockerfile` or any logic to build it just yet, in case we want to roll this back, but that should follow in a subsequent change (tracked by the issue below).

Related: #4752
tekton-robot pushed a commit that referenced this issue Apr 15, 2022
This is very similar to #4758 and #4717 but for `shell-image`.  This switches the default user of the `shell-image` to `nonroot`, which forces Tekton to be explicit about all of the places it needs a shell as `root` using `runAsUser: 0`.

This also switches things over to a much leaner `busybox` image (no `glibc`), which is the main thing we use `base:debug` for with the OG distroless images.

Fixes: #4761
Related: #4752
@mattmoor
Copy link
Member Author

For deleting build-push-ma-base-image.yaml I'm unsure where this is TaskRun from, so we should clean that up before my deletion lands.

mattmoor added a commit to mattmoor/pipeline that referenced this issue Apr 15, 2022
My previous change switched us off of the Dockerfile-based `git-init` base image in favor of `ghcr.io/distroless/git` (:tada:), however, I wanted to stagger cleaning this up so we could keep rebuilding it in case we needed to rollback.

This cleans up the Dockerfile and Task, which should complete the migration.

Fixes: tektoncd#4752
@imjasonh
Copy link
Member

For deleting build-push-ma-base-image.yaml I'm unsure where this is TaskRun from, so we should clean that up before my deletion lands.

- name: build-base-image
runAfter: [build, unit-tests]
taskRef:
name: build-multiarch-base-image
params:
- name: package
value: $(params.package)
- name: imageRegistry
value: $(params.imageRegistry)
- name: imageRegistryPath
value: $(params.imageRegistryPath)
- name: platforms
value: $(params.buildPlatforms)
- name: serviceAccountPath
value: $(params.serviceAccountPath)
workspaces:
- name: source
workspace: workarea
subpath: git
- name: release-secret
workspace: release-secret

Which blocks publish-images:

runAfter: [build-base-image]

...which should just have:

runAfter: [build, unit-tests]

@imjasonh
Copy link
Member

Looking closer, there's two different pipeline params, buildPlatforms (what platforms to pass to buildx, to build these base images) and publishPlatforms (what platforms to pass to ko).

So in removing build-base-image, we'll also want to remove buildPlatforms and only pass around publishPlatforms.

Though it looks like the default values defined in the Pipeline:

- name: publishPlatforms
description: |
Platforms to publish images for (e.g. linux/amd64,linux/arm64,windows/amd64). This
can differ from buildPlatforms due to the fact that a windows-compatible base image
is constructed for the publishing phase.
default: linux/amd64,linux/arm,linux/arm64,linux/s390x,linux/ppc64le,windows/amd64

...match the defaults defined in the Task:

- name: platforms
description: Platforms to publish for the images (e.g. linux/amd64,linux/arm64)
default: linux/amd64,linux/arm,linux/arm64,linux/s390x,linux/ppc64le,windows/amd64

So maybe we can just remove the Pipeline param entirely and just rely on the Task param's default? 🤔

chitrangpatel pushed a commit to chitrangpatel/pipeline that referenced this issue May 3, 2022
This swaps our `Dockerfile` based `git-init` base image in favor of `ghcr.io/distroless/git` since it is now possible to produce a `distroless` Git image without losing one's sanity.

This does NOT remove the `Dockerfile` or any logic to build it just yet, in case we want to roll this back, but that should follow in a subsequent change (tracked by the issue below).

Related: tektoncd#4752
chitrangpatel pushed a commit to chitrangpatel/pipeline that referenced this issue May 3, 2022
This is very similar to tektoncd#4758 and tektoncd#4717 but for `shell-image`.  This switches the default user of the `shell-image` to `nonroot`, which forces Tekton to be explicit about all of the places it needs a shell as `root` using `runAsUser: 0`.

This also switches things over to a much leaner `busybox` image (no `glibc`), which is the main thing we use `base:debug` for with the OG distroless images.

Fixes: tektoncd#4761
Related: tektoncd#4752
@mattmoor
Copy link
Member Author

mattmoor commented Jun 1, 2022

I wanted to circle back to this, since this has now presumably had reasonable bake time.

Do folks have any final thoughts on this, or should we remove the hold on #4765?

@vdemeester
Copy link
Member

cc @jerop @lbernick @abayer
I think we can remove the hold. One less "base" image to maintain is looking good to me 😝

@mattmoor
Copy link
Member Author

mattmoor commented Jun 3, 2022

Ok, I am going to remove the hold. I believe Prow will rerun everything, and this gives us tomorrow to fix things before the weekend if some crazy merge conflict snuck in. 🤞

tekton-robot pushed a commit that referenced this issue Jun 3, 2022
My previous change switched us off of the Dockerfile-based `git-init` base image in favor of `ghcr.io/distroless/git` (:tada:), however, I wanted to stagger cleaning this up so we could keep rebuilding it in case we needed to rollback.

This cleans up the Dockerfile and Task, which should complete the migration.

Fixes: #4752
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature Categorizes issue or PR as related to a new feature.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants