Script får V2's skygge-server på benene igen efter nedbrud

Illustration: Version2
Et script gør det muligt at gendanne Version2's skygge-server i skyen, hvis uheldet skulle være ude.

En sky-server er en nem og billig måde at sætte en lille tjeneste i luften, især for os, der gør det i skygge-it og hjemmestrikkede løsninger.

Men ligesom alle andre slags computere kan serveren stå af. Vores server-instans hører hjemme hos Amazon, og hvis disk eller hukommelse går i stykker i datacenteret i Virginia på USA’s østkyst, er det hele væk.

Amazon stiller en ny instans til rådighed, hvis uheldet er ude, men den nye instans er ganske tom til at starte med, og jeg får også et nyt IP-nummer i den anledning.

Det tager tid at sætte det hele mekanikken op igen med håndarbejde. Og den tid har jeg måske ikke, den dag, hvor alt bare går galt i skyen.

Løsningen er at skrive et script, som kan udrulle systemet i en ruf. Webtjenesten gemmer ikke noget på disk, så der er ingen behov for backup.

Hemmelige passwords

I sidste episode af denne fortælling løste vi problemet med Let’s Encrypt’s kortlivede SSL-certifikater, der skal fornyes hver tredje måned. Og det gik helt fint.

Vores problem består denne gang i at udrulle hele baduljen på frisk, blank sky. Kronologisk ser det således ud:

Vi har scripts liggende lokalt. Vi afvikler et lokal script, der beder os om passwordet til root i skyen - altså sky-serverens administrator-password. Det script kopierer en række scripts over på sky-serveren, samt webtjeneste-programmet.

Dernæst afvikler vi - fra den lokale terminal - to scripts, der sætter det hele op på sky-serveren. Det første skal køre som root - administrator - på sky-serveren. Det andet skal kører som den almindelige bruger, der hedder ‘ec2-user.’

Det første, lokale script, ser ud som herunder. Vores linjer er lidt lange, og da Version2-cms’ets kodeformatering ikke har en rulleskakt - det er skrevet i backloggen - har vi knækket linjerne med backslash \, som i bash betyder: Kommandoen fortsætter på næste linje.

# Udruller sky-app. Afvikles lokalt.
# Indlæs password til skyen.
echo -n Password:
read -s PASSWORD
HOST=ec2-user@ec2-18-223-114-109.us-east-2.compute.amazonaws.com
WEBTJ_LOKAL=/mnt/c/Users/tan/Documents/webtjeneste
WEBTJ_FJERN=/home/ec2-user/webtjeneste
# Kopier udrul-script 1 og 2 til skyen.
scp -i TaniasAWSNoegler.pem udrul-sky-1.sh $HOST:/home/ec2-user
scp -i TaniasAWSNoegler.pem udrul-sky-2.sh $HOST:/home/ec2-user
# Kopier webtjeneste til skyen.
scp -i TaniasAWSNoegler.pem -r $WEBTJ_LOKAL $HOST:$WEBTJ_FJERN
# Kopier script til certifikat-fornyelse til sky.
scp -i TaniasAWSNoegler.pem cert-forny.sh $HOST:/home/ec2-user
# Kopier script til start af webtjeneste til sky.
scp -i TaniasAWSNoegler.pem genstart-tjeneste.sh \
 $HOST:/home/ec2-user
# Gør scripts eksekverbare.
ssh -i TaniasAWSNoegler.pem \
 ec2-user@ec2-18-223-114-109.us-east-2.compute.amazonaws.com 'echo \
 $PASSWORD | sudo chmod +x udrul-sky-1.sh'
ssh -i TaniasAWSNoegler.pem \
 ec2-user@ec2-18-223-114-109.us-east-2.compute.amazonaws.com 'echo \
 $PASSWORD | sudo chmod +x udrul-sky-2.sh'
# Kør udrul-sky-1.sh i skyen som root.
ssh -i TaniasAWSNoegler.pem \
 ec2-user@ec2-18-223-114-109.us-east-2.compute.amazonaws.com 'echo \
 $PASSWORD | sudo -S /home/ec2-user/udrul-sky-1.sh'
