{"id":3741,"date":"2021-10-29T13:59:00","date_gmt":"2021-10-29T11:59:00","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=3741"},"modified":"2021-10-28T12:47:02","modified_gmt":"2021-10-28T10:47:02","slug":"installare-plug-in-custom-su-rds-con-le-custom-resources-di-cloudformation","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/it\/installare-plug-in-custom-su-rds-con-le-custom-resources-di-cloudformation\/","title":{"rendered":"Installare plug-in custom su RDS con le Custom Resources di CloudFormation"},"content":{"rendered":"\n
La gestione e l’amministrazione dei database<\/strong> sono sempre stati compiti molto delicati sia per server on premise, sia sul cloud. Lo sforzo richiesto per configurare e mantenere un database \u00e8 molto alto: dalla configurazione della rete, alla restrizione dei permessi per i vari utenti, gruppi e ruoli. Backup e aggiornamenti, inoltre, richiedono anch\u2019essi tempo. C\u2019\u00e8 anche da considerare il fatto che le varie configurazioni di un database possono cambiare nel tempo<\/strong> e richiedere quindi revisioni e modifiche, anche sostanziali. <\/p>\n\n\n\n Sfruttare i database managed<\/em><\/strong> diminuisce considerevolmente lo sforzo di gestione e amministrazione aggiungendo anche caratteristiche fondamentali come scalabilit\u00e0<\/strong>, alta disponibilit\u00e0<\/strong>, fault-tolerance<\/strong> e sicurezza<\/strong>.<\/p>\n\n\n\n Ma non basta: in molti casi pu\u00f2 sopraggiungere per un amministratore di databases la necessit\u00e0 di installare uno o pi\u00f9 plug-in<\/strong> (o estensioni) per incrementare le potenzialit\u00e0 del database o aggiungere funzionalit\u00e0. Alcuni esempi relativi al mondo PostgreSQL, possono essere l\u2019installazione di PostGis per query che includono informazioni geografiche, o PGCrypto per avere funzionalit\u00e0 crittografiche come la generazione del salt o l\u2019hashing di stringhe. Queste sono operazioni manuali e ricorrenti che richiedono tempo e attenzione gi\u00e0 per un singolo database. Oggi, per\u00f2, anche le aziende pi\u00f9 piccole necessitano di pi\u00f9 database, a seconda del numero di servizi e\/o applicazioni che offrono. Ripetere le stesse azioni per configurare correttamente molti databases \u00e8 un’operazione time-consuming e rischiosa: la ripetizione manuale<\/strong> delle stesse configurazioni ha un’alta probabilit\u00e0 di incappare in errori<\/strong>. <\/p>\n\n\n\n Per queste ragioni, la nuova sfida \u00e8 trovare un modo per schierare molteplici database con un dato set di configurazioni, in modo automatico<\/strong>. In tutto questo, l\u2019Infrastructure as Code (IaC)<\/strong> ci viene in aiuto: strumenti come Terraform o Pulumi, ad esempio, possono essere usati per automatizzare la creazione di svariate risorse in ambienti diversi, sia in locale, sia sui Cloud providers supportati, il tutto descrivendo l\u2019infrastruttura desiderata tramite codice. Solitamente, i cloud providers offrono le loro soluzioni proprietarie per lo IaC. La soluzione di AWS \u00e8 AWS CloudFormation<\/strong>.<\/p>\n\n\n\n Utilizzando i servizi cloud combinati con templates IaC, possiamo costruire una soluzione riutilizzabile che, con poche azioni manuali, pu\u00f2 creare svariati databases, completamente gestiti, in modo automatico. <\/p>\n\n\n\n Rimane comunque la necessit\u00e0 dell\u2019azione manuale per l\u2019installazione di plugin <\/strong>specifici.<\/p>\n\n\n\n A questo problema non c\u2019\u00e8 una soluzione standard a seconda del motore: scegliendo, ad esempio, tra PostgreSQL o MySQL, ci si trova di fronte a differenti versioni, ognuna delle quali supporta un insieme differente di plugins, ognuno, a sua volta, con diverse versioni. <\/p>\n\n\n\n In pratica, serve trovare un set di configurazioni compatibili<\/strong> che lavori insieme. Una volta trovato questo set, potremo sfruttare lo IaC per automatizzare completamente la creazione dei databases.<\/p>\n\n\n\n In questo articolo, proponiamo una possibile soluzione a questo problema, automatizzando la creazione di database con conseguente installazione di plug-ins a bordo di essi. Per gli esempi contenuti in questo articolo useremo AWS<\/strong> come cloud provider e RDS<\/strong>, con PostgreSQL<\/strong>, come servizio database.<\/p>\n\n\n\n Prima di sporcarci le mani con il codice CloudFormation, ci sono alcune cose che dobbiamo tenere in considerazione. Diamo per assunto che tutte le configurazioni relative all\u2019ambiente in cui il database verr\u00e0 messo siano gi\u00e0 state fatte, non essendo centrali in questo articolo. In particolare, diamo per scontato che VPC, sottoreti, tabelle di routing e security groups siano gi\u00e0 pronti. Verranno presi come parametri in input nel nostro codice per l\u2019infrastruttura.<\/strong><\/p>\n\n\n\n Partendo dalla creazione del database, ci sono tre risorse principali che sono necessarie alla creazione dell\u2019istanza: un subnet group<\/strong> per gestire il networking del database, un parameter group<\/strong> per definire alcuni parametri specifici della famiglia di database scelta e un option group<\/strong> per configurare alcune caratteristiche specifiche del dato engine del database.<\/p>\n\n\n\n Come possiamo vedere dal codice, utilizzando il subnet group, abbiamo messo il nostro database nelle sottoreti private e abbiamo configurato l\u2019uso di Postgres13 con l\u2019option group. Nel mentre, tramite il parameter group, abbiamo configurato un singolo parametro, ai fini della spiegazione, impostando il massimo numero di connessioni al database, limitandolo a 30.<\/p>\n\n\n\n Ora \u00e8 il momento dell\u2019istanza per il database. Dato che questo \u00e8 un semplice esempio, possiamo rimanere su configurazioni di base, utilizzando un\u2019istanza db.m5.large con 20 GBs per lo storage (gp2). Poi possiamo configurare altri parametri addizionali quali: nome dell\u2019istanza, nome dell\u2019utente master e la relativa password, i parametri relativi alla cifratura dello storage, come la chiave KMS e le finestre di backup e manutenzione preferite.<\/p>\n\n\n\n Insieme all’istanza del DB, ci sono alcune risorse aggiuntive che possiamo utilizzare per migliorare la sicurezza del nostro database. Abbiamo definito una chiave KMS, insieme al relativo alias, per criptare lo storage e un segreto dentro al Secrets Manager per contenere le credenziali di admin per l\u2019accesso al DB. Inoltre, come ulteriore layer di sicurezza, potremmo anche impostare un meccanismo che fa ruotare la password molto frequentemente, ad esempio ogni singolo giorno. Anche queste risorse possono essere create tramite CloudFormation. Non entreremo, per\u00f2, nei dettagli di ci\u00f2 dato che non \u00e8 l\u2019oggetto principale di questo articolo.<\/p>\n\n\n\n Giusto un\u2019ultima aggiunta riguardo l\u2019accesso al DB: in AWS c\u2019\u00e8 anche la possibilit\u00e0, per i database che lo supportano, di utilizzare le credenziali IAM per accedere alle istanze di database. Ci\u00f2 potrebbe risultare particolarmente utile per incrementare la sicurezza dell\u2019infrastruttura dato che verrebbe ridotto drasticamente il numero di credenziali di accesso.<\/p>\n\n\n\n Ora che abbiamo lanciato il nostro template CloudFormation e il nostro database \u00e8 stato creato, possiamo provare a connetterci e fare alcune queries. Per esempio, possiamo controllare il set di plug-ins installati con<\/p>\n\n\n\nDBSubnetGroup:\n Type: 'AWS::RDS::DBSubnetGroup'\n Properties:\n DBSubnetGroupDescription: !Sub \"${DBName}-db-subnet-group\"\n SubnetIds: [!Ref PrivateSubnetA, !Ref PrivateSubnetB, !Ref PrivateSubnetC]\n Tags:\n - Key: Name\n Value: !Sub \"${DBName}-db-subnet-group\"\n<\/code><\/pre>\n\n\n\n
DBOptionGroup:\n Type: \"AWS::RDS::OptionGroup\"\n Properties:\n EngineName: \"postgres\"\n MajorEngineVersion: 13\n # OptionConfigurations: [] # no options needed for PostgreSQL\n OptionGroupDescription: !Sub \"${DBName}-db-option-group\"\n Tags:\n - Key: Name\n Value: !Sub \"${DBName}-db-option-group\"\n<\/code><\/pre>\n\n\n\n
DBInstance:\n Type: 'AWS::RDS::DBInstance'\n Properties:\n DBInstanceIdentifier: !Ref DBName\n Engine: \"postgres\"\n DBInstanceClass: \"db.m5.large\"\n StorageType: \"gp2\"\n AllocatedStorage: 20\n DBParameterGroupName: !Ref DBParameterGroup\n OptionGroupName: !Ref DBOptionGroup\n DBSubnetGroupName: !Ref DBSubnetGroup\n VPCSecurityGroups: [!Ref DBSecurityGroup]\n MasterUsername: !Ref DBMasterUser\n MasterUserPassword: !Ref DBMasterUserPassword\n DBName: !Ref DBName\n Port: 5432\n AutoMinorVersionUpgrade: true\n CopyTagsToSnapshot: true\n Tags:\n - Key: Name\n Value: !Sub \"${DBName}-db\"\n<\/code><\/pre>\n\n\n\n
SELECT * FROM pg_extension;<\/pre>\n\n\n\n