Effektiv distribution av Docker-avbildning för tillfällig anslutning med låg bandbredd

Azure DevOps
Functions
Container Registry
Storage
Key Vault

När Sakernas Internet (IoT) blir allt vanligare fungerar flytt av bearbetning till gränsen som en nyckelmodell för att hantera behov som anslutning med låg latens och bandbreddsanvändning. Detta gäller särskilt i scenarier som rör mobilitet, som ofta kännetecknas av tillfälliga anslutningar med låg bandbredd. Eftersom du vanligtvis etablerar gränsenheter genom att distribuera programcontaineravbildningar kan avbrott i distributionsprocesser resultera i fel i mobila scenarier. Därför kan du behöva en tillförlitlig och elastisk distributionskapacitet för situationer när du har begränsad, tillfällig eller låg bandbredd.

Den här lösningen möjliggjorde distribution av Docker-containrar till heterogena fjärranslutna IoT-enheter över tillfälliga Internetanslutningar med låg bandbredd, till exempel via satellit, från kundens IoT Edge-plattform. CSE-teamet åstadkom detta genom att minimera storleken på distributionen till varje enhet och genom att aktivera tillförlitlig övervakning av dessa distributioner.

Potentiella användningsfall

Den här lösningen är lämplig för alla scenarier där programvarucontainrar används som en del av lösningen och anslutningen är tillfällig med låg bandbredd. Exempel är följande:

  • Mobila scenarier

  • Over-the-air-biluppdateringar

  • Olja och gas och utvinning

  • Retail

  • Överallt garanteras inte en stark anslutning

Arkitektur

I scenarier med hög bandbredd hämtar Azure IoT Edge avbildningar direkt från ett Docker-register som är tillgängligt via Internet, antingen en Docker-hubb eller en privat som Azure Container Registry (ACR). Det här är samma funktioner som när du kör kommandot "docker pull <> image_name" från en lokal dator.

Men när du tvingas arbeta med potentiellt tillfällig nätverksåtkomst, till exempel en satellitanslutning till Internet, blir Docker-pullmetoden otillförlitlig. Mer specifikt cachelagras inte förloppet om Internetanslutningen sjunker medan Docker drar avbildningen. När Internetanslutningen återupptas måste Docker därför börja hämta avbildningen från början.

I följande avsnitt beskrivs en alternativ distributionsmekanism som kompenserar för de begränsningar som uppstår vid tillfällig anslutning.

Diagrammet nedan visar den avancerade arkitekturen för den här lösningen.

Azure DevOps- och Azure-arkivering av lösningar på hög nivå

Designkrav

Kunden behövde en lösning som hade stöd för tillfällig molnanslutning med låg bandbredd, så att distribuerade program kunde fortsätta att köras lokalt och göra det möjligt för lokal personal att använda funktioner utan en fördröjning i molnfördröjningen och offline. När du är ansluten till molnet behövde lösningen använda molnanslutningen effektivt för att prioritera sändning av data enligt affärsregler som är konsekvent definierade i olika produkter.

CSE-teamet identifierade följande detaljerade krav för binär uppdatering av bildfiler:

  • Bildfiler måste överföras över en satellitanslutning med låg bandbredd (1 Mbit/s), periodvis anslutning.

  • De data som överförs bör minimeras så mycket som möjligt.

  • Kunden föredrar att fortsätta använda ett program från tredje part för att överföra filer till enheter.

  • Arbetsbelastningarna på en enhet körs i en IoT Edge Docker-avbildningar.

  • Bildstorleken sträcker sig från tiotals MB till flera GB (Windows basavbildningar är ~5,5 GB).

  • IoT Edge moduler skrivs i .NET Core 2.2.

Komponenter

Azure

Tredje part

Öppen källkod

Exempel på användningsfall

