En guide til Apache Mesos

1. Oversigt

Vi distribuerer normalt forskellige applikationer på den samme klynge af maskiner. For eksempel er det almindeligt i dag at have en distribueret behandlingsmotor som Apache Spark eller Apache Flink med distribuerede databaser som Apache Cassandra i samme klynge.

Apache Mesos er en platform, der tillader effektiv ressourcedeling mellem sådanne applikationer.

I denne artikel vil vi først diskutere et par problemer med ressourceallokering inden for applikationer, der er implementeret i samme klynge. Senere ser vi, hvordan Apache Mesos giver bedre ressourceudnyttelse mellem applikationer.

2. Deling af klyngen

Mange applikationer har brug for at dele en klynge. I det store og hele er der to almindelige tilgange:

  • Del klyngen statisk, og kør et program på hver partition
  • Tildel et sæt maskiner til en applikation

Selvom disse tilgange tillader applikationer at køre uafhængigt af hinanden, opnår det ikke høj ressourceudnyttelse.

Overvej f.eks. En applikation, der kører kun i en kort periode efterfulgt af en periode med inaktivitet. Nu, da vi har tildelt statiske maskiner eller partitioner til denne applikation, har vi det uudnyttede ressourcer i den inaktive periode.

Vi kan optimere ressourceudnyttelsen ved at allokere gratis ressourcer i den inaktive periode til andre applikationer.

Apache Mesos hjælper med dynamisk ressourceallokering mellem applikationer.

3. Apache Mesos

Med begge klyngedelingstilgange, som vi diskuterede ovenfor, er applikationer kun opmærksomme på ressourcerne til en bestemt partition eller maskine, de kører. Apache Mesos giver dog et abstrakt overblik over alle ressourcerne i klyngen til applikationer.

Som vi snart vil se, fungerer Mesos som en grænseflade mellem maskiner og applikationer. Det giver applikationer med tilgængelige ressourcer på alle maskiner i klyngen. Det opdaterer ofte disse oplysninger, så de inkluderer ressourcer, der frigøres af applikationer der har nået færdiggørelsesstatus. Dette gør det muligt for applikationer at træffe den bedste beslutning om, hvilken opgave der skal udføres på hvilken maskine.

For at forstå hvordan Mesos fungerer, lad os se på dens arkitektur:

Dette billede er en del af den officielle dokumentation for Mesos (kilde). Her, Hadoop og MPI er to applikationer, der deler klyngen.

Vi vil tale om hver komponent, der vises her i de næste par sektioner.

3.1. Mesos Master

Master er kernekomponenten i denne opsætning og gemmer den aktuelle tilstand af ressourcer i klyngen. Derudover fungerer det som en orkestrator mellem agenterne og applikationerne ved at videregive oplysninger om ting som ressourcer og opgaver.

Da enhver fejl i master resulterer i tab af tilstand om ressourcer og opgaver, implementerer vi den i konfiguration med høj tilgængelighed. Som det kan ses i diagrammet ovenfor, anvender Mesos standby-master-dæmoner sammen med en leder. Disse dæmoner er afhængige af Zookeeper for at komme sig igen i tilfælde af en fiasko.

3.2. Mesos Agenter

En Mesos-klynge skal køre en agent på hver maskine. Disse agenter rapportere deres ressourcer regelmæssigt til mesteren og igen modtage opgaver, som en applikation har planlagt at køre. Denne cyklus gentages, når den planlagte opgave enten er afsluttet eller mistet.

Vi får se, hvordan applikationer planlægger og udfører opgaver på disse agenter i de følgende sektioner.

3.3. Mesos rammer

Mesos tillader applikationer at implementere en abstrakt komponent, der interagerer med mesteren til modtage de tilgængelige ressourcer i klyngen og desuden træffe beslutninger om planlægning baseret på dem. Disse komponenter er kendt som rammer.

En Mesos-ramme består af to underkomponenter:

  • Planlægning - Gør det muligt for applikationer at planlægge opgaver baseret på tilgængelige ressourcer på alle agenter
  • Eksekutor - Kører på alle agenter og indeholder alle de oplysninger, der er nødvendige for at udføre enhver planlagt opgave på denne agent

Hele denne proces er afbildet med denne strømning:

For det første rapporterer agenterne deres ressourcer til mesteren. På dette øjeblik tilbyder master disse ressourcer til alle registrerede planlæggere. Denne proces er kendt som et ressourcetilbud, og vi vil diskutere det detaljeret i det næste afsnit.

