V2’s emneords-spåkone går serverless

22. oktober 2019 kl. 05:113
V2’s emneords-spåkone går serverless
Illustration: Wikipedia-bruger Nillerdk.
Serverless løser en masse problemer med skygge-it. Men vejen dertil er belagt med installation af vanvittig mange kommandolinje-programmer.
Artiklen er ældre end 30 dage
Manglende links i teksten kan sandsynligvis findes i bunden af artiklen.

Hvis der ellers er nogen, der skulle være i tvivl, har Version2 lavet en hjemmestrikket machine learning-løsning, der gætter emneord til nye artikler.

Programmet kørte først på min egen pc på kontoret, som resten af kollegerne kunne tilgå med en bookmarklet i browseren. Men det var lige en tand for interimistisk. Og en dag slukkede it-afdelingen for ip-kommunikation mellem kontor-pc’er - fornuftigt nok. Hvis der kommer malware på matriklen, er det nok ikke så smart, at der kan snakkes fra pc til pc.

Vi flyttede systemet til skyen, og indtil videre har det ikke kostet en krone, da vi har brugt gratis tilbud og tjenester som Let’s Encrypt, der byder på omkostningsfri SSL-certifikater.

Vi stod altså ombord i cloud’en, hos Amazon. Det er egentlig ikke så svært, det der sky. Hvis man har lidt erfaring med Linux' bash-terminal - og mine evner er kun lige til øllet - så er det nemt at have med at gøre, synes jeg.

Artiklen fortsætter efter annoncen

Man trykker på en knap i en web-konsol, og et par minutter efter - simsalabim - så har man en sprit-ny server til rådighed, som man kan logge ind på med terminalen på ens egen pc. Det er dælme smart.

Men, men. Som vi også har kigget på i et par artikler, så følger der lidt mere med en server, end bare det at afvikle et program. Når jeg logger ind på serveren, spørger den om ikke jeg har lyst til at 'update' softwaren med yum, som er det pakkeprogram, serveren benytter.

Jeg har altså med i købet fået noget uønsket arbejde med at vedligeholde og sikre min server. Det handler ikke blot om mit eget programs velfærd.

Hvis jeg bommer med en sikkerhedsopdatering, eller har lavet en bøf i egen kode, kan ondskabsfulde typer måske overtage min server og benytte den til kriminelle formål mod andre. Det opdager jeg nok ikke lige med det samme, i mit hygge-skygge-opsæt.

Artiklen fortsætter efter annoncen

Jeg har altså en eller anden slags forpligtelse til at sørge for, at min server hos Amazon ikke er sårbar for angreb. Det arbejde får jeg strengt taget ikke bonus for, ud over god samvittighed. Og - ærlig talt - jeg er ikke devops-ekspert i Linux-sikkerhed.

Dernæst er der heller ikke noget, der hedder failover, i hvert fald ikke på min gratis-server. Hvis uheldet er ude, skal jeg bruge et script til at gendanne det hele. Sådan et lavede vi i en tidligere artikel, og det tog et stykke tid at finde ud af alle kommandoerne.

Vores program har også sin egen webserver indbygget. Den snakker med webudvidelsen, som maler spåkonens emneords-bud med gult i cms’et.

Det ville jeg ikke have behov for i serverless, for der er HTTP indbygget fra starten af som tjeneste.

Derfor serverless

Nu har jeg stort set nævnt de fleste af argumenterne for at gå serverless.

Det handler om kode, der kører i skyen, uden at man skal bekymre sig om kørselsmiljø, patches, sikkerhed, failover eller noget som helst andet, og hvor basal funktionalitet som HTTP kommer med som standard.

Hvordan det ser ud med økonomien ved et større produktionsscenarie, i forhold til alternativerne, vil vi glemme alt om her.

Serverless løser i hvert fald problemet med de arbejdsopgaver, der fulgte med min server, og som jeg ikke lige synes, jeg har bedt om.

Men kan vores hjemmelavede machine learning køre på serverless? Der er jo de kæmpemæssige hyppighedstabeller, der volder mig så mange kvaler.

Artiklen fortsætter efter annoncen

Kan det fungere i et letvægts-miljø? Jeg har ganske simpelt aldrig tænkt tanken.

Men det har cloud-konsulent Henrik Oddershede til gengæld. Han skriver til mig en dag i september:

  1. Hej Tania.
  2.  
  3. I opbygningen af din skygge-it har du brugt 'gammeldags' virtuelle maskiner (ec2- instanser), som tydeligvis kræver en del scripting at få til at fungere.
  4.  
  5. Jeg mener, det er en oplagt mulighed at skrive en artikel om, hvordan du kan få den samme funktionalitet med mindre indsats ved at køre serverless. Her overlader du meget mere arbejde til AWS, og kan fokusere på at skrive Javakoden.
  6.  
  7. Hvis du er interesseret i det, vil jeg gerne sætte en dag af til at vise dig, hvor let det er.