# Kør udrul-sky-2.sh i skyen som alm. bruger (ec2-user).
ssh -i TaniasAWSNoegler.pem \
 ec2-user@ec2-18-223-114-109.us-east-2.compute.amazonaws.com \
 '/home/ec2-user/udrul-sky-2.sh'

Vi skal bruge root-passwordet til skyen, som jo giver administrator-adgang, og vi vil ikke have, at det ryger ned i bash’ history, der gemmer alle kommandoer.

Linjen read -s PASSWORD gør, at passwordet indlæses fra terminalen uden at skrive noget, ligesom når man anvender sudo-kommandoen. Det gemmes i variablen PASSWORD.

Vi starter med at kopiere vores to udrulnings-scripts over på sky-serveren med scp, der tager vores Amazon-nøgler som argument.

Så kopierer vi webtjeneste-programmet over, samt de to scripts, der henholdsvis fornyer certifikater og starter eller genstarter webtjenesten.

Nu skal vi gøre vores scripts eksekverbare på sky-serveren, og her skal vi bruge vores PASSWORD-variabel fra tidligere. Det er denne linje, det drejer sig om:

# Gør scripts eksekverbart.
ssh -i TaniasAWSNoegler.pem $HOST 'echo $PASSWORD | sudo chmod +x \
 udrul-sky-1.sh'

HOST-variablen satte vi øverst i scriptet, og nu udfører vi denne kommando på sky-serveren, som står inde mellem de to anførselstegn:

echo $PASSWORD | sudo chmod +x udrul-sky-1.sh

Sudo-kommandoen vil efterspørge et password, og den klarer vi ved at skrive vores password med echo, og ‘pipe’ det over i sudo-kommandoen. Det gør det samme, som hvis jeg var logget ind på sky-serveren og skrev kommandoen i hånden. Passwordet bliver på denne måde heller ikke skrevet i en history-fil, hverken på sky eller lokalt, og når scriptet er afviklet, er variablen væk.

Spørgelystne kommandoer tier stille

Vi gør det samme med de to udrulnings-scripts udrul-sky-1 og 2, og etteren afvikler vi på skyen som root, og toeren som skyens almindelige bruger ec2-user.

# Køres som root på sky-serveren.
# Installer Java 11.
curl -L \
 https://d3pxv6yz143wms.cloudfront.net/11.0.4.11.1/java-11-amazon-corretto-devel-11.0.4.11-1.x86_64.rpm  \ 
 -o /tmp/java-11-amazon-corretto-devel-11.0.4.11-1.x86_64.rpm
yum localinstall \
 /tmp/java-11-amazon-corretto-devel-11.0.4.11-1.x86_64.rpm -y
# Installer Let’s Encrypt certbot-auto.
wget https://dl.eff.org/certbot-auto
mv certbot-auto /usr/local/bin/certbot-auto
chown root /usr/local/bin/certbot-auto
chmod 0755 /usr/local/bin/certbot-auto
# Skab certifikater.
/usr/local/bin/certbot-auto certonly --standalone --no-bootstrap \
 --preferred-challenges http -d v2emneord.ddnsfree.com \
 --non-interactive --agree-tos -m tan@ing.dk
# Opsæt et cronjob som root, der fornyer certifikater hver
# søndag kl. 00.00.
echo "0 0 * * 0 /home/ec2-user/cert-forny.sh >> \
 /home/ec2-user/forny.log 2>&1" > cronfil
crontab cronfil
rm cronfil
# Lav swapspace
dd if=/dev/zero of=/swapspace bs=1M count=2000
chmod 600 /swapspace
mkswap /swapspace
swapon /swapspace
# Gør scripts eksekverbare.
chmod +x /home/ec2-user/genstart-tjeneste.sh
chmod +x /home/ec2-user/cert-forny.sh

Først installerer vi Java, og her benytter vi Amazons udgave af Java 11. Dernæst installerer vi Let’s Encrypts certbot-program, der skaber og fornyer SSL-certifikater. Hernæst opsætter vi et cronjob, der fornyer certifikaterne. Så skaber vi swapspace, da vores webtjeneste er lidt underforsynet med hukommelse, og til sidst gør vi de to scripts, der genstarter tjenesten og fornyer certifikater, eksekverbare.