Planlæggeren vælger derefter den bedste agent og udfører forskellige opgaver på den gennem masteren. Så snart eksekutøren fuldfører den tildelte opgave, offentliggør agenter deres ressourcer igen til mesteren. Master gentager denne proces med ressourcedeling for alle rammer i klyngen.

Mesos tillader applikationer at implementere deres brugerdefinerede planlægning og eksekutor på forskellige programmeringssprog. En Java-implementering af scheduler skal implementeredet Planlægning interface:

offentlig klasse HelloWorldScheduler implementerer Scheduler {@Override offentlig ugyldig registreret (SchedulerDriver schedulerDriver, Protos.FrameworkID frameworkID, Protos.MasterInfo masterInfo) {} @Override public void omregistreret (SchedulerDriver schedulerDriver, Protos.MasterInfoid masterinfo) schedulerDriver, List list) {} @Override public void offerRescinded (SchedulerDriver schedulerDriver, OfferID offerID) {} @Override public void statusUpdate (SchedulerDriver schedulerDriver, Protos.TaskStatus taskStatus) {} @Overridriverriverrider , Protos.SlaveID slaveID, byte [] bytes) {} @ Overstyr offentlig ugyldig afbrudt (SchedulerDriver schedulerDriver) {} @ Override public void slaveLost (SchedulerDriver schedulerDriver, Protos.SlaveID slaveID) {} @Override public voiduler executor .ExecutorID executorID, Protos.SlaveID slaveID, i nt i) {} @Override offentlig ugyldig fejl (SchedulerDriver schedulerDriver, String s) {}}

Som det kan ses, består det for det meste af forskellige tilbagekaldsmetoder til kommunikation med mesteren i særdeleshed.

Tilsvarende skal implementeringen af ​​en eksekutor implementere Eksekutor grænseflade:

offentlig klasse HelloWorldExecutor implementerer Executor {@Override offentlig ugyldig registreret (ExecutorDriver driver, Protos.ExecutorInfo executorInfo, Protos.FrameworkInfo frameworkInfo, Protos.SlaveInfo slaveInfo) {} @Override public ugyldigt omregistreret (ExecutorDriver driver, ProtosveInfo) slavefo offentlig tomrum afbrudt (ExecutorDriver-driver) {} @Override offentlig ugyldig launchTask (ExecutorDriver-driver, Protos.TaskInfo-opgave) {} @Override public void killTask ​​(ExecutorDriver driver, Protos.TaskID taskId) {} ​​@Override public void frameworkMessage driver, ExecutorDr byte [] data) {} @Override offentlig ugyldig nedlukning (ExecutorDriver-driver) {}}

Vi ser en operationel version af planlæggeren og eksekutøren i et senere afsnit.

4. Ressourcestyring

4.1. Ressource tilbud

Som vi diskuterede tidligere, offentliggør agenter deres ressourceoplysninger til mesteren. Til gengæld tilbyder mesteren disse ressourcer til de rammer, der kører i klyngen. Denne proces er kendt som en ressourcetilbud.

Et ressourstilbud består af to dele - ressourcer og attributter.

Ressourcer er vant til offentliggøre hardwareoplysninger om agentmaskinen såsom hukommelse, CPU og disk.

Der er fem foruddefinerede ressourcer for hver agent:

  • cpu
  • gpus
  • mem
  • disk
  • porte

Værdierne for disse ressourcer kan defineres i en af ​​de tre typer:

  • Skalar - Bruges til at repræsentere numeriske oplysninger ved hjælp af flydende numre for at tillade brøkværdier såsom 1,5 G hukommelse
  • Rækkevidde - Bruges til at repræsentere en række skalære værdier - for eksempel et portområde
  • Sæt - Bruges til at repræsentere flere tekstværdier

Som standard forsøger Mesos-agent at opdage disse ressourcer fra maskinen.

I nogle situationer kan vi imidlertid konfigurere tilpassede ressourcer på en agent. Værdierne for sådanne brugerdefinerede ressourcer skal igen være i en hvilken som helst af de typer, der er diskuteret ovenfor.

For eksempel kan vi starte vores agent med disse ressourcer:

--ressourcer = 'cpus: 24; gpus: 2; mem: 24576; disk: 409600; porte: [21000-24000,30000-34000]; bugs (debug_role): {a, b, c}'

