AWS - autoskalowanie EC208.VII.2017
Spis treści
- Przygotowanie komponentów
- Konfiguracja startowa do autoskalowania
- Load balancer - przygotowanie
- Przypięcie load balancera do autoskalera
- 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:
- VPC1_SUBb (subnet-f19d28b8, eu-west-1b) adresacja 10.0.1.0/24
- VPC1_SUBc (subnet-037c9458, eu-west-1c) adresacja 10.0.2.0/24
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:
- Instalacja NodeJs na maszynie
- 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
- Auto scaling / Auto scaling groups
-
Create Auto Scaling group
-
Create Launch Configuration
- 1. Choose AMI: Ubuntu Server
- 2. Choose Instance Type: t2.micro
-
3. Configure details
- Name: VPC1_AUTO_CFG_v1
- Advanced Details / User data: skrypt z poprzedniej sekcji
- Advanced Details / IP Address Type: Assign a public IP address to every instance
- Pozostałe ustawienia wedle życzenia.
-
Create Auto Scaling group
-
1. Configure Auto Scaling group details
- Launch Configuration: VPC1_AUTO_CFG_v1
- Group name: VPC1_AUTO_GRP1
- Group size: Start with 1 instances
- Network: VPC1
- Subnet: VPC1_SUBb (subnet-f19d28b8, eu-west-1b), VPC1_SUBc (subnet-037c9458, eu-west-1c)
- 2. Configure scaling policies: Keep this group at its initial size
- 4. Configure Tags: Dobrze jest dodać tag np. "Group: AUTOGR" bo wszystkie nowe instancje będą go również dostawać
-
5. Review
- Group name: VPC1_AUTO_GRP1
- Group size: 1
- Minimum Group Size: 1
- Maximum Group Size: 1
- Subnet(s): subnet-f19d28b8,subnet-037c9458
- Health Check Grace Period: 300
- Detailed Monitoring: Yes
- Instance Protection: None
-
1. Configure Auto Scaling group details
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.
- klikamy w link z jej "Instance ID" i z opcji "Terminate"
- logujemy się na maszynę jako root i wykonujemy "shutdown -h now"
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.
- Load balancing / Load balancers
-
Create Load Balancer
- Load balancer type: Classic Load Balancer
-
1. Define Load Balancer
- Load Balancer name: VPC1-LB
- Create LB Inside: VPC1
- Select Subnets: eu-west-1b, eu-west-1c
- 2. Assign Security Groups: Select an existing security group
-
4. Configure Health Check
- Ping Path: /health1
- Response Timeout: 5 seconds
- Interval: 30 seconds
- Unhealthy threshold: 2 (ile sprawdzeń)
- Healthy threshold: 10 (ile sprawdzeń)
- 5. Add EC2 Instances: Nie zaznaczamy żadnej instancji
-
6. Add Tags
- Group: VPC1_LB_TAG
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:
- Load Balancers: VPC1-LB
- Desired: 2
- Min: 1
- Max: 3
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.
-
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
-
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