Naar de inhoud

Blog ·

Een script dat weet dat het om een container gaat

Zeven optionele velden waar ontbreken niet vastgesteld betekent, een tabel waarvan de test zijn gevallen afleidt, en een OS in de verkeerde lijst.

Door Provibr

Een Proxmox-host kan twee heel verschillende dingen draaien: een volledige virtuele machine met een eigen kernel en eigen firmware, en een container die de kernel van de host deelt. Van een afstand zijn het allebei "een server" en het paneel zet ze in één lijst. Van dichtbij verschillen ze op manieren die ertoe doen voor wie automatisering schrijft, en tot deze ronde kon een script ze niet uit elkaar houden.

Dat is een slechte positie. Een script dat een container vraagt een virtuele schijf te vergroten, een ISO aan te koppelen of van het netwerk te starten vraagt niet om iets moeilijks; het vraagt om iets dat niet bestaat. De mislukking komt vier lagen later aan, als een commando dat aanvaard, in de wachtrij gezet, verstuurd en toen door een agent geweigerd is.

Zeven velden, en ontbreken betekent niet vastgesteld

Scripts en webhooks krijgen nu een groep feiten over wat er onder een server zit: zijn soort, het sjabloon waar hij uit komt, of hij onbevoorrecht is, de storage waar zijn root op staat, zijn mountpoints, wat hij werkelijk kan, en wat hij niet kan.

Elk van die velden mag ontbreken, en ontbreken betekent niet vastgesteld. Dat is dezelfde regel als de onderliggende kolom volgt, waar de soort nooit stil is bijgevuld, en hij bestaat omdat het alternatief erger is dan nutteloos. Een momentopname die "virtuele machine" invult terwijl niemand het ooit gemeten heeft, is een gok die aan een script wordt gegeven dat er een besluit op neemt.

Een onbekende soort wordt dus geen standaardwaarde. Het veld verdwijnt volledig uit de rendercontext, en het lezen ervan is dan een harde fout op het moment dat de flow wordt opgeslagen, in plaats van een lege tekenreeks die een voorwaarde stil onwaar maakt. Dat is dezelfde redenering als het verwijderen van een variabelengroep die een trigger niet kan leveren: luid bij het opslaan wint van stil tijdens de run.

Het is ook de eerste geneste groep in de variabelencatalogus. Een veldnaam met een punt erin is in deze codebase normaal een val, want de vertaalcatalogus behandelt een punt als een niveau; hier plat de catalogussleutel hem bewust plat terwijl het contextpad één niveau dieper wandelt, en een test legt de aanname vast dat er precies één punt in zit.

Hostpaden reizen niet mee

Een bind mount in de configuratie van een container ziet eruit als een sleutel, een hostpad en een mountpunt. Dat hostpad is een map op de hypervisor, en het mag daar nooit vandaan.

De regel in onze eigen documentatie is bot: klanten krijgen via Provibr nooit een hostshell, een pad in het hostbestandssysteem of een rootcredential van de hypervisor. Een variabelenmomentopname is precies zo'n weg. Hij belandt in een script, in een webhookbody bij een derde partij, en in een auditrij.

De momentopname draagt de bron dus nooit. Wat overblijft is wat een klant over zijn eigen container mag weten: welke sleutel het is, waar hij in de container hangt, en uit welke soort bron hij komt. Eén vaste tekstvorm, want een script leest dit door op een scheidingsteken te splitsen en niet door proza te ontleden: mp1:bind:/srv zegt dat er een bind mount op /srv hangt, en zegt helemaal niets over waar hij op de host vandaan komt.

Dat geldt ook voor een volume-mount. Een storagenaam is geen hostpad, maar het is wel de eigen naamgeving van de hypervisor, en geen enkele scriptvraag heeft hem nodig. De storagenaam verschijnt één keer, apart, als één woord dat de klant bij zijn bestelling al zag.

De prijs van dit ontwerp staat er eerlijk bij in plaats van verborgen: de mountfeiten komen uit de configuratie die de agent tijdens een backup leest, dus een container die nog nooit een backup had levert helemaal geen mountpoints. Het veld ontbreekt dan, en dat is juist, want een lege lijst zou beweren dat de container geen mountpoints heeft.

Een tabel waarvan de test zijn eigen gevallen afleidt

Er was al een geschreven tabel die per commando voor virtuele machines zegt of een container het kan en waarom niet. Wat ontbrak was een tabel die élk commando dekt dat een Proxmox-koppeling kan dragen, inclusief backups en de vier lezingen die over de koppeling gaan en niet over één gast.

Zonder dat onderscheid kan een zeef "geen oordeel vastgelegd" niet onderscheiden van "dit gaat helemaal niet over een gast", en het enige veilige gedrag voor het tweede is doorlaten. Dat is precies de stille tak waar dit project zich aan blijft branden.

De nieuwe tabel is daarom afgeleid uit de geschreven tabel in plaats van ernaast geschreven, en de test somt geen gevallen op. Hij berekent de bereikbare verzameling uit de registers, door elk commandokind te nemen dat de Proxmox-provider niet weigert en dat ook een gastresource bedient, plus de lezingen die op de providerdescriptor zelf staan, en eist dan per kind een uitspraak. Zevenentwintig gastcommando's en vier koppelingslezingen, en de test is eerst rood bewezen en daarna groen.

