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

bundle: Add platform-matching config directories #76

Closed
wants to merge 1 commit into from

Conversation

wking
Copy link
Contributor

@wking wking commented Jul 25, 2015

To allow a single bundle to be cross-platform. I've tried to add
enough context to motivate the additional complexity without adding so
much that the context distracts from the spec changes.

The tie-breaking version ranking (step (2) for picking the best config
file) also make it possible to write backwards-compatible bundles that
still take advantage of new features when possible. For example,
placing v1.0, v1.6, and v2.0 configs in the same directory would let
you run the same container on all v1.* and v2.* runtimes while still
letting you take advantage of v1.6 and v2.0 features for compatible
runtimes. After explaining the multi-platform advantages, the
multi-version example seemed obvious enough to not be worth cluttering
the bundle.md description, but commit-message space is cheap so I'm
talking about it explicitly here ;).

There was discussion about schemes for sharing content between config
files (JSON Schema's $ref and explicit child
declarations
). However, neither approach makes it convenient to
both make mass tweaks across a family of related configs and make
targetted tweaks to a single leaf
, so for now we'll follow the
Dockerfile example and have simple, stand-alone configs. Folks
who find this tedious or redundant are free to automate it with
external tooling, and if a given external tool gains enough mass we
can roll it into the spec later.

See also: #73 and #74.

To allow a single bundle to be cross-platform.  I've tried to add
enough context to motivate the additional complexity without adding so
much that the context distracts from the spec changes.

The tie-breaking version ranking (step (2) for picking the best config
file) also make it possible to write backwards-compatible bundles that
still take advantage of new features when possible.  For example,
placing v1.0, v1.6, and v2.0 configs in the same directory would let
you run the same container on all v1.* and v2.* runtimes while still
letting you take advantage of v1.6 and v2.0 features for compatible
runtimes.  After explaining the multi-platform advantages, the
multi-version example seemed obvious enough to not be worth cluttering
the bundle.md description, but commit-message space is cheap so I'm
talking about it explicitly here ;).

There was discussion about schemes for sharing content between config
files (JSON Schema's $ref [1] and explicit child declarations [2]).
However, neither approach makes it convenient to both make mass tweaks
across a family of related configs and make targetted tweaks to a
single leaf [3], so for now we'll follow the Dockerfile example and
have simple, stand-alone configs [4].  Folks who find this tedious or
redundant are free to automate it with external tooling, and if a
given external tool gains enough mass we can roll it into the spec
later.

[1]: opencontainers#73 (comment)
[2]: opencontainers#74
[3]: opencontainers#73 (comment)
[4]: opencontainers#74 (comment)
@wking
Copy link
Contributor Author

wking commented Jul 25, 2015

Thinking this over some more, the config-choosing functionality doesn't have to get rolled into the runtime. It could happen in a separate step. So it might be better to split this off into a separate spec layer (opencontainers/multi-platform-spec?). Then bundle-authors who want to use this functionality can skip config.json and write their config directory. A meta-runtime that understands that extension would:

  1. Notice the presence of the config directory
  2. Launch the config-matching utility, and write it's stdout to config.json.
  3. Launch the container-launching utility (e.g. runC)

That approach also makes it easy for folks to plug in alternative or additional layers (e.g. $ref replacement, explicit-child joining, environment-variable injection, signature checking #11, …). I like the Unix-philosophy approach here, but we'd want a way to:

  1. Declare requirements so the meta-runtime knows what to do.
  2. Make the per-tool specs discoverable.
  3. Provide examples tying the tools together to perform real-world things.

For (2), what do we think about a “Related tools” section in the opencontainers/specs README that has a list of per-tool specs, a brief description of the idea, and then known implementations of the spec? For example:

* Multi-platform spec matching ([spec][mpms]).  Implementations: [mpm][]
* Namespace joining ([spec][nsj]).  Implementations: [util-linux][], [jpetazzo][]
…

[mpms]: https://github.com/wking/multi-platform-match-spec
[mpm]: https://github.com/wking/multi-platform-match-spec
[nsj]: http://man7.org/linux/man-pages/man1/nsenter.1.html
[util-linux]: https://git.kernel.org/cgit/utils/util-linux/util-linux.git/
[jpetazzo]: https://github.com/jpetazzo/nsenter

Then (1) can be a shell script in the root of the container (main.sh)?. The meta-runtime can launch from a restricted environment if it wants better security. This sort of thing could be handled by hooks in config.json, but if the purpose of a given script is to build config.json you have a chicken/egg problem. The POSIX shell syntax (likely with a reduced set of available utilities) is well established and independent of containerization, so I think that makes the most sense for the lowest orchestration layer. Going down this path will probalby lead to container systems like ipfs-exec, which is just “fetch a bundle, cd into it, and run something (maybe in a restricted environment)”. If we have a consistent name for what that “run something” looks like (and I'd recommend main.sh), life gets easier for everyone.

How does this sound? Is it crazy? If so, what are our alternatives for orchestrating multi-spec/component runtimes without building a single monolithic tool?

@wking wking mentioned this pull request Jul 27, 2015
@philips
Copy link
Contributor

philips commented Jul 28, 2015

I think we are a ways off from this being a concern. My preference is that we build something simple enough that we only add new fields and remain backwards compatible at the config level forever. This may take a few releases but I think we know enough about the problem space to do it.

Put another way we need to treat the spec JSON like a protobuf and only add new fields, and deprecate old fields. We should never repurpose a field based on the version number.

@philips
Copy link
Contributor

philips commented Jul 28, 2015

Closing until we get further along.

@philips philips closed this Jul 28, 2015
@wking wking mentioned this pull request Jul 28, 2015
@wking
Copy link
Contributor Author

wking commented Jul 28, 2015

On Tue, Jul 28, 2015 at 12:31:12PM -0700, Brandon Philips wrote:

Put another way we need to treat the spec JSON like a protobuf and
only add new fields, and deprecate old fields. We should never
repurpose a field based on the version number.

Even without breaking strict backwards compatibility, I think we'll
still want a way to be compatible with multiple config versions. For
example, say we add a more convenient way to mount sysfs with the
right permissions (#65). What happens to my current sysfs mount 1?
How do I stay compatible with the current no-special-sysfs-handling
runC while also taking advantage (for newer runtimes) of the new,
convenient sysfs handling? Without providing a way to select between
a few provided config versions, it seems like bundles will be stuck
jumping through all the hoops required by the oldest minor version of
the spec that they need to support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants