courses I and II wired: cascade + up-down split animations, fleet-labels move in VI, the library, C-II hero + manifest
This commit is contained in:
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
@@ -10,11 +10,13 @@ trap 'printf "build failed at line %s\n" "$LINENO" >&2' ERR
|
||||
here="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd -- "$here"
|
||||
|
||||
for f in pilot/arc.tpl.html pilot/manifest-gitops.json pilot/manifest-supply.json \
|
||||
for f in pilot/arc.tpl.html pilot/manifest-docker.json pilot/manifest-cluster.json \
|
||||
pilot/manifest-gitops.json pilot/manifest-supply.json \
|
||||
pilot/manifest-helm.json gsap.min.js st.min.js \
|
||||
assets/dist/course-VI-gitops.webp assets/dist/course-VII-supply-chain.webp \
|
||||
assets/dist/course-VIII-helm-press.webp assets/dist/appendix-dependency-ledger.webp \
|
||||
assets/dist/delivery-flow.svg; do
|
||||
assets/dist/delivery-flow.svg assets/dist/docker-layers.webp \
|
||||
assets/dist/course-II-cluster.webp; do
|
||||
[[ -f "$f" ]] || { printf 'missing source: %s\n' "$f" >&2; exit 1; }
|
||||
done
|
||||
|
||||
|
||||
+155
-6
@@ -1,20 +1,114 @@
|
||||
<header class="masthead">
|
||||
<p class="eyebrow">The Exploded Cluster · The Delivery Arc</p>
|
||||
<h1>The machine was the easy part.<br><em>Now watch how software reaches it.</em></h1>
|
||||
<p class="lede">Three courses on the toolchain around the cluster: how change travels, how images
|
||||
are named, and how one definition serves a fleet. Scroll, and each machine comes apart.</p>
|
||||
<p class="lede">The foundations first - what an image is, what a cluster is - then the toolchain
|
||||
that delivers to them: how change travels, how images are named, and how one definition serves
|
||||
a fleet. Scroll, and each machine comes apart.</p>
|
||||
<p class="scrollcue" aria-hidden="true">scroll<span></span></p>
|
||||
</header>
|
||||
|
||||
<aside class="key" aria-label="reading key">
|
||||
<p class="kt">Reading key · this page stands alone - anything it leans on is listed here</p>
|
||||
<ul>
|
||||
<li><b>C-I</b><span>Docker: an image is a stack of frozen diffs. Referenced by Course VII.</span><i>course lands here soon</i></li>
|
||||
<li><b>C-II</b><span>Kubernetes: a cluster is a promise - the reconciliation loop. Referenced by Courses VI and VIII.</span><i>course lands here soon</i></li>
|
||||
<li><b>C-I</b><span>Docker: an image is a stack of frozen diffs. Referenced by Course VII.</span><a href="#c1">on this page</a></li>
|
||||
<li><b>C-II</b><span>Kubernetes: a cluster is a promise - the reconciliation loop. Referenced by Courses VI and VIII.</span><a href="#c2">on this page</a></li>
|
||||
<li><b>BLOG</b><span>Consistency by construction beats consistency by discipline - Course VIII's contexts move, lived on a real fleet.</span><a href="https://www.bztmon.com/blog/one-value-many-enforcers/">read it on bztmon.com</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<!-- ============ COURSE I ============ -->
|
||||
<section class="course" id="c1" data-scene="docker" aria-labelledby="c1h">
|
||||
<header class="chead">
|
||||
<p class="eyebrow">Course I · Docker</p>
|
||||
<h2 id="c1h" class="thesis">An image is not a box.<br><em>It is a stack of frozen diffs.</em></h2>
|
||||
<p class="lede">Scroll, and the thing you keep calling "a container image" comes apart in your
|
||||
hands. Four layers. Each one only stores what changed from the layer under it - and here they
|
||||
rise one at a time, bottom up.</p>
|
||||
</header>
|
||||
<div class="pin">
|
||||
<div class="viewport">
|
||||
<figure class="scene">
|
||||
<img class="flat" src="__HERO_DOCKER__"
|
||||
alt="An exploded isometric view of a container image: four stacked slabs floating
|
||||
apart - a heavy metal base, a circuit-etched dependency layer, a magenta-traced
|
||||
code layer, and a thin frosted-glass writable layer on top.">
|
||||
</figure>
|
||||
<ol class="legend"></ol>
|
||||
</div>
|
||||
<div class="bench"></div>
|
||||
</div>
|
||||
<div class="prose">
|
||||
<h3>A stack of diffs wearing a name</h3>
|
||||
<p>An image is not a copy of a machine. It is a stack of read-only layers, each recording only
|
||||
what changed from the one beneath. The base OS is pulled once and shared by every image on
|
||||
the host; your dependencies sit on it; your code - usually the smallest layer, always the
|
||||
most volatile - sits above that; and the writable layer is created fresh per container and
|
||||
thrown away when it dies. Nothing you write there survives.</p>
|
||||
<p class="sayit">Change a layer and every layer above it must be rebuilt.</p>
|
||||
<h3>The order is a caching decision</h3>
|
||||
<p>The builder caches layer by layer, and a cached layer survives only while everything
|
||||
beneath it is unchanged. Put <span class="mono">COPY . .</span> above your dependency
|
||||
install and you have told the builder to throw the dependency cache away every time one
|
||||
line of code changes. Dependencies first, code last - a Dockerfile is a cache policy that
|
||||
happens to build software.</p>
|
||||
<p class="fieldnote"><b>Field note.</b> A rebuild that takes twenty minutes and one that
|
||||
takes twenty seconds are usually the same Dockerfile with the lines swapped.</p>
|
||||
<p class="closeline">This stack explains the whole ecosystem above it: sharing explains why
|
||||
pulls are fast, immutability explains why a digest can name the exact bytes (Course VII),
|
||||
and the throwaway top layer explains why state needs volumes. One idea - frozen diffs -
|
||||
all the way down.</p>
|
||||
<p class="reads"><b>Pre-reads:</b> none - start here
|
||||
 <b>Further:</b> <a href="https://docs.docker.com/get-started/">Docker get-started</a> ·
