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
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions text/0000-remove-stacks-mixins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Meta
[meta]: #meta
- Name: Remove Stacks & Mixins
- Start Date: 2021-06-30
- Author(s): sclevine
- RFC Pull Request: (leave blank)
- CNB Pull Request: (leave blank)
- CNB Issue: (leave blank)
- Supersedes: [RFC0069](https://github.com/buildpacks/rfcs/blob/main/text/0069-stack-buildpacks.md), [RFC#167](https://github.com/buildpacks/rfcs/pull/167), many others

# Summary
[summary]: #summary

*NOTE: This proposal is part of a larger initiative to reduce complexity originally outlined in https://github.com/buildpacks/rfcs/pull/167*

This RFC proposes that we remove the "stack" and "mixin" concepts from the project and replace them with existing constructs in the container image ecosystem such as base images, Dockerfiles, and OS packages.
sclevine marked this conversation as resolved.
Show resolved Hide resolved

# Motivation
[motivation]: #motivation

The "stack" and "mixin" concepts add unnecessary complexity to the project and make it difficult for new users and contributors to understand how buildpacks work. Compatibility guarantees that are strongly enforced by the stack contract could be replaced with metadata validations and warnings.

# What it is
[what-it-is]: #what-it-is

Summary of changes:
- Remove mixins
- Replace stack metadata (including stack IDs) with canonical OS metadata.
jromero marked this conversation as resolved.
Show resolved Hide resolved

# How it Works
[how-it-works]: #how-it-works

## Base Image Metadata
sclevine marked this conversation as resolved.
Show resolved Hide resolved

Instead of a stack ID, runtime and build-time base images must contain the following canonicalized metadata:
- OS (e.g., "linux", `$GOOS`), specified as `os` in the base image `config`
- Architecture (e.g., "arm", `$GOARCH`), specified as `architecture` in the base image `config`
- Architecture Variant (optional) (e.g., "v6", `$GOARM`), specified as `variant` in the base image `config`
- Distribution (optional) (e.g., "ubuntu", `$ID`), specified as a label `io.buildpacks.distribution.name`
- Version (optional) (e.g., "18.04", `$VERSION_ID`), specified as a label `io.buildpacks.distribution.version`
jromero marked this conversation as resolved.
Show resolved Hide resolved

OS, Architecture, and Architecture Variant must be valid identifiers as defined in the [OCI Image specification](https://github.com/opencontainers/image-spec/blob/main/config.md).
For Linux-based images, each field should be canonicalized against values specified in `/etc/os-release` (`$ID` and `$VERSION_ID`).
hone marked this conversation as resolved.
Show resolved Hide resolved
sclevine marked this conversation as resolved.
Show resolved Hide resolved
The `os.version` field in an base image `config` may contain combined distribution and version information, but it is not used by the lifecycle.

The `stacks` list in `buildpack.toml` is replaced by a `targets` 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, Architecture, and Variant.

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.


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`.
sclevine marked this conversation as resolved.
Show resolved Hide resolved

#### Example: buildpack.toml `targets` table

```toml
hone marked this conversation as resolved.
Show resolved Hide resolved
[[targets]]
os = "linux"
arch = "x86_64"
[[targets.distributions]]
name = "ubuntu"
versions = ["18.04", "20.04"]

[[targets]]
os = "linux"
arch = "x86_64"
ekcasey marked this conversation as resolved.
Show resolved Hide resolved
[[targets.distributions]]
name = "ubuntu"
versions = ["14.04", "16.04"]

[[targets]]
os = "linux"
arch = "arm"
variant = "v6"
[[targets.distributions]]
name = "ubuntu"
versions = ["14.04", "16.04"]
```

## 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

- `CNB_TARGET_OS`
- `CNB_TARGET_ARCH`
- `CNB_TARGET_VARIANT`
- `CNB_TARGET_DISTRO_NAME`
- `CNB_TARGET_DISTRO_VERSION`
- `CNB_TARGET_ID` (optional ID, if present on runtime base image `io.buildpacks.id` label)
hone marked this conversation as resolved.
Show resolved Hide resolved

## Mixins

Mixins are no longer used. If an SBoM is available, platforms may warn when, e.g., a rebase operation would change the available packages.

### Example: CycloneDX SBoM

```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.3",
"version": 1,
"components": [
{
"type": "library",
"name": "curl",
"version": "1.2.3",
"purl": "pkg:deb/ubuntu/curl@1.2.3"
},
{
"type": "library",
"name": "libcurl",
"version": "4.5.6",
"purl": "pkg:deb/ubuntu/libcurl@4.5.6"
},
...
]
}
```

### Validations

Buildpack base image metadata specified in `buildpack.toml`'s `targets` list are validated against the runtime and build-time base images.
jromero marked this conversation as resolved.
Show resolved Hide resolved

Runtime and build-time base image packages are no longer validated against each other.

If an SBoM is available, `pack rebase` will fail if packages are removed from the new runtime base image.
sclevine marked this conversation as resolved.
Show resolved Hide resolved
This check may be skipped by passing a new `--force` flag to `pack rebase`.
However, this validation is not enforced by the specification.

### Migration

All existing labels and environment variables for stacks and mixins may be preserved on a base image until all users have migrated to the new format.
These labels will be deprecated (but allowed) for the forseeable future.
If the newly-specified field values are missing, the lifecycle and pack may used existing, standardized stack IDs (i.e., `io.buildpacks.stacks.*`) to determine the values of the missing fields, as long as the lifecycle and pack provide a warning for the user.
sclevine marked this conversation as resolved.
Show resolved Hide resolved

Copy link
Member

Choose a reason for hiding this comment

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

I think we need to address the migration path in this RFC

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed, let me know if you think I covered the relevant migration scenarios

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for adding this! Would we also continue to allow [[stacks]] in buildpack.toml, and ignore it at some point?

Copy link
Member Author

Choose a reason for hiding this comment

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

Definitely, I can add that as well

Copy link
Member

Choose a reason for hiding this comment

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

These labels will be deprecated (but allowed) for the forseeable future.

@jkutner This makes me think [[stacks]] and those labels would go away at the same time.

# Drawbacks
[drawbacks]: #drawbacks

- Involves breaking changes when existing metadata is removed.
- `CNB_TARGET_*` env vars assume a single target -- may require more breaking changes to support parallel, single-container cross-compilation in the future.

# Alternatives
[alternatives]: #alternatives

- Keep stacks.
sclevine marked this conversation as resolved.
Show resolved Hide resolved
- Make the above changes but keep some existing terminology: stacks, build-image, run-image.
jromero marked this conversation as resolved.
Show resolved Hide resolved
- Continue to allow buildpacks to specify package requirements (e.g., by PURL instead of mixins)

# Unresolved Questions
sclevine marked this conversation as resolved.
Show resolved Hide resolved
[unresolved-questions]: #unresolved-questions

- How will migration work? Can we make new base images compatible with older buildpacks? Can we make newer buildpacks compatible with older stacks?
- What should builder.toml (and similar stack-dependent config files) look like? What should assets look like? Note: these could be decided in subsequent subteam RFCs / spec PRs.
sclevine marked this conversation as resolved.
Show resolved Hide resolved
jromero marked this conversation as resolved.
Show resolved Hide resolved

sclevine marked this conversation as resolved.
Show resolved Hide resolved
# Spec. Changes (OPTIONAL)
[spec-changes]: #spec-changes

This RFC requires extensive changes to all specifications.