Ett stort logistikföretag ville förbättra spårningen av sina globala produktleveranser, även via geografiska områden med tillfällig molnanslutning med låg bandbredd. Produktförsändelser hade en mängd olika IoT-enheter installerade på sig för försäkrings-, säkerhets- eller spårningsändamål, beroende på vilken typ av varor som levererades. Funktionerna för dessa enheter, till exempel GPS-spårare, temperatursensorer och verktyg för att samla in andra relevanta datapunkter, varierar från en enhet till en annan. och varor kan levereras med en mängd olika transportmetoder (till exempel mark, luft och hav) och till en mängd olika fjärranslutna språk.

Lösningen har avsevärt ökat tillförlitligheten och återhämtningsförmågan i etableringsprocessen i miljöer med begränsad anslutning. Diskussionen nedan beskriver alternativutvärderingsprocessen, information om lösningen som CSE-teamet har utvecklat för den här kunden och andra scenarier där den här lösningen kan vara användbar.

Kundscenario

Kunden hade problem med att uppdatera sina enheter via den nyligen utvecklade IoT Edge-plattformen. CSE har tillsammans med kunden hanterat följande viktiga problem:

  • Hög bandbreddsförbrukning vid distribution av uppdaterad programvara till enheter.

  • Ingen standardiserad automatiserad distribution mellan enheter och inget sätt att veta vilka enheter som hade vilka uppdateringar.

  • Begränsad flexibilitet när det gäller val av teknik.

Lösningsutvärdering

Av de fyra möjliga lösningarna som CSE utvärderade var fler än en genomförbar och tillgänglig. CSE fastställde att en fullständig Dataöverföring för Docker-avbildningen var den perfekta lösningen.

Utvärderingskriterier

CSE betraktas som följande:

  • Lösningens förmåga att uppfylla kraven

    • Ja, Nej
  • IoT-enhetens komplexitet (hur mycket logik som måste implementeras på enheterna)

    • Låg, Medel, Hög
  • Azure-komplexitet (hur mycket logik som måste implementeras i Azure)

    • Låg, Medel, Hög
  • Bandbreddseffektivitet (förhållandet mellan överförda data och den totala storleken på bilden) för överföring av en bild när:

    • Det finns inga avbildningar på enheten.

    • En avbildning med samma basavbildning finns på enheten.

    • En bild som representerar en tidigare version av ett program finns på enheten.

    • En avbildning för programmet som bygger på en tidigare version av basavbildningen finns på enheten.

För utvärdering av bandbreddseffektivitet använde CSE bilder för att representera följande uppsättningar.

Scenario Beskrivning
Överför ny avbildning – Basskiktet finns redan på enheten Överföra en ny avbildning medan det redan finns en annan avbildning på enheten som delar en basavbildning. Detta representerar distributionen av ett nytt program för första gången, medan det finns ett annat program i samma operativsystem och ramverk.
Uppdatera till programlagret Ändra bara koden för ett befintligt programs avbildning. Detta representerar en typisk ändring när en användare genomför en ny funktion.
Uppdatera till basavbildning Ändra versionen av basavbildningen som programmet bygger på.

En kort beskrivning av de fyra alternativen och deras kompromisser följer.

Utvärderingsalternativ som övervägs för lösningen

Överföra Docker-lager

En avbildning är en Union File System-montering av olika filsystemskillnader, som är skrivskyddade, med ytterligare ett skrivbart lager för alla ändringar som görs när containern körs. Dessa olika filsystem kallas skikt , somi stort sett bara är mappar och filer. Skikt staplas för att utgöra grunden för en containers rotfilsystem. Eftersom skikt är skrivskyddade kan olika avbildningar dela samma lager om de har det gemensamt.

I den här lösningen återanvänds lager mellan bilder, vilket innebär att de nya lagren bara behöver överföras till enheten. Detta är vanligast i avbildningar som delar samma basskikt (vanligtvis operativsystemet, till exempel Ubuntu eller Alpine) eller i avbildningar som är uppdaterade versioner av befintliga avbildningar.

