AWS - autoskalowanie EC208.VII.2017

Spis treści

  1. Przygotowanie komponentów
  2. Konfiguracja startowa do autoskalowania
  3. Load balancer - przygotowanie
  4. Przypięcie load balancera do autoskalera
  5. Przykład - automatyczne zwiększanie ilości instancji

Przygotowanie komponentów

Należy przygotować dwie podsieci w różnych Availability Zone (AZ) w obrębie jednej sieci wirtualnej - w tym przypadku wygląda to tak:

Dodatkowo pomocny będzie poniższy skrypt (modyfikacja już kiedyż użytego w AWS CloudFront CDN), który AWS użyje w procesie tworzenia nowej instancji maszyny tj. zostanie uruchomiony raz przy pierwszym starcie. Jego zadaniem przede wszystkim jest:

  1. Instalacja NodeJs na maszynie
  2. Uruchomienie mikro serwera WWW

UWAGA skrypty startowe muszą zaczynać się od ciągu #! i zawsze są wykonywane w kontekście użytkownika root. Gdyby coś poszło nie tak to logi startu są w pliku /var/log/cloud-init-output.log

#!/bin/bash

apt-get install nodejs -y
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1337
cd /home/ubuntu
echo "hello autoscaled!" > auto.txt

cat >run_node.sh <<EOL
#!/bin/bash

nodejs /home/ubuntu/server.js 1337 &
EOL

cat >server.js <<EOL
var os_hostname = require('os').hostname();
var http = require('http');
var app = http.createServer(function(req,res) {
    if ('/favicon.ico' === req.url) {
        res.statusCode = 404;
        res.end();
        return;
    }

    if ('/' === req.url || '/initgo' === req.url) {
        res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    }

    var now = (new Date()).toISOString();
    console.log(now, '>> url:', req.url);

    res.statusCode = 200;
    res.end(os_hostname + ': Teraz mamy: ' + now);
});
app.listen(process.argv[2] || 1337);
EOL

chown ubuntu:ubuntu run_node.sh
chown ubuntu:ubuntu server.js

sudo -u ubuntu sh /home/ubuntu/run_node.sh

Dzięki niemu każdy z serwerów będzie zwracał dane jak niżej ale poprzedzone nazwą maszyny na której działa.

ip-10-0-1-52: Teraz mamy: 2017-07-08T15:27:54.864Z

Konfiguracja startowa do autoskalowania

W tym momencie w obrębie grupy autoskalowania powinna być uruchomiona jedna instancja EC2 najprawdopodobniej w strefie eu-west-1b.

Dla testu można zepsuć instancję na dwa poniższe sposoby i zobaczyć, że autoskaler stworzy nową instancję, i w dodatku w innym AZ.

Load balancer - przygotowanie

Teraz należy dodać klasyczny wg. AWS load balancer, który będzie dzielił równomiernie ruch pomiędzy wszystkie maszyny w różnych AZ.

Po stworzeniu instancji load balancera w zakładce "Description" dostaniemy informację o jego adresie, który należy później umieścić w rekordzie CNAME swojej domeny: VPC1-LB-544907824.eu-west-1.elb.amazonaws.com (A Record).

Przypięcie load balancera do autoskalera

Przechodzimy do "Auto Scaling Groups: VPC1_AUTO_GRP1", zakładka "Details", przycisk "Edit" i ustawiamy następujące opcje:

Po zapisaniu autoskaler stworzy 2 instancje EC2 na 3 możliwe maksymalnie. W ustawieniach load balancera VPC1-LB, w zakładce "Instances", po czasie "Status" na instancjach zmieni się na "InService".

Po wejściu na stronę: http://vpc1-lb-544907824.eu-west-1.elb.amazonaws.com/ dostajemy na zmianę (patrząc na nazwy hostów):

ip-10-0-1-52: Teraz mamy: 2017-07-08T16:06:13.011Z
ip-10-0-2-55: Teraz mamy: 2017-07-08T16:06:07.102Z

Zatrzymanie usługi na jednym z serwerów