Sådan et tilbud og generøsitet kan jeg naturligvis ikke sige nej til.

Men jeg er ret skeptisk overfor ideen, og det lader jeg Henrik vide. De der hyppighedstabeller er jo kæmpestore? Det er vel næppe letvægt?

Han holder dog fast i sit, og man må jo tage hatten af for sagkundskaben. Så et par uger senere sidder vi i verdens mindste mødelokale i Teknologiens Mediehus, med hver vores terminal åben. Jeg bruger Windows Subsystem for Linux med Ubuntu, mens Henrik kører Red Hat på sin laptop.

Dårlig kaffe

Der er en hel masse, der skal installeres, for at komme til serverless.

Først skal vi installere Pythons pakke-værktøj Pip med kommandoen

  1. sudo apt install python3-pip

Det går frygtelig langsomt - om det er vores wifi-netværk eller min Windows Subsystem for Linux, der skaber flaskehalsen, bliver aldrig helt klart.

Vores fancy kapsel-kaffemaskine er gået i stykker, og der er kun almindelig filterkaffe til rådighed på fjerde sal. Henrik vil hellere have et glas vand fra vandhanen. Det kan jeg godt forstå - kaffen dufter og smager aldeles grufuldt. Jeg føler mig lidt pinligt berørt, det må jeg indrømme. Det er altså ikke det indtryk, som Version2 og Teknologiens Mediehus ønsker, at kilderne går hjem med.

Jeg siger til Henrik:

»Hvad nu, hvis du giver mig nogle fingerpeg, og så tager jeg den herfra?«

Den er han med på, og vi går hver til sit. Jeg er på egen hånd nu, lidt ligesom Jean-Claude Van Damme i en intens scene i en 80’er action-film. Det er altså bare min oplevelse.

Tilbage til installeringen af pip. Det driller, men jeg tilføjer flaget --fix-missing, og så virker det.

Vi skal bruge pip til at installere Amazons kommandolinjeværktøj til skyen. Det hedder awscli og installeres sådan her:

  1. sudo pip3 install awscli --upgrade

Det tager også en hulens tid, og et par forsøg - jeg har vist ikke lige den skarpeste tænkehat på hovedet denne dag.

Ny bruger

Nu skal der oprettes en ‘Identity and Access Management’-bruger. Det havde jeg nok aldrig fundet ud af, hvis ikke Henrik havde fortalt mig om det.

Det er en speciel bruger, som benyttes i forbindelse med kommandolinje-værktøjerne. Jeg benytter Amazons webkonsol, og jeg synes dælme, man skal klikke hist og her og alle vegne. Amazon har dog en god vejledning til de 15 skridt, man skal igennem, og jeg holder tungen lige i munden.

Resultatet er to nøgler, Access Key ID og Secret Access Key, som bare er nogle lange strenge. Dem kan jeg altså ikke gengive overfor jer, kære læsere - beklager.

Nu kan jeg benytte aws-kommandoen, vi installerede før, til at konfigurere opsætningen med. Det skal kun gøres én gang.

  1. aws configure
  2. AWS Access Key ID (None): (slettet)
  3. AWS Secret Access Key (None): (slettet)
  4. Default region name (None): us-east-1
  5. Default output format (None): json

Så langt, så godt. Men der stadig et godt stykke vej til ‘hallo verden’ - så er I advaret.

Jeg skal nu oprette en ‘bucket’ i Amazons storage-system S3. Det er et sted, man kan gemme ting, lidt ligesom en mappe i et filsystem, uden undermapper. Den kode, vi skaber senere hen, skal op og ligge her.

Jeg kan ikke finde ud af at skabe en bucket med kommandolinje-værktøjet - den kommer hele tiden med dumme fejlmeddelelser, i stedet for at fortælle mig, hvad jeg skal skrive.

Men en bucket kan også oprettes via webkonsollen. Jeg navigerer frem til ‘S3’ og her er det legende nemt at skabe en bucket. Den er også gratis i 12 måneder, så det koster mig altså ikke yderligere.

Nu skal vi dæleme også installere pakke-programmet brew. Jeg synes ellers, at jeg har installeret rigeligt allerede. Men det ser sådan ud:

  1. sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
  2. test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
  3. test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
  4. test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile
  5. echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile
  6. brew --version

Jeg læste instruktionerne et eller andet sted, og kan helt ærligt ikke rigtig huske, hvad det går ud på. Men nu er jeg i hvert fald i stand til at installere programmer med brew.

Det næste vi skal installere, er værktøjet sam. Det står for Serverless Application Model, så nu nærmer vi os langt om længe sagens kerne. Det ser sådan ud:

  1. brew tap aws/tap
  2. brew install aws-sam-cli
  3. sam --version

Vi skal dog liiiiige installere ét værktøj til - men så er det også det sidste!