Kompromisser med den här metoden är:

  • Information om vilka lager som finns på vilka enheter som måste underhållas i initieraren.

  • Ändringar i baslagret gör att alla efterföljande lagers hash-värden ändras.

  • Konsekventa lagerhashs krävs för att jämföra.

  • Det kan leda till beroende av Docker-spara och Docker-belastning.

Docker-klienten har ändrats

Den här lösningen fokuserar på att ändra eller omsluta Docker-klienten så att den återupptar lagernedladdningen när Internetanslutningen avbryts. Som standard återupptar en Docker-hämtning en nedladdning om Internetanslutningen återställs inom ~30 minuter från avbrottet. Annars avslutas klienten och alla nedladdningsförloppet går förlorade.

Även om det här var en fungerande lösning hade den problem, bland annat:

  • Alla avbildningar på enheten behövde registreras med Docker-daemonen för att hämta avbildningarna för att maximera bandbreddseffektiviteten.

  • Docker-projektet med öppen källkod skulle behöva ändras för att stödja den här ändrade funktionen, vilket innebär en risk för projektet om förslaget avvisades av de som underhåller öppen källkod.

  • Data skulle överföras via HTTP i stället för kundens favoritlösning för snabb filöverföring, vilket skulle kräva utveckling av anpassad logik för omförsök.

  • Alla lager behövde skickas igen när en basavbildning ändrades.

På gränsen

Den här metoden flyttar avbildningsbyggmiljön till varje enhet. I det här scenariot skickas följande data till enheten:

  • Källkoden för programmet som håller på att byggas

  • En kopia av alla NuGet-paket som koden är beroende av

  • Docker-basavbildningarna för .NET Core-byggmiljön och -körningen

  • Metadata om hur slutbilden ska se ut

En bygga agent på enheten skapar sedan avbildningen och registrerar den med Device Docker Manager.

Den här lösningen avvisades eftersom:

  • Det skulle fortfarande finnas ett behov av ett sätt att flytta stora Docker-avbildningar till enheten. Avbildningar för att skapa .NET-programmet är större än de som ska köras.

  • Den här metoden fungerar bara för .NET Core-program där teamet har källkoden och inga fördelar skulle realiseras om du använder avbildningar från tredje part.

  • Det skapar behovet av att paketera och spåra flytt av NuGet-paket till enheten.

Om en avbildning inte kan byggas på enheten måste teamet felsöka byggmiljön och den skapade avbildningen via fjärranslutning, vilket är mycket telemetri som ska överföras via en potentiellt begränsad Internetanslutning.

Fullständig avbildnings-deltaöverföring

Den här metoden behandlar en Docker-avbildning som en enda binär fil. Detta uppnås genom att använda kommandot Docker save för att exportera avbildningen som en .tar-fil. Genom att exportera två Docker-avbildningar kan vi beräkna den binära delta som, när den används, transformerar en avbildning till den andra.

I den här lösningen spårar vi befintliga Docker-avbildningar på våra enheter och skapar binära delta för att omvandla en befintlig avbildning till den nya avbildning som distribueras. På så sätt överför vi endast delta över Internetanslutningen med låg bandbredd.

Utvärderingsslutslut

I följande tabell visas var och en av ovanstående lösningar som mäts mot utvärderingskriterierna från det första avsnittet.

Lösning Uppfyllt krav? Enhetskomplexitet Azure-komplexitet Transport Första avbildningen Basen finns på enheten Uppdatera till programlager Uppdatera till basskiktet
Överföra Docker-lager Yes Låg Medel FileCatalyst 100 % 10.5% 22.4% 100 %
Docker-klienten har ändrats Yes Medel Låg HTTP 100 % 10.5% 22.4% 100 %
På Gränsen No Högt Medel FileCatalyst Saknas Saknas Saknas Saknas
Fullständig deltaöverföring av avbildning Yes Lågt Högt FileCatalyst 100 % 3.2% 0.01% 16.1%

