feat(bootstrap): host every built image in the internal registry — GC-durable pulls
The disk-pressure drill's dead end: kubelet's image GC collects an unused image
and an air-gapped node has nothing to pull it from (ImagePullBackOff until an
operator re-imports). The registry the bundle already renders becomes that pull
source:
- Every image the installer builds is now a registry ref
(registry.felis.svc:5000/felis/{felis,limbo,lobby,paper}:demo), imported into
containerd under that exact name (first boot needs no registry round-trip)
and mirrored into the registry after deploy_bundle (push_image_to_registry:
push endpoint 127.0.0.1:5000, and only the path after the host matters to the
registry — a push there lands where kubelet's mirrored pull looks). A ref
outside the registry is warned about, not silently unmirrored.
- configure_registry_mirror writes /etc/rancher/k3s/registries.yaml mapping
registry.felis.svc:5000 onto http://127.0.0.1:5000, the loopback hostPort the
registry Deployment binds (node containerd cannot dial the Service VIP — live
drill: "Empty reply"). k3s regenerates containerd config only at agent start,
so a CONTENT change restarts k3s and an identical file (every re-run)
restarts nothing.
- import_registry_image caches registry:2 into containerd so the registry
Deployment can start on a box that cannot reach Docker Hub.
- Migration 0021 re-points the recommended whitelist seeds ('felis-lobby:demo',
'felis-paper:demo') at the registry refs — a user server created from those
rows must not strand when GC collects the bare tag. Only recommended rows
still holding the old seed are touched; enabled is preserved; a pre-existing
target row wins over a duplicate.
bootstrap_test.sh pins the mirror idempotence (identical content must NOT
restart k3s), the push-ref mapping (including the port-confusion refusal) and
the registry:2 precheck.
This commit is contained in:
5 files changed
+303
-17
No files matched your search
@@ -183,11 +183,11 @@ func (s *PGStore) ListImages(ctx context.Context) ([]Image, error) {
|
||||
// Image it constructed (source=external) without re-reading the row, so a sticky
|
||||
// source here would report a value the database does not hold.
|
||||
//
|
||||
// Note that the demote branch is unreachable for the ONLY recommended row Felis
|
||||
// currently seeds: the caller validates with ValidateImageRef first, which refuses
|
||||
// a bare local containerd tag, and 0018's felis-lobby:demo is exactly that. The
|
||||
// branch is written for the host-qualified recommendations this list grows into,
|
||||
// not for today's single seed.
|
||||
// Note that this demote branch is REACHABLE for today's recommended rows: 0021
|
||||
// re-pointed the seeds at host-qualified registry refs (registry.<ns>.svc:5000/…),
|
||||
// which ValidateImageRef accepts — so an admin re-admitting one of those refs
|
||||
// demotes the curated row, by design. It was dead only while the seeds were bare
|
||||
// local containerd tags (0018's felis-lobby:demo), which the validation refuses.
|
||||
func (s *PGStore) AddExternalImage(ctx context.Context, img Image) error {
|
||||
const q = `INSERT INTO image_whitelist
|
||||
(image_ref, source, added_by, enabled, added_at)
|
||||
|
||||
Reference in new issue
Block a user