Alt i alt er det blot det samme, som vi gjorde i en tidligere artikel, men hvor nogle af kommandoerne er i udgaver, der ikke stiller spørgsmål undervejs, som vi også så det i sidste episode.

Når udrul-sky-1 er afviklet, er der kun en lille opgave tilbage. Det er at opsætte en cronjob, der genstarter tjenesten, efter at certifikatet er fornyet. Til allersidst starter vi tjenesten med scriptet genstart-tjeneste.sh. Det lille script, udrul-sky-2, ser sådan ud:

# Køres som alm. bruger (ec2-user). Opsætter cronjob, der 
# genstarter tjenesten efter certifikat-fornyelse, og starter 
#  tjenesten.
echo "15 0 * * 0 /home/ec2-user/genstart-tjeneste.sh >> \
 /home/ec2-user/genstart.log 2>&1" > cronfil
crontab cronfil
rm cronfil
/home/ec2-user/genstart-tjeneste.sh > genstart.log

Så er vi parat til den dag, hvor serveren brænder sammen eller ondskabsfulde typer hacker systemet.

Alt er godt - sådan da. For jeg vil også gerne flytte Version2’s job-robot over på serveren. Den moderne og gnidningsfri måde at gøre det på er med containere. Det kigger vi nærmere på i løbet af efteråret, så bliv på kanalen.

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Følg forløbet
Kommentarer (6)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Klavs Klavsen

Kort opsummering:

ansible er "avanceret scripting".. det er bygget til at være modulært - så man kan genbruge komponenter og "deles om opgaven " - så man får langt mere robust automatisering.. https://www.ansible.com/overview/how-ansible-works

Ovenstående scripting er hvad man gjorde "for mange mange år siden" - idag bør man benytte det man kalder system configuration værktøjer.. Puppet, Ansible, Terraform etc.. - netop fordi man så kan samarbejde om udfordringerne vha. moduler og dermed øge hastigheden og kvaliteten samtidigt.

Disse værktøjer bruges til VMs og fysiske maskiner.

Docker er bygget til at man bygger et image én gang (vha. en Dockerfile) - og så kan man føde med med en sti (volume) der mountes ind i imaget når servicen startes og man kan give den environment variable som koden inden i docker imaget kan bruge til at ændre hvordan den kører. Så har man altså alt det man skal bruge i en "statisk skal" - som derfor kan køre med f.ex. "Ubuntu-18.04 versioner af softwaren" - uanset hvilken VM eller fysisk server det kører på.

Docker er hvad man bruger i Kubernetes miljøer, hvor man så kan kombinere flere docker images (f.ex. nginx + phpfpm docker images) til at køre ens kode (hvor kubernetes sørger for at skalere op/ned og flytte rundt i tilfælde af servere der dør).

  • 1
  • 0
Sune Marcher

Jeg har skrevet det til tidligere indlæg om dette emne, men here goes again: brug en smartere webserver :-)

Caddy har super simpel konfigurationsfil, håndterer LetsEncrypt automatisk, og har alle de features du har behov for. Sæt den ind som en reverse proxy foran din Java applikation, og så slipper du for alt bøvlet med cronjob, Java keystore og så videre.

Hvis du vil lege med Docker til applikationen, kunne det være værd at kigge på Traefik – nok lidt overkill til emneords servicen, men det er et interessant projekt.

Og så i øvrigt +1 til forslagene om at du kigger på Puppet, Ansible (eller Chef eller...) til automatisering fremfor håndrullede scripts.

  • 1
  • 0
Bo AA

Udover alternativerne som er nævnt i andre kommentarer (Puppet, Ansible, osv.), kunne det også gøres med AWS services såsom CloudFormation. Dog er alle disse måske en anelse komplekse, hvis man ikke er erfaren udvikler, og bare skal have noget i luften ASAP.

Et lettere alternativ vil være EC2 user data scripts (hvis altså det er ligemeget at have en cross-cloud løsning):

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html

Ikke den bedste løsning, men den er til at forholde sig til, hvis man skal have noget kørende til små hobby projekter eller lignende. 🙂

  • 0
  • 0
Log ind eller Opret konto for at kommentere
IT Company Rank
maximize minimize