Som det kan ses, har vi konfigureret agenten med få af de foruddefinerede ressourcer og en brugerdefineret ressource navngivet bugs som er af sæt type.

Ud over ressourcer kan agenter offentliggøre attributter for nøgleværdier til masteren. Disse attributter fungerer som yderligere metadata for agenten og hjælper rammerne i planlægning af beslutninger.

Et nyttigt eksempel kan være at tilføj agenter til forskellige stativer eller zoner og så planlægge forskellige opgaver på samme stativ eller zone for at opnå datalokalitet:

--attributter = 'rack: abc; zone: vest; os: centos5; niveau: 10; nøgler: [1000-1500]'

Svarende til ressourcer kan værdier for attributter være enten en skalar, et interval eller en teksttype.

4.2. Ressourceroller

Mange moderne operativsystemer understøtter flere brugere. Tilsvarende understøtter Mesos også flere brugere i samme klynge. Disse brugere er kendt som roller. Vi kan betragte hver rolle som en ressourceforbruger inden for en klynge.

På grund af dette kan Mesos-agenter opdele ressourcerne under forskellige roller baseret på forskellige tildelingsstrategier. Derudover kan rammer abonnere på disse roller i klyngen og have finkornet kontrol over ressourcer under forskellige roller.

Overvej f.eks klyngehostingsapplikationer, der tjener forskellige brugere i en organisation. Så ved ved at opdele ressourcerne i roller kan hver applikation arbejde isoleret fra hinanden.

Derudover kan rammer bruge disse roller til at opnå datalokalitet.

Antag for eksempel, at vi har to applikationer i klyngen, der hedder producent og forbruger. Her, producent skriver data til et vedvarende volumen, som forbruger kan læse bagefter. Vi kan optimere forbruger applikation ved at dele lydstyrken med producent.

Da Mesos tillader flere applikationer at abonnere på den samme rolle, kan vi knytte den vedvarende lydstyrke til en ressourcerolle. Desuden rammerne for begge producent og forbruger begge vil abonnere på den samme ressourcerolle. Derfor er den forbruger applikationen kan nu starte datalæsningsopgaven på samme lydstyrke som den producent Ansøgning.

4.3. Resource Reservation

Nu kan spørgsmålet opstå, hvordan Mesos tildeler klyngeressourcer i forskellige roller. Mesos fordeler ressourcerne gennem forbehold.

Der er to typer reservationer:

  • Statisk reservation
  • Dynamisk reservation

Statisk reservation svarer til ressourceallokeringen ved opstart af agent, som vi diskuterede i de tidligere afsnit:

 --ressourcer = "cpus: 4; mem: 2048; cpus (baeldung): 8; mem (baeldung): 4096"

Den eneste forskel her er, at nu Mesos-agenten reserverer otte CPU'er og 4096m hukommelse til den navngivne rolle baeldung.

Dynamisk reservation giver os mulighed for at skifte ressourcerne inden for roller i modsætning til den statiske reservation. Mesos giver rammer og klyngeoperatører mulighed for dynamisk at ændre tildelingen af ​​ressourcer via rammemeddelelser som et svar på ressourcetilbud eller via HTTP-slutpunkter.

Mesos tildeler alle ressourcer uden nogen rolle til en standardrolle med navnet (*). Master tilbyder sådanne ressourcer til alle rammer, uanset om de har abonneret på det.

4.4. Ressourcevægte og kvoter

Generelt tilbyder Mesos-mesteren ressourcer ved hjælp af en retfærdighedsstrategi. Det bruger den vægtede Dominant Resource Fairness (wDRF) til at identificere de roller, der mangler ressourcer. Mesteren tilbyder derefter flere ressourcer til de rammer, der har abonneret på disse roller.

Begivenhed, selvom en fair deling af ressourcer mellem applikationer er et vigtigt kendetegn ved Mesos, er det ikke altid nødvendigt. Antag, at en klynge, der er vært for applikationer, der har et lavt ressourcefodaftryk sammen med dem, der har et stort ressourceefterspørgsel. I sådanne implementeringer vil vi tildele ressourcer baseret på applikationens art.

Mesos tillader rammer at kræve flere ressourcer ved at abonnere på roller og tilføje en højere vægtværdi for denne rolle. Derfor, hvis der er to roller, en af ​​vægt 1 og en anden af ​​vægt 2, tildeler Mesos dobbelt den retfærdige andel af ressourcerne til den anden rolle.