|
||||
<a href="https://docs.docker.com/build/">Docker build + layers</a></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============ COURSE II ============ -->
|
||||
<section class="course" id="c2" data-scene="cluster" aria-labelledby="c2h">
|
||||
<header class="chead">
|
||||
<p class="eyebrow">Course II · Kubernetes</p>
|
||||
<h2 id="c2h" class="thesis">A cluster is a promise,<br><em>not a place.</em></h2>
|
||||
<p class="lede">You never tell Kubernetes <i>how</i> to run your app. You describe what you
|
||||
want - declarative intent - and the cluster works, forever, to make it true. Scroll, and
|
||||
the formation splits: the half that decides rises, the halves that run spread below.</p>
|
||||
</header>
|
||||
<div class="pin">
|
||||
<div class="viewport">
|
||||
<figure class="scene">
|
||||
<img class="flat" src="__HERO_CLUSTER__"
|
||||
alt="A small fleet mid-explosion: one wide command slab with a strong cyan seam
|
||||
hovering above a row of three identical worker blocks, all floating apart in
|
||||
the void.">
|
||||
</figure>
|
||||
<ol class="legend"></ol>
|
||||
</div>
|
||||
<div class="bench"></div>
|
||||
</div>
|
||||
<div class="prose">
|
||||
<h3>Desired against actual, forever</h3>
|
||||
<p>The habit underneath everything: the <b>reconciliation loop</b> - compare desired state
|
||||
against actual state, fix the difference, repeat. That <span class="mono">kubectl apply</span>
|
||||
didn't launch anything; it filed paperwork. The machine took it from there, and it never
|
||||
stops taking it from there: kill a pod and it returns, not because something noticed the
|
||||
crash but because the loop noticed the difference.</p>
|
||||
<p class="sayit">Kubernetes doesn't run your app - it reconciles it.</p>
|
||||
<h3>One half decides, one half runs</h3>
|
||||
<p>The split in the scene is the split that makes everything else possible: a <b>control
|
||||
plane</b> that decides - holds the truth, schedules, reconciles - and <b>worker nodes</b>
|
||||
that run pods. The workers are deliberately interchangeable: identical, replaceable, cattle
|
||||
from day one. Authority does not live where the work happens.</p>
|
||||
<p class="fieldnote"><b>Field note.</b> If you are SSHing into nodes to "fix" things, you
|
||||
are arm-wrestling the reconciler - and it does not get tired. Change the desired state
|
||||
instead.</p>
|
||||
<p class="closeline">Everything the delivery arc teaches from Course VI onward is this loop
|
||||
wearing bigger clothes - git as the desired state, whole fleets as reconciled objects.
|
||||
Learn the promise once; it repeats all the way up.</p>
|
||||
<p class="reads"><b>Pre-reads:</b> C-I
|
||||
 <b>Further:</b> <a href="https://kubernetes.io/docs/concepts/overview/">Kubernetes overview</a> ·
