From 38bc8cb4ccce27faca6cf9de2f83a26c4e7d9fee Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sat, 25 Apr 2020 14:30:27 +0100 Subject: [PATCH] feat(web/blog): Add Nixery layering design as a blog post Marked as a draft until I've verified that this looks good. --- web/blog/posts.nix | 7 + web/blog/posts/nixery-layers.md | 272 ++++++++++++++++++ web/homepage/static/img/nixery/dominator.webp | Bin 0 -> 12020 bytes .../static/img/nixery/example_extra.webp | Bin 0 -> 10854 bytes .../static/img/nixery/example_plain.webp | Bin 0 -> 9610 bytes .../static/img/nixery/ideal_layout.webp | Bin 0 -> 8334 bytes 6 files changed, 279 insertions(+) create mode 100644 web/blog/posts/nixery-layers.md create mode 100644 web/homepage/static/img/nixery/dominator.webp create mode 100644 web/homepage/static/img/nixery/example_extra.webp create mode 100644 web/homepage/static/img/nixery/example_plain.webp create mode 100644 web/homepage/static/img/nixery/ideal_layout.webp diff --git a/web/blog/posts.nix b/web/blog/posts.nix index d7949fa34..8934cda86 100644 --- a/web/blog/posts.nix +++ b/web/blog/posts.nix @@ -13,6 +13,13 @@ date = 1576800001; content = ./posts/best-tools.md; } + { + key = "nixery-layers"; + title = "Nixery: Improved Layering Design"; + date = 1565391600; + content = ./posts/nixery-layers.md; + draft = true; + } { key = "reversing-watchguard-vpn"; title = "Reverse-engineering WatchGuard Mobile VPN"; diff --git a/web/blog/posts/nixery-layers.md b/web/blog/posts/nixery-layers.md new file mode 100644 index 000000000..3f25ceadc --- /dev/null +++ b/web/blog/posts/nixery-layers.md @@ -0,0 +1,272 @@ +TIP: This blog post was originally published as a design document for +[Nixery][] and is not written in the same style +as other blog posts. + +Thanks to my colleagues at Google and various people from the Nix community for +reviewing this. + +------ + +# Nixery: Improved Layering + +**Authors**: tazjin@ + +**Reviewers**: so...@, en...@, pe...@ + +**Status**: Implemented + +**Last Updated**: 2019-08-10 + +## Introduction + +This document describes a design for an improved image layering method for use +in Nixery. The algorithm [currently used][grhmc] is designed for a slightly +different use-case and we can improve upon it by making use of more of the +available data. + +## Background / Motivation + +Nixery is a service that uses the [Nix package manager][nix] to build container +images (for runtimes such as Docker), that are served on-demand via the +container [registry protocols][]. A demo instance is available at +[nixery.dev][]. + +In practice this means users can simply issue a command such as `docker pull +nixery.dev/shell/git` and receive an image that was built ad-hoc containing a +shell environment and git. + +One of the major advantages of building container images via Nix (as described +for `buildLayeredImage` in [this blog post][grhmc]) is that the +content-addressable nature of container image layers can be used to provide more +efficient caching characteristics (caching based on layer content) than what is +common with Dockerfiles and other image creation methods (caching based on layer +creation method). + +However, this is constrained by the maximum number of layers supported in an +image (125). A naive approach such as putting each included package (any +library, binary, etc.) in its own layer quickly runs into this limitation due to +the large number of dependencies more complex systems tend to have. In addition, +users wanting to extend images created by Nixery (e.g. via `FROM nixery.dev/…`) +share this layer maximum with the created image - limiting extensibility if all +layers are used up by Nixery. + +In theory the layering strategy of `buildLayeredImage` should already provide +good caching characteristics, but in practice we are seeing many images with +significantly more packages than the number of layers configured, leading to +more frequent cache-misses than desired. + +The current implementation of `buildLayeredImage` inspects a graph of image +dependencies and determines the total number of references (direct & indirect) +to any node in the graph. It then sorts all dependencies by this popularity +metric and puts the first `n - 2` (for `n` being the maximum number of layers) +packages in their own layers, all remaining packages in one layer and the image +configuration in the final layer. + +## Design / Proposal + +## (Close-to) ideal layer-layout using more data + +We start out by considering what a close to ideal layout of layers would look +like for a simple use-case. + +![Ideal layout](/static/img/nixery/ideal_layout.webp) + +In this example, counting the total number of references to each node in the +graph yields the following result: + +| pkg | refs | +|-------|------| +| E | 3 | +| D | 2 | +| F | 2 | +| A,B,C | 1 | + +Assuming we are constrained to 4 layers, the current algorithm would yield these layers: + +``` +L1: E +L2: D +L3: F +L4: A, B, C +``` + +The initial proposal for this design is that additional data should be +considered in addition to the total number of references, in particular a +distinction should be made between direct and indirect references. Packages that +are only referenced indirectly should be merged with their parents. + +This yields the following table: + +| pkg | direct | indirect | +|-------|--------|----------| +| E | 3 | 3 | +| D | 2 | 2 | +| F | *1* | 2 | +| A,B,C | 1 | 1 | + +Despite having two indirect references, F is in fact only being referred to +once. Assuming that we have no other data available outside of this graph, we +have no reason to assume that F has any popularity outside of the scope of D. +This might yield the following layers: + +``` +L1: E +L2: D, F +L3: A +L4: B, C +``` + +D and F were grouped, while the top-level references (i.e. the packages +explicitly requested by the user) were split up. + +An assumption is introduced here to justify this split: The top-level packages +is what the user is modifying directly, and those groupings are likely +unpredictable. Thus it is opportune to not group top-level packages in the same +layer. + +This raises a new question: Can we make better decisions about where to split +the top-level? + +## (Even closer to) ideal layering using (even) more data + +So far when deciding layer layouts, only information immediately available in +the build graph of the image has been considered. We do however have much more +information available, as we have both the entire nixpkgs-tree and potentially +other information (such as download statistics). + +We can calculate the total number of references to any derivation in nixpkgs and +use that to rank the popularity of each package. Packages within some percentile +can then be singled out as good candidates for a separate layer. + +When faced with a splitting decision such as in the last section, this data can +aid the decision. Assume for example that package B in the above is actually +`openssl`, which is a very popular package. Taking this into account would +instead yield the following layers: + +``` +L1: E, +L2: D, F +L3: B, +L4: A, C +``` + +## Layer budgets and download size considerations + +As described in the introduction, there is a finite amount of layers available +for each image (the “layer budget”). When calculating the layer distribution, we +might end up with the “ideal” list of layers that we would like to create. Using +our previous example: + +``` +L1: E, +L2: D, F +L3: A +L4: B +L5: C +``` + +If we only have a layer budget of 4 available, something needs to be merged into +the same layer. To make a decision here we could consider only the package +popularity, but there is in fact another piece of information that has not come +up yet: The actual size of the package. + +Presumably a user would not mind downloading a library that is a few kilobytes +in size repeatedly, but they would if it was a 200 megabyte binary instead. + +Conversely if a large binary was successfully cached, but an extremely popular +small library is not, the total download size might also grow to irritating +levels. + +To avoid this we can calculate a merge rating: + + merge_rating(pkg) = popularity_percentile(pkg) × size(pkg.subtree) + +Packages with a low merge rating would be merged together before packages with +higher merge ratings. + +## Implementation + +There are two primary components of the implementation: + +1. The layering component which, given an image specification, decides the image + layers. + +2. The popularity component which, given the entire nixpkgs-tree, calculates the + popularity of packages. + +## Layering component + +It turns out that graph theory’s concept of [dominator trees][] maps reasonably +well onto the proposed idea of separating direct and indirect dependencies. This +becomes visible when creating the dominator tree of a simple example: + +![Example without extra edges](/static/img/nixery/example_plain.webp) + +Before calculating the dominator tree, we inspect each node and insert extra +edges from the root for packages that match a certain popularity or size +threshold. In this example, G is popular and an extra edge is inserted: + +![Example with extra edges](/static/img/nixery/example_extra.webp) + +Calculating the dominator tree of this graph now yields our ideal layer +distribution: + +![Dominator tree of example](/static/img/nixery/dominator.webp) + +The nodes immediately dominated by the root node can now be “harvested” as image +layers, and merging can be performed as described above until the result fits +into the layer budget. + +To implement this, the layering component uses the [gonum/graph][] library which +supports calculating dominator trees. The program is fed with Nix’s +`exportReferencesGraph` (which contains the runtime dependency graph and runtime +closure size) as well as the popularity data and layer budget. It returns a list +of layers, each specifying the paths it should contain. + +Nix invokes this program and uses the output to create a derivation for each +layer, which is then built and returned to Nixery as usual. + +TIP: This is implemented in [`layers.go`][layers.go] in Nixery. The file starts +with an explanatory comment that talks through the process in detail. + +## Popularity component + +The primary issue in calculating the popularity of each package in the tree is +that we are interested in the runtime dependencies of a derivation, not its +build dependencies. + +To access information about the runtime dependency, the derivation actually +needs to be built by Nix - it can not be inferred because Nix does not know +which store paths will still be referenced by the build output. + +However for packages that are cached in the NixOS cache, we can simply inspect +the `narinfo`-files and use those to determine popularity. + +Not every package in nixpkgs is cached, but we can expect all *popular* packages +to be cached. Relying on the cache should therefore be reasonable and avoids us +having to rebuild/download all packages. + +The implementation will read the `narinfo` for each store path in the cache at a +given commit and create a JSON-file containing the total reference count per +package. + +For the public Nixery instance, these popularity files will be distributed via a +GCS bucket. + +TIP: This is implemented in [popcount][] in Nixery. + +-------- + +Hopefully this detailed design review was useful to you. You can also watch [my +NixCon talk][talk] about Nixery for a review of some of this, and some demos. + +[Nixery]: https://github.com/google/nixery +[grhmc]: https://grahamc.com/blog/nix-and-layered-docker-images +[Nix]: https://nixos.org/nix +[registry protocols]: https://github.com/opencontainers/distribution-spec/blob/master/spec.md +[nixery.dev]: https://nixery.dev +[dominator trees]: https://en.wikipedia.org/wiki/Dominator_(graph_theory) +[gonum/graph]: https://godoc.org/gonum.org/v1/gonum/graph +[layers.go]: https://github.com/google/nixery/blob/master/builder/layers.go +[popcount]: https://github.com/google/nixery/tree/master/popcount +[talk]: https://www.youtube.com/watch?v=pOI9H4oeXqA diff --git a/web/homepage/static/img/nixery/dominator.webp b/web/homepage/static/img/nixery/dominator.webp new file mode 100644 index 0000000000000000000000000000000000000000..2d8569a6ca21fb32acb22ca1735bd8c5e3d89a2b GIT binary patch literal 12020 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 literal 0 HcmV?d00001 diff --git a/web/homepage/static/img/nixery/example_extra.webp b/web/homepage/static/img/nixery/example_extra.webp new file mode 100644 index 0000000000000000000000000000000000000000..101f0f633aefb8bcbc38e9c2afd19cc68cdce763 GIT binary patch literal 10854 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 GFaQ8_