Svarende til ressourcer kan vi konfigurere vægte via HTTP-slutpunkter.

Udover at sikre en rimelig andel af ressourcer til en rolle med vægte, sikrer Mesos det også minimumsressourcerne til en rolle tildeles.

Mesos tillader os at tilføj kvoter til ressourcerollerne. En kvote specificerer det minimum af ressourcer, som en rolle garanteres at modtage.

5. Implementeringsramme

Som vi diskuterede i et tidligere afsnit, tillader Mesos applikationer at levere rammeimplementeringer på et sprog efter eget valg. I Java implementeres en ramme ved hjælp af hovedklassen - som fungerer som et indgangspunkt for rammeprocessen - og implementeringen af Planlægning og Eksekutor diskuteret tidligere.

5.1. Framework Main Class

Før vi implementerer en planlægger og en eksekutor, implementerer vi først startpunktet for vores ramme, der:

  • Registrerer sig hos mesteren
  • Giver eksekutør runtime information til agenter
  • Starter planlæggeren

Vi tilføjer først en Maven-afhængighed for Mesos:

 org.apache.mesos mesos 0.28.3 

Dernæst implementerer vi HelloWorldMain for vores rammer. En af de første ting, vi skal gøre, er at starte eksekutorprocessen på Mesos-agenten:

public static void main (String [] args) {String path = System.getProperty ("user.dir") + "/target/libraries2-1.0.0-SNAPSHOT.jar"; CommandInfo.URI uri = CommandInfo.URI.newBuilder (). SetValue (sti) .setExtract (false) .build (); String helloWorldCommand = "java -cp biblioteker2-1.0.0-SNAPSHOT.jar com.baeldung.mesos.executors.HelloWorldExecutor"; CommandInfo commandInfoHelloWorld = CommandInfo.newBuilder () .setValue (helloWorldCommand) .addUris (uri) .build (); ExecutorInfo executorHelloWorld = ExecutorInfo.newBuilder () .setExecutorId (Protos.ExecutorID.newBuilder () .setValue ("HelloWorldExecutor")) .setCommand (commandInfoHelloWorld) .setName ("Hello World (Java)") .setSource ("java"). build (); }

Her konfigurerede vi først eksekutorens binære placering. Mesos-agent ville downloade denne binær ved rammeregistrering. Derefter kørte agenten den givne kommando for at starte eksekutorprocessen.

Dernæst initialiserer vi vores ramme og starter planlæggeren:

FrameworkInfo.Builder frameworkBuilder = FrameworkInfo.newBuilder () .setFailoverTimeout (120000) .setUser ("") .setName ("Hello World Framework (Java)"); frameworkBuilder.setPrincipal ("test-framework-java"); MesosSchedulerDriver driver = ny MesosSchedulerDriver (ny HelloWorldScheduler (), frameworkBuilder.build (), args [0]);

Langt om længe, vi starter MesosSchedulerDriver der registrerer sig hos mesteren. For en vellykket registrering skal vi bestå masterens IP som et programargument args [0] til denne hovedklasse:

int status = driver.run () == Protos.Status.DRIVER_STOPPED? 0: 1; driver.stop (); System.exit (status);

I klassen vist ovenfor, CommandInfo, ExecutorInfo, og FrameworkInfo er alle Java-repræsentationer af protobuf-meddelelser mellem master og rammer.

5.2. Implementeringsplanlægning

Siden Mesos 1.0, Vi kan påkalde HTTP-slutpunktet fra ethvert Java-program til at sende og modtage meddelelser til Mesos-masteren. Nogle af disse meddelelser inkluderer for eksempel rammeregistrering, ressourcetilbud og afvisning af tilbud.

Til Mesos 0.28 eller tidligere skal vi implementere Planlægning interface:

For det meste fokuserer vi kun på resourceOffers metode til Planlægning. Lad os se, hvordan en planlægger modtager ressourcer og initialiserer opgaver baseret på dem.

Først ser vi, hvordan planlæggeren tildeler ressourcer til en opgave:

