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

RFC: Remove Stacks & Mixins #172

Merged
merged 19 commits into from
Oct 7, 2021
Merged

RFC: Remove Stacks & Mixins #172

merged 19 commits into from
Oct 7, 2021

Conversation

sclevine
Copy link
Member

Readable.

This proposal is part of a larger initiative to reduce complexity originally outlined in #167

Signed-off-by: Stephen Levine <stephen.levine@gmail.com>
text/0000-remove-stacks-mixins.md Outdated Show resolved Hide resolved
text/0000-remove-stacks-mixins.md Outdated Show resolved Hide resolved
text/0000-remove-stacks-mixins.md Outdated Show resolved Hide resolved
@sclevine sclevine mentioned this pull request Jun 30, 2021

Instead of a stack ID, runtime and build-time base images are labeled with the following canonicalized metadata:
- OS (e.g., "linux", `$GOOS`)
- Architecture (e.g., "x86_64", `$GOARCH`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Off-topic: Is there any plan/idea for buildpacks to support building multi-platform images, such that a single image manifest can describe an image for linux/arm64 and linux/arm64 and windows/amd64, etc.? Or is the intention that someone wanting to build a multi-platform image should use buildpacks to produce multiple platform-specific images, then stitch them together with something like docker manifest create ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No current RFC, but I definitely agree that we should eventually support exporting multi-platform manifest indexes.

The BuildKit frontend might help us with this, via buildx: buildpacks/pack#768

For non-local builds, we could extend the current exporter to accept a set of layers for each OS/ARCH combination.

In either case, we'd probably want to pass standardized env vars (e.g., $CNB_TARGET_ARCH) to the builder and buildpacks to support cross-compilation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any plan/idea for buildpacks to support building multi-platform images

This is hard to do well given that (some exceptions wrt docker-for-mac notwithstanding) the build takes place in a docker container and a given daemon only supports a single os/arch.

You could theoretically have a buildpacks execute on one target while producing launch layers that are valid for a different target but this puts a lot of responsibility on the buildpack author and comes with a lot of gotchas. e.g

  • a single layer is unlikely to be valid as both a build and launch layers
  • ecosystem tools that buildpacks delegate to will make assumptions based on the build environment

imho this is unlikely to end well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could theoretically have a buildpacks execute on one target while producing launch layers that are valid for a different target

I'm not opposed to this. Cross-compilation seems like a reasonable feature request to me. We would probably want to pass "target" metadata (e.g., from a run image label) to the buildpacks. When multiple run images are provided, buildpacks could produce multiple versions of the same layer for different architectures.

@jkutner jkutner mentioned this pull request Jul 1, 2021
Signed-off-by: Stephen Levine <stephen.levine@gmail.com>

When an app image is rebased, `pack rebase` will fail if the new run image and previous run image have mismatched metadata. This check may be skipped for Distribution and Version by passing a new `--force` flag to `pack rebase`.

#### Example: buildpack.toml `platforms` table
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ekcasey as requested. Looks very noisy, but I think it meets the requirements.

Copy link
Contributor

@dmikusa dmikusa Jul 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain the sample, please? If I have this example in my buildpack's buildpack.toml, what does that mean for the buildpack & compatibility with images? What sort of compatibility guarantees do I get?


For Linux-based images, each field should be canonicalized against values specified in `/etc/os-release` (`$ID` and `$VERSION_ID`).

The `stacks` list in `buildpack.toml` is replaced by a `platforms` list, where each entry corresponds to a different buildpack image that is exported into a [manifest index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). Each entry may contain multiple valid values for Distribution and/or Version, but only a single OS and Architecture. Each entry may also contain a list of package names (as PURL URLs without versions or qualifiers) that specify detect-time and build-time (but not runtime) OS package dependencies. Packages may be specified for all Versions of a distribution, or for a specific Version. Buildpacks may express **runtime** OS package dependencies during detection (see "Runtime Base Image Requirements" below).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the goal of buildpacks is to build an image from an app's project where several build/detect/ (1 to many) steps are done using a Build image and next launched using a Runtime or stack or runtimeStack image, then I think that it is important to continue to use a wording that everyone will understand.

This is the reason why I would like to suggest to keep the stack (or maybe to rename it to: runStack, runtimeStack, ...) word instead of using platform.

Why: to improve the readability of a builder definition with a wording which is more inline with what finally we would like to describe (or what we want to do during a build or when we will launch the image built)

Example of such new definition could be

  # buildPacks could be renamed to buildSteps ;-)
  buildPacks:
  # List of build steps executed by the Lifecycle creator during: detect, build, ... steps
    - id: dev.snowdrop.jdk
      packUri: 'docker://quay.io/snowdrop/pack-jdk:11'
      buildPackImage: 'quay.io/snowdrop/buildpack-jdk:1.0'
    - id: dev.snowdrop.maven
      packUri: 'docker://quay.io/snowdrop/pack-maven:3.5'
      buildPackImage: 'quay.io/snowdrop/buildpack-maven:1.0'
    - id: dev.snowdrop.gradle
      packUri: 'docker://quay.io/snowdrop/pack-gradle:7.1'
      buildImage: 'quay.io/snowdrop/buildpack-gradle:1.0'
      optional: yes
      packages:
        - pkg:rpm/rhel/gradle@7.1
  # List of run stacks image supporting the build image      
  runStacks:
    - id: dev.snowdrop.stack.jdk16
      default: yes
      os: rhel
      version: 8
      arch: x86_64
      runtimeImage: 'quay.io/snowdrop/stack-run:jdk16'
      packages:
        - pkg:rpm/rhel/openjdk11
    - id: dev.snowdrop.stack.jdk11
      os: ubuntu
      version: 
      arch: x86_64
      runtimeImage: 'quay.io/snowdrop/stack-run:jdk11'

See gist created: https://gist.github.com/cmoulliard/04999929df0b758b5edbdf19dfc85f45

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the proposed example. Some questions:

  • Where does the build-time base image come from for the JDK and Maven buildpacks?
  • Is a different build-time base image selected when the runtime base image OS changes?
  • Are the buildpack IDs optional?
  • How does the packages list work?
  • Are you proposing that we re-define stack to only refer to the runtime base image?

Would be great to dig into this during the weekly WG meeting.

I'm not attached to platforms for the table name, but I would like to remove unnecessary, project-specific terms to make the project more accessible.


The `stacks` list in `buildpack.toml` is replaced by a `platforms` list, where each entry corresponds to a different buildpack image that is exported into a [manifest index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). Each entry may contain multiple valid values for Distribution and/or Version, but only a single OS and Architecture. Each entry may also contain a list of package names (as PURL URLs without versions or qualifiers) that specify detect-time and build-time (but not runtime) OS package dependencies. Packages may be specified for all Versions of a distribution, or for a specific Version. Buildpacks may express **runtime** OS package dependencies during detection (see "Runtime Base Image Requirements" below).

App image builds fail if the build image and selected run image have mismatched metadata. We may introduce flags or additional labels to skip this validation (e.g., for cross-compilation or minimal runtime base images). An image without a specified Distribution is compatible with images specifying any Distribution. An image specifying a Distribution without a Version is compatible with images specifying any Versions of that Distribution.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

App image builds fail if the build image and selected run image have mismatched metadata

Haven't thought this through all the way but would it make sense to this in the build plan as well. E.g. a buildpack could specify in buildpack.toml that it needs to run on a particular distribution but could express at detect time that the resulting layers could run on any-linux (distroless images).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An image without a specified Distribution is compatible with images specifying any Distribution. An image specifying a Distribution without a Version is compatible with images specifying any Versions of that Distribution.

Is this what would replace wildcard stack support, i.e. stack="*".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E.g. a buildpack could specify in buildpack.toml that it needs to run on a particular distribution but could express at detect time that the resulting layers could run on any-linux (distroless images).

I'm not sure this needs to be dynamic. I wonder if this could be part of the multi-platform interface? See: #172 (comment)

Is this what would replace wildcard stack support, i.e. stack="*".

The requirement is just describing the contract between the build and run images. Wildcard stack support is achieved by leaving off Distribution and Version entirely. (There is no wildcard support for OS/Architecture.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just updating this thread in case someone comes along in two more years, but anyway it turned out while implementing we did make an explicit extension for "*" OS/Architecture.

text/0000-remove-stacks-mixins.md Show resolved Hide resolved
text/0000-remove-stacks-mixins.md Outdated Show resolved Hide resolved

## Runtime Base Image Requirements

Buildpacks may specify a list of package names (as PURL URLs without versions or qualifiers) in a `packages` table in the build plan. The build will fail if these packages are not present in the runtime base image.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example please :)

text/0000-remove-stacks-mixins.md Show resolved Hide resolved
text/0000-remove-stacks-mixins.md Show resolved Hide resolved
sclevine and others added 2 commits July 1, 2021 12:23
Signed-off-by: Stephen Levine <stephen.levine@gmail.com>

Co-authored-by: Emily Casey <ecasey@vmware.com>
Signed-off-by: Stephen Levine <stephen.levine@gmail.com>

Co-authored-by: Emily Casey <ecasey@vmware.com>
## Base Image Metadata

Instead of a stack ID, runtime and build-time base images are labeled with the following canonicalized metadata:
- OS (e.g., "linux", `$GOOS`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these strings able to be anything? Could I, if I wanted to, create a JesseOS OS string to tightly control the buildpacks that have explicitly updated to work on my build/run images?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OS and Architecture would be restricted to GOOS and GOARCH values. Distribution and Version could technically be anything, but should match /etc/os-release for Linux distros.

Signed-off-by: Stephen Levine <stephen.levine@gmail.com>
@sclevine
Copy link
Member Author

Idea I'd like feedback on: what if we dropped the packages list from both buildpack.toml and detect, at least for now? Builder authors could be responsible for reading buildpack documentation and installing any extra packages. We could re-introduce this functionality, if necessary, as part of #174.

@hone hone added the roadmap/cloud-ecosystem Issues/PRs that provide a better out-of-the box Kubernetes and Docker integration story. label Sep 23, 2021
Signed-off-by: Stephen Levine <stephen.levine@gmail.com>
@sclevine
Copy link
Member Author

@hone added, ready to merge

@hone hone added the roadmap/stack-buildpacks Issues/PRs that add support platform authors and stack authors to allow stacks to be customized. label Sep 29, 2021
@hone
Copy link
Member

hone commented Sep 29, 2021

I think the bot may be broken. :( @buildpacks/implementation-maintainers @buildpacks/platform-maintainers are there any issues that need to be opened before I merge this in?

@jromero
Copy link
Member

jromero commented Sep 30, 2021

I think the bot may be broken. :( @buildpacks/implementation-maintainers @buildpacks/platform-maintainers are there any issues that need to be opened before I merge this in?

It's not broken. The issues only get created when this gets merged via merge-rfc.sh.

EDIT: You can see the list of queued issues here: #172 (comment)

## Runtime Metadata

To allow different runtime base images to be used, and to support cross-compilation in the future, buildpacks may need access to the runtime base image's target metadata.
The following environment variables will be available to buildpacks directly in the build-time environment (not via `/platform/env`):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is a little unclear to me. This appears to be talking about a set of environment variables that are given to the buildpacks during build-time.

  1. It's not talking about these environment variable being set on the run image right?
  2. What determines what these environment variables should be set to?
  3. What does happen if the platform provides these environment variables via /platform/env as a way to configure the desired outcome? Is it explicitly something we don't want to allow?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Correct: "directly in the build-time environment"
  2. "runtime base image's target metadata" -- same metadata as above, but for the runtime base image
  3. All CNB_ env vars are set directly so that they are unaffected by "strict" mode that forces buildpacks to read the env vars from /platform/env

hone added a commit that referenced this pull request Oct 7, 2021
[#172]

Signed-off-by: Terence Lee <hone02@gmail.com>
@hone hone merged commit 89db3e1 into main Oct 7, 2021
@hone hone deleted the remove-stacks-mixins branch October 7, 2021 18:59
@edmorley
Copy link
Contributor

edmorley commented Jun 1, 2022

The current buildpack API spec includes CNB_STACK_ID being set in the environment of buildpack detect/build:
https://github.com/buildpacks/spec/blob/buildpack/v0.8/buildpack.md#provided-by-the-platform

That env var is commonly used by buildpacks when determining which binary to download/install for those that are compiled for specific OSes/OS versions.

This RFC doesn't mention what happens to that env var. Is it now considered deprecated too? Or are only the buildpack.toml stacks parts being deprecated?

If CNB_STACK_ID is being deprecated, could the RFC be updated to clarify this + explain what buildpacks should now use instead? (I would presume they now need to construct the stack name/version/... from the new CNB_TARGET_* env vars?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
audience/platform-maintainer Final Comment Period roadmap/cloud-ecosystem Issues/PRs that provide a better out-of-the box Kubernetes and Docker integration story. roadmap/stack-buildpacks Issues/PRs that add support platform authors and stack authors to allow stacks to be customized. spec/buildpack spec/extensions/builder spec/platform team/implementation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet