{"id":975,"date":"2019-10-04T16:36:33","date_gmt":"2019-10-04T14:36:33","guid":{"rendered":"https:\/\/blog.besharp.it\/autoscaling-like-a-pro-come-utilizzare-gli-auto-scaling-lifecycle-hooks-di-ec2\/"},"modified":"2021-03-17T12:53:52","modified_gmt":"2021-03-17T11:53:52","slug":"autoscaling-like-a-pro-come-utilizzare-gli-auto-scaling-lifecycle-hooks-di-ec2","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/it\/autoscaling-like-a-pro-come-utilizzare-gli-auto-scaling-lifecycle-hooks-di-ec2\/","title":{"rendered":"Autoscaling like a pro: come utilizzare gli Auto Scaling Lifecycle Hooks di EC2."},"content":{"rendered":"
Vi \u00e8 mai capitato di dover indagare le cause di un arresto inaspettato di un\u2019istanza EC2 appartenente ad un Auto Scaling group o di doverla configurare prima di portarla nello stato InService?<\/span><\/p>\n Questi sono entrambi casi in cui i Lifecycle Hooks di EC2<\/strong> possono venirci in aiuto.\u00a0<\/span><\/p>\n In questo articolo approfondiremo il loro funzionamento esaminando alcuni casi d\u2019uso particolarmente significativi.<\/span><\/p>\n Partiamo con un breve recap delle principali caratteristiche del servizio AWS EC2 Auto Scaling.<\/span><\/p>\n EC2 Auto Scaling<\/strong> \u00e8 un servizio offerto da Amazon Web Services che permette di adattare il numero delle istanze EC2 in uso per garantire il corretto funzionamento delle applicazioni in base al reale andamento del traffico.<\/strong> Le istanze sono logicamente raggruppate in Auto Scaling groups.<\/strong> Per ciascuno di questi gruppi \u00e8 possibile impostare valori di capacit\u00e0 minima, massima e desiderata.<\/strong> Ad ogni Auto Scaling group possono essere associate particolari policy di scaling.<\/strong>\u00a0 Nel caso in cui nessuna policy sia associata, invece, il comportamento di default si traduce nel mantenimento di un numero di istanze healthy che coincide con il valore desiderato, inizialmente impostato. Per poter mantenere questo valore stabile, vengono eseguiti periodicamente health check su ciascuna istanza<\/strong> in modo tale che, per ogni istanza trovata in stato unhealthy, ne venga immediatamente avviata un\u2019altra funzionante in sostituzione.<\/span><\/p>\n Oltre allo scaling manuale in cui i valori di capacit\u00e0 minima, massima e desiderata vengono impostati e aggiornati manualmente, esiste la possibilit\u00e0 di rendere lo scaling automatico.<\/strong><\/span><\/p>\n In particolare ci sono due diversi tipi di scaling automatico:<\/span><\/p>\n Per il Dynamic Scaling esistono tre tipi di Policy di scaling:<\/strong><\/span><\/p>\n Questo tipo di policy \u00e8 particolarmente utile nel caso in cui le metriche di utilizzo siano proporzionali alla capacit\u00e0 dell\u2019Autoscaling group.<\/span><\/p>\n Se un\u2019istanza appartiene ad un Autoscaling group, il suo lifecycle risulter\u00e0 differente da quello di ogni altra istanza EC2. Ecco una rappresentazione del Lifecycle di una istanza EC2 appartenente ad un Autoscaling group:<\/span><\/p>\n All\u2019avvio di una nuova istanza EC2 questa assume , in risposta ad un evento di scale-out, lo stato di \u201cPending\u201d.<\/strong> In questo stato \u00e8 possibile configurare l\u2019istanza \u2013 preferibilmente in modo automatico \u2013 e assicurarsi che superi tutti gli health check prima del suo passaggio allo stato successivo:\u00a0<\/span><\/p>\n A partire da questo stato, l\u2019EC2 potr\u00e0 passare a uno dei seguenti stati di transizione:<\/span><\/p>\n Pending, Detaching, EnteringStandby e Terminating sono tutti stati considerati di transizione<\/strong> e\u00a0 anticipano rispettivamente gli stati stabili di InService, Detached, StandBy e Terminated.<\/strong><\/span><\/p>\n Gli stati di Pending e Terminating possono entrambi essere momentaneamente sospesi grazie all\u2019utilizzo degli EC2 Auto Scaling Lifecycle Hooks. Con essi, infatti, \u00e8 possibile definire logiche custom da applicare ai processi di avvio e terminazione delle istanze.<\/span><\/p>\n Il Lifecycle Hook dello stato Pending prende il nome di EC2_INSTANCE_LAUNCHING<\/strong> e si occupa di gestire gli ulteriori stati Pending:Wait<\/strong> e Pending:Proceed.<\/strong><\/span><\/p>\n Allo stesso modo, Il Lifecycle Hook dello stato Terminating chiamato EC2_INSTANCE_TERMINATING<\/strong> si occuper\u00e0 di gestire gli stati Terminating:Wait<\/strong> e Terminating:Proceed.<\/strong><\/span><\/p>\n <\/p>\n In entrambi i casi, le istanze EC2 resteranno in Wait fino allo scadere del timeout a meno che non si decida di concludere in anticipo il Lifecycle Hook procedendo manualmente allo stato successivo.<\/span><\/p>\n Il risultato di un Lifecycle Hook potr\u00e0 essere CONTINUE<\/strong> o ABANDON.\u00a0<\/strong><\/span><\/p>\n Per quanto riguarda il lifecycle di tipo EC2_INSTANCE_LAUNCHING, il risultato ottenuto decreter\u00e0 il passaggio dell\u2019istanza dallo stato InService o Terminating.<\/span><\/p>\n Nel caso di EC2_INSTANCE_TERMINATING, invece, il risultato non avr\u00e0 conseguenze sul lifecycle dell\u2019istanza EC2; l\u2019istanza verr\u00e0 in ogni caso terminata.<\/span><\/p>\n Dipende dallo scenario in cui ci troviamo.<\/span><\/p>\n Andiamo nel dettaglio e vediamo insieme alcuni dei casi pi\u00f9 comuni in cui, mantenere un\u2019istanza nello stato Pending o Terminating pu\u00f2 tornare utile.\u00a0<\/span><\/p>\n Come spiegato in precedenza, \u00e8 possibile pausare un lifecycle di un\u2019istanza EC2 in Pending state prima che essa passi in stato InService.\u00a0<\/span><\/p>\n Mantenere lo stato Pending di un\u2019istanza<\/strong> risulta particolarmente importante quando il tempo di setup si protrae pi\u00f9 del previsto. In questo modo \u00e8 possibile impedire all\u2019istanza di ricevere richieste quando ancora non \u00e8 in grado di gestirle.<\/span><\/p>\n Ad esempio, il servizio CodeDeploy si basa sul lifecycle hook EC2_INSTANCE_LAUNCHING <\/span>per gestire il deploy di applicazioni su istanze EC2 che appartengono a un Autoscaling group. Il tutto \u00e8 perfettamente descritto <\/span>in questo articolo.<\/span><\/p>\n \u00c8 un tipo di comportamento che funziona anche su soluzioni custom attraverso, ad esempio, script resi disponibili negli User Data di un\u2019istanza EC2.<\/span><\/p>\n A: \u201cAiuto! La mia istanza EC2 \u00e8 down!\u201d<\/span><\/p>\n B: \u201cOk, vediamo qual \u00e8 la causa dell\u2019arresto\u201d<\/span><\/p>\n A: \u201cehm.. tutti i log erano sull\u2019istanza. Non abbiamo alcuna copia.\u201d<\/span><\/p>\n Una pratica utile e piuttosto comune a tal proposito consiste nell\u2019utilizzo di un agent che esporti periodicamente i log in una destinazione diversa dall\u2019istanza EC2. Questo \u00e8 il modo migliore per evitare di trovarsi in situazioni simili. Ma non basta!\u00a0<\/span><\/p>\n …<\/span><\/p>\n B: \u201cCerto! L\u2019agent per l\u2019esportazione dei log era installato correttamente!\u201d<\/span><\/p>\n A: \u201cProbabilmente \u00e8 andato in crash.\u201d<\/span><\/p>\n \u00c8 qui che il lifecycle hook EC2_INSTANCE_TERMINATING corre in nostro aiuto: esso permette di esportare i log in una nuova destinazione,<\/strong> ad esempio un bucket S3.<\/span><\/p>\n A volte risulta utile loggarsi sull\u2019istanza EC2 per capirlo. Combinando insieme EC2 Auto Scaling Lifecycle Hooks, un Topic SNS e una Lambda Function \u00e8 possibile setuppare un sistema di notifiche che ci avvisi in caso di istanza unhealthy terminata.<\/strong> In questo tipo di soluzione, la Lambda Function avr\u00e0 il compito di esaminare il motivo del passaggio di un\u2019istanza allo stato di Terminating distinguendo tra istanze healthy, ma non pi\u00f9 necessarie e istanze terminate in quanto <\/span>unhealthy<\/span><\/i>.<\/span><\/p>\n Vediamo insieme come setuppare un EC2 Auto Scaling Lifecycle Hook<\/strong> che consente di completare la configurazione dell\u2019istanza prima che essa passi allo stato<\/span> InService.<\/span><\/i><\/p>\n La configurazione consiste in uno User Data script definito nel Launch Template dell\u2019Auto Scaling group.<\/span><\/p>\n Lo User Data installer\u00e0 un Apache Web Server su un\u2019istanza Ubuntu 18.04.<\/strong> Una volta completata l\u2019installazione, lo script concluder\u00e0 la lifecycle action specificando CONTINUE come risultato, autorizzando l\u2019Auto Scaling group a portare l\u2019istanza in stato InService. Nel caso in cui qualcosa vada storto, il risultato fornito al comando complete-lifecycle-action sar\u00e0 ABANDON. L\u2019istanza sar\u00e0 quindi terminata dall\u2019Auto Scaling group.<\/span><\/p>\n In questo processo occorre porre particolare attenzione sui parametri –lifecycle-hook-name<\/strong> e –auto-scaling-group-name<\/strong> utilizzati nello script di configurazione; \u00e8 necessario che essi corrispondano rispettivamente al nome dell\u2019EC2 Auto Scaling Lifecycle Hook<\/strong> e al nome dell\u2019EC2 Auto Scaling group<\/strong> che andremo a creare.<\/span><\/p>\n Prima di tutto, creiamo il Launch Template<\/strong> specificando come sorgente AMI ubuntu\/images\/hvm-ssd\/ubuntu-bionic-18.04-amd64-server-20190722.1<\/strong> e come User Data lo script che abbiamo preparato durante lo step precedente.<\/span><\/p>\n A questo punto potremo creare un nuovo Auto Scaling group basato sul Launch template appena creato. Durante la configurazione dell\u2019Auto Scaling group, specifichiamo una o pi\u00f9 subnet<\/strong> che consentano all\u2019istanza di installare Apache Web Server.<\/span><\/p>\n Prima di procedere, assicuriamoci che i valori di min<\/strong> e di DesiredCapacity<\/strong> iniziali siano impostati su zero<\/strong>. Il parametro di max<\/strong> iniziale potr\u00e0 essere settato a 1.<\/strong><\/span><\/p>\n Dalla tab del Lifecycle Hooks dell\u2019Auto Scaling group clicchiamo su Create Lifecycle Hook.\u00a0<\/strong><\/span><\/p>\n Configuriamo ora il Lifecycle Hook come mostrato:<\/span><\/p>\n Per testare il comportamento del lifecycle hook, possiamo incrementare il valore del parametro DesiredCapacity di uno.<\/strong> Cos\u00ec facendo, noteremo che una nuova istanza verr\u00e0 aggiunta all\u2019Auto Scaling group.<\/strong> Dalla tab Auto Scaling group dell\u2019istanza, dovremmo quindi notare nella colonna <\/span>Lifecycle<\/span><\/i> dell\u2019istanza appena aggiunta lo stato di Pending:Wait. Questo significa che il Lifecycle dell\u2019istanza rimarr\u00e0 in stato Pending fino a che il comando complete-lifecycle-action non verr\u00e0 invocato dallo script User Data.<\/span><\/p>\n Quando lo stato cambier\u00e0 in InService, potremo accedere via SSH alla nuova istanza EC2 per controllare lo stato del Web Server Apache attraverso il comando<\/span><\/p>\n sudo systemctl status apache2<\/span><\/p>\n Se il Web Server Apache \u00e8 stato configurato correttamente, otterremo una risposta simile alla seguente:<\/span><\/p>\n \u00a0\u00a0\u00a0Loaded: loaded (\/lib\/systemd\/system\/apache2.service; enabled; vendor preset: enabled)<\/span><\/p>\n \u00a0\u00a0Drop-In: \/lib\/systemd\/system\/apache2.service.d<\/span><\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u2514\u2500apache2-systemd.conf<\/span><\/p>\n \u00a0\u00a0\u00a0Active: active (running) since Wed 2019-10-02 12:56:20 UTC; 3min 30s ago<\/span><\/p>\n \u00a0Main PID: 3334 (apache2)<\/span><\/p>\n \u00a0\u00a0\u00a0\u00a0Tasks: 55 (limit: 1125)<\/span><\/p>\n \u00a0\u00a0\u00a0CGroup: \/system.slice\/apache2.service<\/span><\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u251c\u25003334 \/usr\/sbin\/apache2 -k start<\/span><\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u251c\u25003336 \/usr\/sbin\/apache2 -k start<\/span><\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u2514\u25003337 \/usr\/sbin\/apache2 -k start<\/span><\/p>\n Solo dopo aver superato la fase di\u00a0 configurazione, lo stato dell\u2019istanza cambier\u00e0 da Pending a InService.<\/span><\/p>\n Soddisfatti?<\/span><\/p>\n In questo articolo vi abbiamo mostrato il funzionamento dei Lifecycle Hooks descrivendo brevemente come essi possono tornarci utili durante lo sviluppo quotidiano.\u00a0<\/span><\/p>\n Vi \u00e8 capitato di utilizzarli in altre configurazioni? Raccontatecelo nei commenti!<\/span><\/p>\n \u00a0<\/span>Arrivederci al prossimo articolo!<\/span><\/p>\n","protected":false},"excerpt":{"rendered":" Vi \u00e8 mai capitato di dover indagare le cause di un arresto inaspettato di un\u2019istanza EC2 appartenente ad un Auto […]<\/p>\n","protected":false},"author":7,"featured_media":979,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[481],"tags":[315,317,319],"class_list":["post-975","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-architecting","tag-amazon-ec2","tag-amazon-ec2-auto-scaling","tag-lifecycle-hooks"],"yoast_head":"\n\n
\n
<\/p>\n
<\/h2>\n
Cosa succede quando un evento di scale-out avvia una nuova istanza EC2?<\/span><\/h2>\n
Pending State<\/span><\/h3>\n
InService<\/span><\/h3>\n
\n
Quando \u00e8 utile mettere in pausa gli stati Pending e Terminating?<\/span><\/h2>\n
Pending state hook<\/span><\/h2>\n
Instance configuration<\/span><\/h3>\n
Terminating state hook<\/span><\/h2>\n
Log files download<\/span><\/h3>\n
Cosa \u00e8 andato storto?<\/span><\/h3>\n
Hands-on!\u00a0<\/span><\/h2>\n
#!\/bin\/bash\r\napt update && \\\r\napt install snapd && \\\r\nsnap install aws-cli --classic && \\\r\napt install -y apache2 && \\\r\nufw allow 'Apache' && \\\r\nINSTANCE_ID=\"`wget -q -O - http:\/\/instance-data\/latest\/meta-data\/instance-id`\" && \\\r\n\/snap\/bin\/aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE --instance-id $INSTANCE_ID --lifecycle-hook-name test-hook --auto-scaling-group-name test-asg --region eu-west-1 || \\\r\n\/snap\/bin\/aws autoscaling complete-lifecycle-action --lifecycle-action-result ABANDON --instance-id $INSTANCE_ID --lifecycle-hook-name test-hook --auto-scaling-group-name test-asg --region eu-west-1\r\n<\/pre>\n
<\/p>\n
\n