@Override public void resourceOffers (SchedulerDriver schedulerDriver, List list) {for (Offer offer: list) {List Tasks = new ArrayList (); Protos.TaskID taskId = Protos.TaskID.newBuilder () .setValue (Integer.toString (LaunchTasks ++)). Build (); System.out.println ("Start af printHelloWorld" + taskId.getValue () + "Hello World Java"); Protos.Resource.Builder cpus = Protos.Resource.newBuilder () .setName ("cpus") .setType (Protos.Value.Type.SCALAR) .setScalar (Protos.Value.Scalar.newBuilder () .setValue (1)) ; Protos.Resource.Builder mem = Protos.Resource.newBuilder () .setName ("mem"). SetType (Protos.Value.Type.SCALAR) .setScalar (Protos.Value.Scalar.newBuilder () .setValue (128)) ;

Her tildelte vi 1 CPU og 128M hukommelse til vores opgave. Dernæst bruger vi Planlægningsdriver at starte opgaven på en agent:

 TaskInfo printHelloWorld = TaskInfo.newBuilder () .setName ("printHelloWorld" + taskId.getValue ()) .setTaskId (taskId) .setSlaveId (offer.getSlaveId ()) .addResources (cpus) .addResources (mem) .setExecutor. newBuilder (helloWorldExecutor)) .build (); List offerIDS = ny ArrayList (); offerIDS.add (offer.getId ()); task.add (printHelloWorld); schedulerDriver.launchTasks (offerIDS, opgaver); }}

Alternativt Planlægning finder ofte behovet for at afvise ressourcetilbud. For eksempel, hvis Planlægning ikke kan starte en opgave på en agent på grund af manglende ressourcer, skal den straks afvise dette tilbud:

schedulerDriver.declineOffer (offer.getId ());

5.3. Implementerer Eksekutor

Som vi diskuterede tidligere, er eksekutorkomponenten i rammen ansvarlig for at udføre applikationsopgaver på Mesos-agenten.

Vi brugte HTTP-slutpunkterne til implementering Planlægning i Mesos 1.0. På samme måde kan vi bruge HTTP-slutpunktet til eksekutoren.

I et tidligere afsnit diskuterede vi, hvordan en ramme konfigurerer en agent til at starte eksekutorprocessen:

java -cp biblioteker2-1.0.0-SNAPSHOT.jar com.baeldung.mesos.executors.HelloWorldExecutor

Især denne kommando overvejer HelloWorldExecutor som hovedklasse. Vi implementerer dette vigtigste metode til initialisere MesosExecutorDriver der forbinder med Mesos-agenter for at modtage opgaver og dele andre oplysninger som opgavestatus:

offentlig klasse HelloWorldExecutor implementerer Executor {public static void main (String [] args) {MesosExecutorDriver driver = new MesosExecutorDriver (new HelloWorldExecutor ()); System.exit (driver.run () == Protos.Status.DRIVER_STOPPED? 0: 1); }}

Den sidste ting at gøre nu er at acceptere opgaver fra rammen og starte dem på agenten. Oplysningerne til at starte en opgave er selvstændige inden for HelloWorldExecutor:

public void launchTask (ExecutorDriver driver, TaskInfo task) {Protos.TaskStatus status = Protos.TaskStatus.newBuilder () .setTaskId (task.getTaskId ()) .setState (Protos.TaskState.TASK_RUNNING) .build (); driver.sendStatusUpdate (status); System.out.println ("Udfør opgave !!!"); status = Protos.TaskStatus.newBuilder () .setTaskId (task.getTaskId ()) .setState (Protos.TaskState.TASK_FINISHED) .build (); driver.sendStatusUpdate (status); }

Selvfølgelig er dette bare en simpel implementering, men det forklarer, hvordan en eksekutor deler opgavestatus med mesteren på hvert trin og derefter udfører opgaven, før han sender en færdiggørelsesstatus.

I nogle tilfælde kan eksekutører også sende data tilbage til planlæggeren:

String myStatus = "Hej Framework"; driver.sendFrameworkMessage (myStatus.getBytes ());

6. Konklusion

I denne artikel diskuterede vi kort ressourcedeling mellem applikationer, der kører i samme klynge. Vi diskuterede også, hvordan Apache Mesos hjælper applikationer med at opnå maksimal udnyttelse med en abstrakt visning af klyngeressourcerne som CPU og hukommelse.

Senere diskuterede vi dynamisk fordeling af ressourcer mellem applikationer baseret på forskellige retfærdighedspolitikker og roller. Mesos tillader applikationer at lave planlægning af beslutninger baseret på ressourcetilbud fra Mesos agenter i klyngen.

Endelig så vi en implementering af Mesos-rammen i Java.

Som normalt er alle eksempler tilgængelige på GitHub.