Baserat på informationen ovan har CSE valt den fullständiga avbildningsmetoden deltaöverföring. Den här lösningen krävde viss anpassad logik för att skapa de binära korrigeringarna, men det var det mest effektiva alternativet när det gäller hur mycket data som skickas till enheter.

Överväganden

Lösningsinformation

Utvecklare interagerar med källkoden för sina moduler i en lagringsplats för källkod. Den grundläggande strukturen för lagringsplatsen består av mappar som innehåller koden för varje modul enligt följande:


\- repository root

    - modulea

    - modulea.csproj

    - module.json

    - Program.cs

    - Dockerfile

\- moduleb

    - moduleb.csproj

    - module.json

    - Program.cs

    - Dockerfile

Antalet lagringsplatsen för källkod är en prioritetsfråga. De två rekommenderade mönstren och vad CSE använde med den här kunden var dock:

  • En lagringsplats för alla moduler som utvecklats i alla arbetsströmmar.

  • En källkodsdatabas för varje arbetsström.

Bygg-pipelines för källlager

Det finns en Azure DevOps-bygg-pipeline för varje modul. Dessa pipelines ansvarar för:

  • Säkerhetsgenomsökning av källkoden.

  • Säkerhetsgenomsökning av basavbildningen för att skapa Docker-avbildningen.

  • Köra enhetstester för modulen.

  • Skapa källan i en Docker-avbildning. Avbildningstaggen innehåller BUILD_BUILDID så att avbildningen alltid kan länkas tillbaka till källkoden som gjorde den.

  • Push-push-avbildningen till Azure Container Registry instans.

  • Skapa deltafilen.

  • Skapa en signaturfil för avbildningen och spara den på ett Azure Storage-konto.

Alla pipelineinstanser kan baseras på en enda YAML-pipelinedefinition. Modulen kan åtgärdas med hjälp av miljövariabler, med filter som läggs till i varje pipeline, så att de bara utlöses när ändringar har gjorts i en viss mapp. På så sätt undviker du att skapa alla moduler när bara en av dem uppdateras.

Som du ser nedan används ett allmänt Docker-bygge som använder Azure DevOps Build Pipeline för att skapa och registrera moduler.

Azure Container Registry

Azure Container Registry (ACR) används för att lagra varje moduls Docker-avbildningar. Det finns två möjliga konfigurationer för ACR:

  • En enda ACR-instans som lagrar alla avbildningar

  • Ett system med två ACR-instanser: ett lagrar utvecklar-, testnings- och felsökningsavbildningar; den andra innehåller endast avbildningar som verifierats av ytterligare testning och markerats som produktionsklara.

Manifestdatabas

Manifestdatabasen innehåller distributionsmanifest för alla arbetsströmmar. Mallarna läggs i mappar baserat på det arbetsflöde som de representerar, vilket visas nedan. I det här engagemanget är de två arbetsströmmarna delad infrastruktur och containerprogrammet (programvara).


\- repository root

     - Workstream1

         - deployment.template.json

     - Workstream2

         - deployment.template.json

Avbildning-till-enhet-pipeline för manifestlager

Den här pipelinen ansvarar för att distribuera avbildningarna till olika målenheter, enligt definitionen i en manifestfil. Du måste utlösa pipelinen manuellt för att starta en distribution.

Definitionen för dessa pipelines anger att det här distributionsarbetet körs i en container. Azure DevOps stöder körning av bygg-pipelines inuti containrar och har stöd för variabel indata som avbildningen ska basera containern på. På så sätt kan en enskild variabel styra avbildningen som alla pipelines baseras på.

Den här avbildningen innehåller den kod som behövs för att avgöra vilka korrigeringar som ska byggas, för att skapa korrigeringarna och för att distribuera dem till Azure-sidan av filöverföringsverktyget.

För att kunna använda avbildningsdistributionsverktyget behöver du följande information:

  • Avbildningar som ska distribueras (tillhandahålls av manifestet på lagringsplatsen)

  • Enheter att distribuera till (tillhandahålls av användaren som utlöser pipelinen)

  • Avbildningar som redan finns på målenheterna (tillhandahålls av en SQL databas i Azure)