|
||||
<a href="https://kubernetes.io/docs/concepts/architecture/">cluster architecture</a></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============ COURSE VI ============ -->
|
||||
<section class="course" id="c6" data-scene="gitops" aria-labelledby="c6h">
|
||||
<header class="chead">
|
||||
@@ -55,6 +149,15 @@
|
||||
<p class="fieldnote"><b>Field note.</b> Fighting the reconciler over SSH is arm-wrestling a
|
||||
machine that does not get tired - C-II's warning, now with a face. The fix is always
|
||||
upstream, in git.</p>
|
||||
<h3>At fleet scale, the label is the deploy button</h3>
|
||||
<p>Run many OpenShift clusters under a hub - RHACM, with edge clusters arriving through
|
||||
zero-touch provisioning - and nobody applies apps to clusters by hand. Each app carries a
|
||||
<b>Placement</b> that selects cluster <b>labels</b>; the hub matches placements against the
|
||||
labels a cluster wears, and the chosen cluster pulls its assignment. Labelling the cluster
|
||||
<i>is</i> the deploy action: attach the label and the app follows, remove it and the app
|
||||
leaves. The same pull model as above, one level bigger - a cluster's labels are its
|
||||
entitlements, reconciled like everything else.</p>
|
||||
<p class="sayit">Label the cluster; the app follows.</p>
|
||||
<h3>The one thing git never holds</h3>
|
||||
<p>Git holds everything except secrets - a secret in git is published, forever, to everyone who
|
||||
ever clones. So the pattern splits the reference from the value: git carries an ExternalSecret
|
||||
@@ -275,6 +378,40 @@
|
||||
</figure>
|
||||
</section>
|
||||
|
||||
<section class="course" id="library" aria-labelledby="libh">
|
||||
<header class="chead">
|
||||
<p class="eyebrow">The library</p>
|
||||
<h2 id="libh" class="thesis">Go to <em>the sources.</em></h2>
|
||||
<p class="lede">Every technology this site teaches, one sentence each, official documentation
|
||||
only.</p>
|
||||
</header>
|
||||
<ul class="library">
|
||||
<li><b>Kubernetes</b><span>The container orchestrator underneath everything here: declarative
|
||||
state, the reconciliation loop, pods, services and the machinery that keeps promises.</span>
|
||||
<a href="https://kubernetes.io/docs/">kubernetes.io/docs</a></li>
|
||||
<li><b>Helm</b><span>The package manager and Go-template engine that turns one chart plus a
|
||||
per-cluster values file into the rendered manifests a cluster actually runs.</span>
|
||||
<a href="https://helm.sh/docs/">helm.sh/docs</a></li>
|
||||
<li><b>Red Hat OpenShift</b><span>Kubernetes as an opinionated, supported distribution -
|
||||
SCCs, Routes and Operators, plus the fleet tooling (RHACM, zero-touch provisioning) that
|
||||
assigns apps to clusters by label.</span>
|
||||
<a href="https://docs.redhat.com/en/documentation/openshift_container_platform">docs.redhat.com</a></li>
|
||||
<li><b>Argo CD</b><span>The GitOps reconciler that watches a repository and keeps the cluster
|
||||
converged on what it finds there - the pull model that means nothing ever pushes to
|
||||
production.</span>
|
||||
<a href="https://argo-cd.readthedocs.io/">argo-cd.readthedocs.io</a></li>
|
||||
<li><b>GitHub Actions</b><span>CI that builds and tests on every push - in this flow it makes
|
||||
artefacts and proposes changes, and never holds a credential that can touch a cluster.</span>
|
||||
<a href="https://docs.github.com/en/actions">docs.github.com/actions</a></li>
|
||||
<li><b>Azure Key Vault</b><span>The managed vault holding secret values, so git carries only
|
||||
references and rotation never has to become a commit.</span>
|
||||
<a href="https://learn.microsoft.com/azure/key-vault/">learn.microsoft.com/key-vault</a></li>
|
||||
<li><b>Azure Container Registry</b><span>The managed upstream registry CI pushes to - where
|
||||
the digest is minted that everything downstream pins and promotes.</span>
|
||||
<a href="https://learn.microsoft.com/azure/container-registry/">learn.microsoft.com/container-registry</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<footer class="outro">
|
||||
<p>The Exploded Cluster · the delivery arc · every scene is one generated hero,
|
||||
sliced and scrubbed - no diagrams were harmed.</p>
|
||||
@@ -318,6 +455,15 @@ b{color:var(--ink)} .mono{font-family:var(--mono);font-size:.9em;color:var(--cya
|
||||
.key a{font-family:var(--mono);font-size:.66rem;letter-spacing:.06em;white-space:nowrap}
|
||||
@media (max-width:700px){.key li{grid-template-columns:44px 1fr}.key i,.key a{grid-column:2}}
|
||||
|
||||
.library{max-width:860px;margin:2vh auto 6vh;padding:0 24px;list-style:none;
|
||||
display:flex;flex-direction:column;gap:12px}
|
||||
.library li{display:grid;grid-template-columns:190px 1fr auto;gap:16px;align-items:baseline;
|
||||
border:1px solid var(--line);border-radius:8px;padding:14px 18px;background:#0a1020}
|
||||
.library b{font-family:var(--mono);font-size:.78rem;letter-spacing:.06em;color:var(--cyan)}
|
||||
.library span{font-size:.85rem;line-height:1.6;color:var(--dim)}
|
||||
.library a{font-family:var(--mono);font-size:.68rem;letter-spacing:.04em;white-space:nowrap}
|
||||
@media (max-width:760px){.library li{grid-template-columns:1fr}.library a{justify-self:start}}
|
||||
|
||||
.blueprint{max-width:1220px;margin:2vh auto 4vh;padding:0 24px}
|
||||
.blueprint img{width:100%;height:auto;display:block;border-radius:12px}
|
||||
|
||||
@@ -384,7 +530,7 @@ body:not(.fx) .bench{display:none}
|
||||
<script>
|
||||
(() => {
|
||||
"use strict";
|
||||
const SCENES = { gitops: __MAN_GITOPS__, supply: __MAN_SUPPLY__, helm: __MAN_HELM__ };
|
||||
const SCENES = { docker: __MAN_DOCKER__, cluster: __MAN_CLUSTER__, gitops: __MAN_GITOPS__, supply: __MAN_SUPPLY__, helm: __MAN_HELM__ };
|
||||
const RM = matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
const units = [];
|
||||
|
||||
@@ -419,9 +565,12 @@ body:not(.fx) .bench{display:none}
|
||||
const lis = [...u.legend.children];
|
||||
const n = lis.length;
|
||||
u.apply = t => {
|
||||
// stagger > 0 = cascade: parts complete their travel one after another in list order
|
||||
const sg = u.man.stagger || 0;
|
||||
u.man.parts.forEach((p, i) => {
|
||||
const pt = sg ? Math.min(1, Math.max(0, t * (1 + sg * (n - 1)) - sg * i)) : t;
|
||||
u.slabs[i].style.transform =
|
||||
"translate3d(" + (p.dx * (1 - t)).toFixed(3) + "%," + (p.dy * (1 - t)).toFixed(3) + "%,0)";
|
||||
"translate3d(" + (p.dx * (1 - pt)).toFixed(3) + "%," + (p.dy * (1 - pt)).toFixed(3) + "%,0)";
|
||||
});
|
||||
u.scene.style.transform = "scale(" + (0.95 + 0.05 * t).toFixed(4) + ")";
|
||||
// the side list lights in reading order, top to bottom, as the scrub advances
|
||||
|
||||
@@ -19,12 +19,16 @@ const i = tpl.lastIndexOf("<script>");
|
||||
const j = tpl.lastIndexOf("</script>");
|
||||
if (i < 0 || j < i) throw new Error("app script block not found");
|
||||
let app = tpl.slice(i + 8, j)
|
||||
.replace("__MAN_DOCKER__", man("docker"))
|
||||
.replace("__MAN_CLUSTER__", man("cluster"))
|
||||
.replace("__MAN_GITOPS__", man("gitops"))
|
||||
.replace("__MAN_SUPPLY__", man("supply"))
|
||||
.replace("__MAN_HELM__", man("helm"));
|
||||
let body = tpl.slice(0, i) + tpl.slice(j + 9);
|
||||
|
||||
const heroes = {
|
||||
__HERO_DOCKER__: "docker-layers.webp",
|
||||
__HERO_CLUSTER__: "course-II-cluster.webp",
|
||||
__HERO_GITOPS__: "course-VI-gitops.webp",
|
||||
__HERO_SUPPLY__: "course-VII-supply-chain.webp",
|
||||
__HERO_HELM__: "course-VIII-helm-press.webp",
|
||||
|
||||
@@ -16,9 +16,13 @@ def man(tag):
|
||||
separators=(",", ":"))
|
||||
|
||||
out = (ROOT / "pilot/arc.tpl.html").read_text() \
|
||||
.replace("__MAN_DOCKER__", man("docker")) \
|
||||
.replace("__MAN_CLUSTER__", man("cluster")) \
|
||||
.replace("__MAN_GITOPS__", man("gitops")) \
|
||||
.replace("__MAN_SUPPLY__", man("supply")) \
|
||||
.replace("__MAN_HELM__", man("helm")) \
|
||||
.replace("__HERO_DOCKER__", b64("docker-layers.webp")) \
|
||||
.replace("__HERO_CLUSTER__", b64("course-II-cluster.webp")) \
|
||||
.replace("__HERO_GITOPS__", b64("course-VI-gitops.webp")) \
|
||||
.replace("__HERO_SUPPLY__", b64("course-VII-supply-chain.webp")) \
|
||||
.replace("__HERO_HELM__", b64("course-VIII-helm-press.webp")) \
|
||||
|
||||
@@ -0,0 +1,439 @@
|
||||
{
|
||||
"scene": "cluster",
|
||||
"source": "assets/raw/course-II-cluster.jpeg",
|
||||
"parts": [
|
||||
{
|
||||
"name": "command",
|
||||
"title": "The control plane",
|
||||
"blurb": "Decides - holds the truth, schedules, reconciles. The only authority in the room.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
70.1,
|
||||
23.15
|
||||
],
|
||||
[
|
||||
70.02,
|
||||
28.95
|
||||
],
|
||||
[
|
||||
68.86,
|
||||
30.8
|
||||
],
|
||||
[
|
||||
63.92,
|
||||
34.78
|
||||
],
|
||||
[
|
||||
55.0,
|
||||
42.6
|
||||
],
|
||||
[
|
||||
51.76,
|
||||
44.47
|
||||
],
|
||||
[
|
||||
49.56,
|
||||
45.13
|
||||
],
|
||||
[
|
||||
47.87,
|
||||
44.2
|
||||
],
|
||||
[
|
||||
43.26,
|
||||
41.53
|
||||
],
|
||||
[
|
||||
32.23,
|
||||
31.68
|
||||
],
|
||||
[
|
||||
30.85,
|
||||
30.52
|
||||
],
|
||||
[
|
||||
29.98,
|
||||
29.1
|
||||
],
|
||||
[
|
||||
29.83,
|
||||
27.54
|
||||
],
|
||||
[
|
||||
30.63,
|
||||
21.55
|
||||
],
|
||||
[
|
||||
47.43,
|
||||
9.27
|
||||
],
|
||||
[
|
||||
49.73,
|
||||
8.07
|
||||
],
|
||||
[
|
||||
50.71,
|
||||
8.2
|
||||
],
|
||||
[
|
||||
68.5,
|
||||
20.84
|
||||
],
|
||||
[
|
||||
69.3,
|
||||
21.57
|
||||
]
|
||||
],
|
||||
"dx": 0.0,
|
||||
"dy": 0.0
|
||||
},
|
||||
{
|
||||
"name": "worker-1",
|
||||
"title": "Worker node",
|
||||
"blurb": "Runs pods. Identical and replaceable by design - cattle, not pets.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
32.59,
|
||||
76.73
|
||||
],
|
||||
[
|
||||
30.36,
|
||||
76.47
|
||||
],
|
||||
[
|
||||
23.8,
|
||||
71.93
|
||||
],
|
||||
[
|
||||
23.29,
|
||||
71.16
|
||||
],
|
||||
[
|
||||
22.71,
|
||||
69.64
|
||||
],
|
||||
[
|
||||
22.56,
|
||||
68.69
|
||||
],
|
||||
[
|
||||
22.35,
|
||||
51.98
|
||||
],
|
||||
[
|
||||
22.42,
|
||||
49.83
|
||||
],
|
||||
[
|
||||
22.56,
|
||||
49.04
|
||||
],
|
||||
[
|
||||
23.73,
|
||||
46.8
|
||||
],
|
||||
[
|
||||
30.59,
|
||||
42.2
|
||||
],
|
||||
[
|
||||
31.6,
|
||||
41.67
|
||||
],
|
||||
[
|
||||
32.52,
|
||||
41.8
|
||||
],
|
||||
[
|
||||
33.62,
|
||||
42.47
|
||||
],
|
||||
[
|
||||
39.21,
|
||||
46.19
|
||||
],
|
||||
[
|
||||
40.01,
|
||||
47.18
|
||||
],
|
||||
[
|
||||
40.88,
|
||||
49.36
|
||||
],
|
||||
[
|
||||
41.03,
|
||||
52.59
|
||||
],
|
||||
[
|
||||
41.1,
|
||||
68.65
|
||||
],
|
||||
[
|
||||
40.95,
|
||||
69.59
|
||||
],
|
||||
[
|
||||
40.37,
|
||||
71.1
|
||||
],
|
||||
[
|
||||
40.01,
|
||||
71.66
|
||||
]
|
||||
],
|
||||
"dx": 11.06,
|
||||
"dy": -19.39
|
||||
},
|
||||
{
|
||||
"name": "worker-2",
|
||||
"title": "Worker node",
|
||||
"blurb": "Interchangeable with its neighbours - lose one and the promise re-lands its pods elsewhere.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
59.78,
|
||||
62.5
|
||||
],
|
||||
[
|
||||
59.78,
|
||||
74.77
|
||||
],
|
||||
[
|
||||
59.7,
|
||||
81.75
|
||||
],
|
||||
[
|
||||
59.63,
|
||||
82.22
|
||||
],
|
||||
[
|
||||
59.56,
|
||||
82.53
|
||||
],
|
||||
[
|
||||
58.83,
|
||||
84.19
|
||||
],
|
||||
[
|
||||
58.54,
|
||||
84.56
|
||||
],
|
||||
[
|
||||
52.87,
|
||||
88.87
|
||||
],
|
||||
[
|
||||
51.1,
|
||||
90.07
|
||||
],
|
||||
[
|
||||
50.85,
|
||||
90.2
|
||||
],
|
||||
[
|
||||
49.12,
|
||||
90.2
|
||||
],
|
||||
[
|
||||
48.87,
|
||||
90.07
|
||||
],
|
||||
[
|
||||
48.29,
|
||||
89.67
|
||||
],
|
||||
[
|
||||
41.39,
|
||||
84.65
|
||||
],
|
||||
[
|
||||
41.1,
|
||||
84.27
|
||||
],
|
||||
[
|
||||
40.44,
|
||||
82.76
|
||||
],
|
||||
[
|
||||
40.3,
|
||||
82.12
|
||||
],
|
||||
[
|
||||
40.22,
|
||||
81.65
|
||||
],
|
||||
[
|
||||
40.15,
|
||||
72.96
|
||||
],
|
||||
[
|
||||
40.15,
|
||||
62.14
|
||||
],
|
||||
[
|
||||
40.22,
|
||||
61.52
|
||||
],
|
||||
[
|
||||
40.37,
|
||||
60.89
|
||||
],
|
||||
[
|
||||
41.02,
|
||||
59.38
|
||||
],
|
||||
[
|
||||
41.24,
|
||||
59.02
|
||||
],
|
||||
[
|
||||
41.53,
|
||||
58.63
|
||||
],
|
||||
[
|
||||
45.13,
|
||||
56.07
|
||||
],
|
||||
[
|
||||
49.37,
|
||||
53.4
|
||||
],
|
||||
[
|
||||
49.7,
|
||||
53.27
|
||||
],
|
||||
[
|
||||
50.28,
|
||||
53.27
|
||||
],
|
||||
[
|
||||
50.61,
|
||||
53.4
|
||||
],
|
||||
[
|
||||
54.86,
|
||||
56.07
|
||||
],
|
||||
[
|
||||
58.54,
|
||||
58.92
|
||||
],
|
||||
[
|
||||
58.76,
|
||||
59.27
|
||||
],
|
||||
[
|
||||
59.63,
|
||||
61.26
|
||||
],
|
||||
[
|
||||
59.7,
|
||||
61.73
|
||||
]
|
||||
],
|
||||
"dx": 0.28,
|
||||
"dy": -26.71
|
||||
},
|
||||
{
|
||||
"name": "worker-3",
|
||||
"title": "Worker node",
|
||||
"blurb": "The fleet grows by adding more of exactly this.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
58.9,
|
||||
69.09
|
||||
],
|
||||
[
|
||||
58.97,
|
||||
50.11
|
||||
],
|
||||
[
|
||||
59.19,
|
||||
49.18
|
||||
],
|
||||
[
|
||||
60.21,
|
||||
47.22
|
||||
],
|
||||
[
|
||||
66.51,
|
||||
42.2
|
||||
],
|
||||
[
|
||||
67.2,
|
||||
41.8
|
||||
],
|
||||
[
|
||||
68.05,
|
||||
41.67
|
||||
],
|
||||
[
|
||||
68.73,
|
||||
41.93
|
||||
],
|
||||
[
|
||||
73.28,
|
||||
44.6
|
||||
],
|
||||
[
|
||||
76.2,
|
||||
46.67
|
||||
],
|
||||
[
|
||||
77.22,
|
||||
48.69
|
||||
],
|
||||
[
|
||||
77.44,
|
||||
49.51
|
||||
],
|
||||
[
|
||||
77.58,
|
||||
50.94
|
||||
],
|
||||
[
|
||||
77.51,
|
||||
58.91
|
||||
],
|
||||
[
|
||||
77.36,
|
||||
69.28
|
||||
],
|
||||
[
|
||||
77.14,
|
||||
70.44
|
||||
],
|
||||
[
|
||||
75.71,
|
||||
72.2
|
||||
],
|
||||
[
|
||||
70.98,
|
||||
75.4
|
||||
],
|
||||
[
|
||||
69.0,
|
||||
76.73
|
||||
],
|
||||
[
|
||||
67.19,
|
||||
76.73
|
||||
],
|
||||
[
|
||||
59.92,
|
||||
71.54
|
||||
],
|
||||
[
|
||||
59.05,
|
||||
69.71
|
||||
]
|
||||
],
|
||||
"dx": -11.12,
|
||||
"dy": -19.34
|
||||
}
|
||||
],
|
||||
"stagger": 0.28
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
{
|
||||
"scene": "docker",
|
||||
"source": "assets/dist/docker-layers.webp",
|
||||
"stagger": 0.35,
|
||||
"parts": [
|
||||
{
|
||||
"name": "base",
|
||||
"title": "Base image",
|
||||
"blurb": "The OS layer everything else is stacked on. Pull it once, share it across every image on the host.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
55.66
|
||||
],
|
||||
[
|
||||
27.88,
|
||||
55.66
|
||||
],
|
||||
[
|
||||
49.48,
|
||||
75.51
|
||||
],
|
||||
[
|
||||
71.88,
|
||||
55.6
|
||||
],
|
||||
[
|
||||
100,
|
||||
55.6
|
||||
],
|
||||
[
|
||||
100,
|
||||
100
|
||||
],
|
||||
[
|
||||
0,
|
||||
100
|
||||
]
|
||||
],
|
||||
"dx": 0.0,
|
||||
"dy": 0.0
|
||||
},
|
||||
{
|
||||
"name": "deps",
|
||||
"title": "Dependencies",
|
||||
"blurb": "Your packages and runtime. Change these and every layer above has to be rebuilt.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
40.64
|
||||
],
|
||||
[
|
||||
28.38,
|
||||
40.64
|
||||
],
|
||||
[
|
||||
49.76,
|
||||
55.45
|
||||
],
|
||||
[
|
||||
71.5,
|
||||
40.32
|
||||
],
|
||||
[
|
||||
100,
|
||||
40.32
|
||||
],
|
||||
[
|
||||
100,
|
||||
56.3
|
||||
],
|
||||
[
|
||||
71.88,
|
||||
56.3
|
||||
],
|
||||
[
|
||||
49.48,
|
||||
76.21
|
||||
],
|
||||
[
|
||||
27.88,
|
||||
56.36
|
||||
],
|
||||
[
|
||||
0,
|
||||
56.36
|
||||
]
|
||||
],
|
||||
"dx": 0.0,
|
||||
"dy": 13.49
|
||||
},
|
||||
{
|
||||
"name": "code",
|
||||
"title": "Application code",
|
||||
"blurb": "Your actual program \u2014 usually the smallest layer, and the one that changes every single build.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
26.54
|
||||
],
|
||||
[
|
||||
27.75,
|
||||
26.54
|
||||
],
|
||||
[
|
||||
50.77,
|
||||
40.03
|
||||
],
|
||||
[
|
||||
72.0,
|
||||
26.17
|
||||
],
|
||||
[
|
||||
100,
|
||||
26.17
|
||||
],
|
||||
[
|
||||
100,
|
||||
41.02
|
||||
],
|
||||
[
|
||||
71.5,
|
||||
41.02
|
||||
],
|
||||
[
|
||||
49.76,
|
||||
56.15
|
||||
],
|
||||
[
|
||||
28.38,
|
||||
41.34
|
||||
],
|
||||
[
|
||||
0,
|
||||
41.34
|
||||
]
|
||||
],
|
||||
"dx": 0.0,
|
||||
"dy": 28.54
|
||||
},
|
||||
{
|
||||
"name": "writable",
|
||||
"title": "Writable layer",
|
||||
"blurb": "Created fresh per container, thrown away when it dies. Anything written here is not in the image.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
100,
|
||||
0
|
||||
],
|
||||
[
|
||||
100,
|
||||
26.87
|
||||
],
|
||||
[
|
||||
72.0,
|
||||
26.87
|
||||
],
|
||||
[
|
||||
50.77,
|
||||
40.73
|
||||
],
|
||||
[
|
||||
27.75,
|
||||
27.24
|
||||
],
|
||||
[
|
||||
0,
|
||||
27.24
|
||||
]
|
||||
],
|
||||
"dx": 0.0,
|
||||
"dy": 40.1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
{
|
||||
"name": "image",
|
||||
"title": "The image",
|
||||
"blurb": "C-I's layers, shipped as one unit - the thing whose name we must say precisely.",
|
||||
"blurb": "Course I's layers, shipped as one unit - the thing whose name we must say precisely.",
|
||||
"z": 0,
|
||||
"points": [
|
||||
[
|
||||
|
||||
+4
-1
@@ -84,6 +84,8 @@ def emit(name, tag, spec):
|
||||
p["dy"] = round((ay - p["cy"]) * nest, 2)
|
||||
del p["cx"]; del p["cy"]
|
||||
man = dict(scene=tag, source=f"assets/raw/{name}", parts=parts)
|
||||
if "stagger" in spec:
|
||||
man["stagger"] = spec["stagger"]
|
||||
out = ROOT / "pilot" / f"manifest-{tag}.json"
|
||||
out.write_text(json.dumps(man, indent=1))
|
||||
print(f"manifest-{tag}.json: {len(parts)} parts ->",
|
||||
@@ -92,7 +94,8 @@ def emit(name, tag, spec):
|
||||
if __name__ == "__main__":
|
||||
mode, scenes_json, outdir = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
scenes = json.loads(pathlib.Path(scenes_json).read_text()) if mode == "emit" else None
|
||||
heroes = [("course-VI-gitops.jpeg", "gitops"),
|
||||
heroes = [("course-II-cluster.jpeg", "cluster"),
|
||||
("course-VI-gitops.jpeg", "gitops"),
|
||||
("course-VII-supply-chain.jpeg", "supply"),
|
||||
("course-VIII-helm-press.jpeg", "helm")]
|
||||
for name, tag in heroes:
|
||||
|
||||
Reference in New Issue
Block a user