Een test per geval kan een ontbrekend geval niet vinden. Die les heeft deze codebase nu drie keer geleerd, en dit is de derde vorm van dezelfde bewaking.

Eén commando ontbreekt met opzet, en het commentaar zegt waar je het moet zoeken. Een commando ín een container uitvoeren zou vandaag betekenen dat het als root op de hypervisor draait, buiten de container, met de rechten van de host. Dat is geen scriptfunctie met een kleine voetafdruk; het is een hostshell met een vriendelijke naam. Wie hem bouwt krijgt een eigen ronde, met een uitvoerder ín de gast, een eigen recht en een eigen auditspoor.

Een weigering vóór de dispatch laat geen rij achter

De gateway weigerde onmogelijke commando's al. Die weigering overkomt een commando dat er al ís: de rij staat in de database, de operatie is aangemaakt, en de klant kijkt naar een opdracht die mislukt.

De eis was validatie vóór de dispatch, en dat is precies het verschil. Een container om zijn virtuele hardware vragen hoort een zin op te leveren en geen auditrij.

De twee zeven kunnen niet uit elkaar lopen, want ze lezen dezelfde tabel. Dit is geen tweede waarheid; het is dezelfde waarheid, één laag eerder. De gateway blijft nodig voor het herhaalde of nagemaakte verzoek dat nooit langs de paneelfunctie komt.

De weigeringsreden wordt gerenderd als één bericht met een tak per reden, en de bewaking eromheen eist twee dingen: een tak voor élke reden, en dat de zinnen onderling verschillen. Een ontbrekende tak in een taalkeuze valt door naar de standaard en zegt iets dat klopt en niets betekent, en dat faalgedrag heeft dit project eerder meegemaakt.

Het besturingssysteem in de verkeerde lijst

De bevinding die alleen een echte database opleverde had met niets van het bovenstaande te maken.

Regels voor besturingssystemen bewaarden hun installatiebron vroeger in één kolom en nu in twee, waarbij de oude kolom als terugval gelezen wordt voor rijen die geen enkele nieuwe schrijver ooit heeft aangeraakt. Containersjablonen kwamen er later bij en gaan naar een eigen kolom, en worden op een verse rij ook naar de oude geprojecteerd.

De terugval wist daar niets van. Hij las een containerverwijzing in de legacykolom als sjabloon voor een virtuele machine, waardoor een besturingssysteem met alleen een containersjabloon in de lijst met virtuele machines van de bestelflow stond, zonder computesoort, en een bestelling daarop later zou stranden op een kloonbron zonder id om van te klonen.

De reparatie is één tak: een containerverwijzing in de legacykolom is geen bron voor een virtuele machine. Er gaat niets verloren, want de containerkant leest zijn eigen kolom en nergens anders, en rijen die oud genoeg zijn om de terugval nodig te hebben kunnen per constructie geen containerverwijzing dragen: die kolom bestond toen nog niet.

Een tweede bevinding kwam uit een schermafbeelding en niet uit een controle. In de lijst met dingen die een container niet kan stond een betaalcommando dat bij een andere provider hoort en op Proxmox voor geen van beide soorten bestaat. Waar, en volstrekt misplaatst op de detailpagina van een container. Het is uit die lijst gehaald.

Wat wij zouden opschrijven

  1. Afwezig is een antwoord. Weet je de soort niet, vul dan geen standaardwaarde in. Een gok die aan automatisering wordt doorgegeven is erger dan een gat dat het script kan zien.
  2. Rechtenveiligheid is een eigenschap van de vorm en niet van de aanroeper. Ontwerp de momentopname zo dat het hostpad er niet in zit, dan kan geen enkele latere lezer hem lekken.
  3. Eén vaste tekstvorm wint van proza. Er gaat iemand op een scheidingsteken splitsen.
  4. Leid de gevallen af uit het register. Een test per geval kan het geval dat niemand schreef per constructie niet vinden.
  5. Weiger voordat je vastlegt. Een weigering die een auditrij oplevert heeft de klant al het verkeerde verhaal verteld.
  6. Kijk naar de schermafbeeldingen. De misplaatste regel was waar, kwam door elke controle heen, en was voor een mens meteen zichtbaar fout.

Voor de duidelijkheid over wat dit is: containers zijn op Proxmox te bestellen en de computefeiten staan live. Meerdere dingen zijn onbewezen. Niets ervan is in deze ronde tegen een echte hypervisor beproefd, de mountfeiten hangen ervan af dat er minstens één keer een backup is geweest, één zin in de bestelflow zegt op een container nog "de VM", en de licentieteller telt een container nog als virtuele machine.

Uit het platformwerk van Provibr. Waarom een onbevoorrechte container een meting is en geen instelling staat in unprivileged is een meting, geen instelling, en welke mountpoints een containerbackup wel en niet bevat staat in wat er niet in een backup zit.

Begin met één host en één agent

Maak een account aan, installeer de agent met één commando en koppel je eerste Proxmox-host. De proefperiode loopt 14 dagen en vraagt geen betaalgegevens.