ubuntu@ip-10-0-1-52:~$ ps aux | grep node
ubuntu    1954  0.0  2.4 944636 24528 ?        Sl   15:27   0:00 nodejs /home/ubuntu/server.js 1337
ubuntu    2071  0.0  0.0  14992   984 pts/0    S+   16:07   0:00 grep --color=auto node
ubuntu@ip-10-0-1-52:~$ kill 1954

Powoduje, że w odpowiedziach pojawia się już tylko poniższa treść a instancja na load balancerze dostaje Status: OutOfService (Instance has failed at least the UnhealthyThreshold number of health checks consecutively.)

ip-10-0-2-55: Teraz mamy: 2017-07-08T16:08:38.678Z

Mimo ponownego uruchomienia usługi WWW (serwer ubuntu działał cały czas) load balancer nie przekierowuje na niego ruchu, pomimo poprawnych odpowiedzi o statusie usługi.

ubuntu@ip-10-0-1-52:~$ nodejs /home/ubuntu/server.js 1337
2017-07-08T16:10:23.131Z >> url: /health1
2017-07-08T16:10:28.313Z >> url: /health1
2017-07-08T16:10:53.125Z >> url: /health1
2017-07-08T16:10:58.312Z >> url: /health1
2017-07-08T16:11:23.125Z >> url: /health1
2017-07-08T16:11:28.313Z >> url: /health1
2017-07-08T16:11:53.127Z >> url: /health1
2017-07-08T16:11:58.314Z >> url: /health1
2017-07-08T16:12:23.124Z >> url: /health1
2017-07-08T16:12:28.315Z >> url: /health1
2017-07-08T16:12:53.124Z >> url: /health1
2017-07-08T16:12:58.315Z >> url: /health1
2017-07-08T16:13:23.124Z >> url: /health1
2017-07-08T16:13:28.316Z >> url: /health1
2017-07-08T16:13:53.128Z >> url: /health1
2017-07-08T16:13:58.312Z >> url: /health1
2017-07-08T16:14:23.125Z >> url: /health1
2017-07-08T16:14:28.310Z >> url: /health1
2017-07-08T16:14:53.124Z >> url: /health1
2017-07-08T16:14:58.308Z >> url: /health1
2017-07-08T16:15:00.583Z >> url: /
2017-07-08T16:15:01.097Z >> url: /
2017-07-08T16:15:01.530Z >> url: /
2017-07-08T16:15:01.848Z >> url: /
2017-07-08T16:15:04.642Z >> url: /
2017-07-08T16:15:10.247Z >> url: /lolz
2017-07-08T16:15:23.124Z >> url: /health1
2017-07-08T16:15:28.307Z >> url: /health1

Dopiero po 10 minutach pojawia się jedno z pierwszych przekierowań na ponownie przywróconą do życia usługę WWW.

ip-10-0-1-52: Teraz mamy: 2017-07-08T16:15:10.247Z

To samo widać w wykresie monitoringu dostępności poprawnych instancji.

Przykład - automatyczne zwiększanie ilości instancji

Aby automatycznie zwiększała się liczba instancji w autoskalerze na podstawie danych z load balancera postępujemy następująco.

  1. W load balancerze VPC1-LB ustawiamy nowy alarm dot. istnienia nieprzydatnych hostów
    • Whenever: Average of Unhealthy Hosts
    • Is: >= 1
    • For at least: 1 consecutive period(s) of 1 Minute
    • Name of alarm: LB-ALARM-Unhealthy-Hosts
  2. W grupie autoskalowania VPC1_AUTO_GRP1, zakładka "Scaling Policies" klikamy "Add policy"
    • Klikamy link Create a simple scaling policy
    • Name: LB_SCALE_UP
    • Execute policy when: LB-ALARM-Unhealthy-Hosts
    • Take the action: Add 1 instances
    • Instances need: 30 seconds to warm up after each step

Teraz, po zatrzymaniu usługi WWW na jednym z serwerów po wystąpieniu alarmu (trochę ponad minutę) zostanie dołożona nowa instancja do puli autoskalera co ładnie widać w logu