Utdata från pipelinen är:

  • Korrigeringspaket som skickas till Azure-sidan av filöverföringsverktyget som ska distribueras till enheterna.

  • En post i SQL som markerar vilka bilder som har börjat överföras till var och en av enheterna.

  • En post i SQL som representerar en ny distributionsuppsättning. Detta inkluderar information om vem som har beställt distributionen och en e-postadress att kontakta om något går fel med distributionen.

Den här processen omfattar följande steg:

  1. Fastställ vilka avbildningar som behövs baserat på distributionsmanifestet.

  2. Fråga SQL om du vill se vilka avbildningar som redan finns på målenheterna. Om alla finns avslutas pipelinen.

  3. Fastställ vilka korrigeringspaket som behöver skapas.

    1. Algoritmen som bestämmer startavbildningen genererar det minsta korrigeringspaketet.

    2. Indata: .tar-fil som innehåller den nya avbildning som distribueras och signaturfiler för de befintliga avbildningarna på enheterna.

    3. Utdata: en rangordning av befintliga avbildningar för att fastställa den minsta korrigeringen som ska skapas.

    4. Från den här rangordnade listan kan du fastställa vilka korrigeringar som ska byggas för varje enhet. Liknande korrigeringar byggs en gång och kopieras sedan till alla enheter som behöver dem.

  4. Skapa de nödvändiga korrigeringspaketen enligt föregående steg.

  5. Distribuera korrigeringarna till lagringskontot för filöverföringsverktyget för distribution.

  6. Uppdatera SQL att markera de nya avbildningarna som "under överföring" till var och en av målenheterna.

  7. Lägg till information om distributionsuppsättningen SQL tillsammans med kontaktmeddelandet för den person som distribuerar avbildningen.

Ursprunglig fil för ändrad fil till resulterande dataarbetsflöde

Manifestlagermanifest-till-enhet-pipeline

Den här pipelinen skickar det nya distributionsmanifestet till rätt IoT-hubb för den enhet som uppdateras. Det här är en manuellt utlöst pipeline. Pipelinen:

  • Avgör vilka avbildningar som behövs för distributionen.

  • Frågor SQL att se till att alla nödvändiga avbildningar redan finns på målenheterna.

    • Om de inte är det avslutas pipelinen här med statusen "misslyckad".
  • Push-distribuerar det nya distributionsmanifestet till rätt IoT-hubb.

Den IoT Hub instans där distributionen skickas är en miljövariabel som konfigureras när pipelinen skapas.

Snabb filöverföringslösning

Den här kunden använde redan en snabb filöverföringslösning som kallas FileCatalyst och som de föredrar att fortsätta använda. Den här lösningen, som även kallas ett "så småningom konsekvent" filöverföringsverktyg, tillhandahåller anslutningen mellan Azure och deras IoT-enheter. Konceptet med så småningom konsekvent innebär att det kan ta veckor innan en överföring går från A till B, men så småningom slutförs utan att filinformation går förlorad. CSE använde ett Azure Storage-konto på Azure-sidan av anslutningen och kundens befintliga virtuella dator för filöverföring på var och en av enheterna för att ta emot avbildningar. När korrigeringspaketen tas emot på enheten överförs de av befintliga processer till en virtuell Linux-dator. Härifrån flyttas filen till den virtuella Linux-dator som kör IoT Hub.

Modul för bildrekonstruktion