Det er Java-konfigurationsværktøjet Maven. Det er heldigvis nemt at installere i min Linux:

  1. sudo apt install maven
  2. mvn -version

Så er vi på vej til serverless, mine damer og herrer.

Skelet til serverless-funktion

Henrik fortæller mig på mail, hvad jeg nu skal gøre. Vi bruger kommandoen:

  1. sam init --runtime java8

– som svarer således:

  1. [+] Initializing project structure...
  2.  
  3. Project generated: ./sam-app
  4.  
  5. Steps you can take next within the project folder
  6. ===================================================
  7. [+] Install dependencies
  8. [+] Invoke Function: sam local invoke HelloWorldFunction --event event.json
  9. [+] Start API Gateway locally: sam local start-api
  10.  
  11. Read sam-app/README.md for further instructions
  12.  
  13. [+] Project initialization is now complete

Nu kan jeg navigere til mappen sam-app/HelloWorldFunction/src/main/java/helloworld, hvor jeg finder disse to kildefiler:

  1. App.java
  2. GatewayResponse.java

I App.java finder vi blandt andet disse linjer:

  1. public class App implements RequestHandler<Object, Object> {
  2.  
  3. public Object handleRequest(final Object input,
  4. final Context context) {
  5. Map<String, String> headers = new HashMap<>();
  6. headers.put("Content-Type", "application/json");
  7. headers.put("X-Custom-Header", "application/json");
  8. try {
  9. final String pageContents = this
  10. .getPageContents("https://checkip.amazonaws.com");
  11. String output = String
  12. .format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
  13. return new GatewayResponse(output, headers, 200);
  14. } catch (IOException e) {
  15. return new GatewayResponse("{}", headers, 500);
  16. }
  17. }

Vi ændrer output til

  1. String output = String.format("{ \"message\": \"hej du!\", \"location\": \"%s\" }", pageContents);

– for lige at personalisere en anelse.

Jeg navigerer nu ind i mappen sam-app. Her afvikler jeg kommandoerne

  1. sam build
  2. sam package --output-template packaged.yaml --s3-bucket taniasnyebucket
  3. sam deploy --template-file packaged.yaml --region us-east-1 \
  4. --capabilities CAPABILITY_IAM --stack-name aws-sam-getting-started

Her bliver koden compilet, pakket og udrullet.

Nu kan jeg spørge Amazon om min serverless hallo-app:

  1. aws cloudformation describe-stacks --stack-name aws-sam-getting-started --region us-east-1 --query "Stacks[].Outputs"

– der svarer med Json, og blandt andet fortæller dette:

  1. {
  2. "OutputKey": "HelloWorldApi",
  3. "OutputValue": "https://x8d598jn85.execute-api.us-east-1.amazonaws.com/Prod/hello/",
  4. "Description": "API Gateway endpoint URL for Prod stage for Hello World function"
  5. },

Her har vi funktionens endepunkt. Vi daffer ind i en browser og smider url’en i adresselinjen:

For hulen da også - så lykkedes det til sidst. Men hold dog op, hvor skulle der meget til.

Det er lidt paradoksalt, at det er så nemt at sætte en virtuel server op, mens det skal tage så lang tid at få serverless på plads. Hvis ikke Henrik Oddershede havde hjulpet mig, havde jeg måske givet op undervejs.

Nu har vi en ‘hej verden’-app på plads, og i næste artikel kigger vi på, hvorledes vi får machine learning-programmet op at køre med Henriks hjælp. Bliv på kanalen.

3 kommentarer.  Hop til debatten
Denne artikel er gratis...

...men det er dyrt at lave god journalistik. Derfor beder vi dig overveje at tegne abonnement på Version2.

Digitaliseringen buldrer derudaf, og it-folkene tegner fremtidens Danmark. Derfor er det vigtigere end nogensinde med et kvalificeret bud på, hvordan it bedst kan være med til at udvikle det danske samfund og erhvervsliv.

Og der har aldrig været mere akut brug for en kritisk vagthund, der råber op, når der tages forkerte it-beslutninger.

Den rolle har Version2 indtaget siden 2006 - og det bliver vi ved med.

Debatten
Log ind eller opret en bruger for at deltage i debatten.
settingsDebatindstillinger
3
22. oktober 2019 kl. 16:27

Det er AWS SAM som benytter CloudFormation templates. Serverless funktionen kører på Lambda med API Gateway foran. ?

2
22. oktober 2019 kl. 14:15

Godt spörgsmål - Det må väre AWS-Lambda.

https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-build.html

AWS-Lambda er lidt mere indviklet for Java fordi man 'manuelt' skal bygge sin container, for Python kan man bruge 'Zappa', som 'gör alt' - til gengäld ved man måske ikke så meget om hvad der faktisk sker 'inde bagved'.

AWS-Lambda er super-smart, I övrigt.

1
22. oktober 2019 kl. 13:33

Er det så AWS Fargate eller hvad hedder den service, du er ved at skifte til?