Modulen Image Rekonstruering IoT Edge ansvarar för att tillämpa mottagna korrigeringar på enheterna. Den fungerar genom att:

  1. Tar emot korrigeringspaketet i en mapp som monterats i containern.

  2. Packa upp innehållet för att läsa konfigurationsfilen.

  3. Hämta basavbildningen från det lokala containerregistret (efter hash).

  4. Spara basavbildningen som en .tar-fil.

  5. Tillämpa korrigeringen på basavbildningen.

  6. Läser in den nya .tar-filen som innehåller den nya avbildningen i Docker.

  7. Push-push-teknik för den nya avbildningen till Container Registry. Ett eget namn och en tagg ingår i konfigurationsfilen.

  8. Skicka ett meddelande till IoT Hub.

Om processen misslyckas vid något tillfälle ansvarar den här modulen för att skicka ett felmeddelande till IoT Hub så att användaren som har beställt distributionen kan meddelas. Azure-funktionen som övervakar IoT Hub dataströmmen bearbetar dessa avbildningar och vidtar åtgärder i molnet när de är klara. Arbetsflöde för åtgärdscenter och IoT-enhetskorrigering till avbildningsrestructor

Lokalt containerregister

Varje enhet är värd för ett eget lokalt containerregister. I den här lösningen använde CSE registret med öppen källkod som distribuerades av Docker. Den här processen körs på den virtuella värddatorn, som också används som den befintliga virtuella datorn för filöverföring.

Azure IoT Hub

IoT Hub används av flera andra distributionsprocesser. IoT-hubben tar emot statusmeddelanden från modulerna för bildrekonstruktion. Den anger även distributionsmanifest för de olika enheterna, och dessa manifest används sedan av resten av DevOps-flödet.

Azure Functions

En Azure-funktion används för att övervaka meddelandeströmmen som kommer från IoT-hubben. Detta ansvarar för att agera på meddelanden som skickas av modulerna för bildrekonstruktion på varje enhet.

Om ett meddelande lyckas:

  • Funktionen uppdaterar statusen för SQL posten för avbildningen på enheten från "under överföring" till "lyckades".

  • Om det här är den sista avbildningen som tas emot i en distributionsuppsättning:

    • Funktionen meddelar användaren (via e-postaviseringar som konfigurerats SQL servern) om distributionen lyckades.

    • Funktionen utlöser även en manifest-till-enhet-pipeline för att börja använda de nya avbildningarna.

När det gäller ett felmeddelande:

  • Posten SQL bilden på enhetens status uppdateras från "under överföring" till "misslyckades".

  • Användaren meddelas (via e-postaviseringar som konfigurerats SQL servern) om avbildningens överföringsfel.

Arbetsflöde för meddelande om bildkonstruktor för Operations Center- och IoT-enheter

SQL-databaser

En SQL databas ansvarar för att spåra tillståndet för vad som händer på målenheterna och de Azure-baserade distributionstjänster under och efter distributionsprocesserna.

Ett privat NuGet-paket har skapats för att interagera med databasen som används av både Azure Functions och Azure Pipelines.

De data som för närvarande lagras är:

  • Vilka avbildningar som finns på vilken enhet.

  • Vilka avbildningar som är på väg till vilken enhet.

  • Vilka avbildningar som distribueras tillhör en uppsättning och vem som har beställt distributionen.

Detta kan användas som en datakälla för en instrumentpanel som visar:

  • Tillståndet för en distribution.

  • Bilderna på en viss enhet.

  • Enheter som har en avbildning.

  • Tidsseriedata vid lyckade och misslyckade överföringar.

  • Frågor om distributioner baserat på användare.

Det primära målet under kundengagemang var att säkerställa att systemet genererade de data som skulle behövas i framtiden. Lösningen gör att framtida instrumentpaneler kan fråga IoT Hub för att få statistik om att köra IoT Edge-enheter, vilket ger insyn i framgången för manifest-till-enhet-pipelinen.

Implementeringssammanfattning

Implementeringen av den här lösningen minskade avsevärt den bandbredd som förbrukades av uppdateringar av IoT-enheter. En analys av skillnaderna i överföringseffektivitet visas nedan.

Informationsgrafik om överföringseffektivitet

Nästa steg

Mer information om de processer och tekniker som används för att skapa den här lösningen finns i: