SOBRE O AUTOR - estremote.vfm.com.brestremote.vfm.com.br/etec/P_ETIM/Apostilas/Caixa de...
Transcript of SOBRE O AUTOR - estremote.vfm.com.brestremote.vfm.com.br/etec/P_ETIM/Apostilas/Caixa de...
SOBREOAUTORPasseiminhainfânciaeadolescênciamexendoemeletrônica,guitarraecomputadores8bits.HojesouformadoemCiênciadaComputaçãoepós-graduadoemSistemasdeInformação.
Gostomuitodoquefaço:construoeconsertosistemasdistribuídosedelargaescalahá20anos.AlémdeprogramaremPython,ErlangeGo,façocafé,e-mail,cloud,bigdataeautomaçãodeinfra.
Háalgumtempocomeceiatrabalhargerenciandopessoasemeapaixoneipelapossibilidadedecriarequipeseconquistargrandesprojetos.Quandodescobriminhacarreiragerencialtivecertezadequedeveriameesforçarmaisparacontinuarrelevantetecnicamenteefalaralínguadaspessoasquetrabalhamcomigo.TiveasortedeparticipardeempresaseequipesquedesenvolvemeoperamalgunsdosmaioressistemasdainternetdoBrasil.
Escreviumlivroem2005chamadoProgramaçãoAvançadaemLinux,oprimeirolivrobrasileiroafalarsobrekernel,módulos,drivers,dispositivoseletrônicosetemasavançadosdosistemaoperacional.
JápalestreiemváriasediçõesdaRubyConf,QConeOSCon,noBrasilenosEstadosUnidos.Tenhoumrepositóriodecódigo(https://github.com/gleicon)epublicooqueachointeressantenoTwitter(https://twitter.com/gleicon).
MeuperfilprofissionalnoLinkedinficaemhttps://linkedin.com/in/gleicon.Tenhoumsitecomlinksparaprojetosemhttp://7co.cc/.Omaterialdaspalestrasquejádeipodeserencontradoemhttp://www.slideshare.net/gleiconetambémemhttps://speakerdeck.com/gleicon/.
Participedonossogrupodediscussãodolivro,emhttps://groups.google.com/forum/#!forum/caixa-de-ferramentas-devops.
INTRODUÇÃOEstelivroéumaintroduçãocomopiniõessobreferramentasparadesenvolvimentoeadministraçãodesistemas.Asferramentasdemonstradassãoflexíveiseextensíveis,oquepermitequeamesmatarefasejaexecutadadeformasdistintas.
Meuobjetivoémostrarumamaneiradeutilizá-lasparaganharprodutividaderapidamente.Aolongodotexto,coloqueireferênciasparaqueoleitorpossaseaprofundaroubuscarumconceitoteóricoqueestáforadoescopoproposto.NãovoumedeteremdiscussõesholísticasdeimplantaçãodeconceitosÁgeisouDevOps.
Originalmente,estelivroeraumconjuntodenotasquefuicolecionandoduranteodiaadiaeconversascomcolegas.Revisandoestasnotasquandopreciseicomeçarumnovoprojetomedeicontadequeelascontavamumahistóriainteressanteparaquemtevepoucoounenhumcontatocomferramentasdeautomaçãoevirtualização.Maisainda,elasmeajudaramatreinaroutraspessoascompoucotempoecomobjetivosmaioresdoqueseespecializarememAnsible,VagrantouVirtualbox.
Asideiasdescritaspodemserimplementadaseutilizadascomqualquersubstitutodestasferramentas─provavelmentevocêtemumdeploy.shemalgumdiretórioourepositórioquefazmaisqueelasemconjunto.Issoébom,poismostraqueanecessidadeexisteequejáfoiinvestidoumtempoematendê-la.Minhapropostanestecasoéexploraracombinaçãodasferramentasapresentadasparaentenderamaneiramodularcomoomesmoproblemaéresolvidoporelas.
Automatizaçãoéumamplificadordaenergiaquevocêinvesteemsuastarefas.Omesmoargumentoqueerautilizadoparacontroledeversãopodeserutilizadoparaautomação:você
comprometeumtempoaprendendo,investeumpoucomaisnosprimeirospassosedepoisganhaemescalaequalidadedetrabalho.
Umadasideiasquevouexplorarnotextoédequetodorepositóriodecódigotenhaumaestruturamínimaqueconsigacriarumambienteparadesenvolvimentooutestelocalmente.Aomontarumaestruturadeautomaçãoparasuaaplicaçãoquefuncionalocalmente,vocêganhaamesmaestruturaparaseuambientedeprodução.
Desenvolverlocalmentecomahabilidadedecriarambientescomarquiteturasemelhantesàsencontradasemambientedeproduçãoéumprincipiopoderoso.Elehabilitaodesenvolvimentoincrementaletestesfuncionais,alémdafamiliaridadecomaarquiteturadosistema.
Avelocidadededesenvolvimentoeavaliaçãodebibliotecaseprojetosdecódigoabertotambémaumentacomahabilidadedecriarumambienteisoladocomtodasasdependênciasedescartá-loapósouso.Finalmente,éumtreinamentoparaoprocessodedeploy.
Seencararmosofatodequesistemasesuasarquiteturasnãosãoestáticos,éimportantedesenvolverumconjuntodepráticasparaacompanharodesenvolvimentoemudançadestaarquitetura.Temosqueterrespostaspararecriaroambienteemcasodedesastres,fazercrescerseuscomponentesquandoconfrontadoscomumacargainesperadaedesenvolveremumaréplicaemescaladoambientefinal.
FerramentascomoAnsibleeVagrantsãoassociadasaomovimentoDevOps,queexploramudançasculturaiseorganizacionais,alémdenovasabordagensparaproblemasconhecidoscomogerenciamentodeconfiguração,monitoramentoecoletasdemétricas,aplicaçãodetécnicasdeengenhariadesoftware
nacriaçãodeinfraestruturaeainteraçãorápidaentreequipes.
Acompanhepodcasts(porexemplooFoodFight,listascomoDevOpsWeekly,Redditscomoreddit.com/r/devopsereddit.com/r/sysadmineconferenciascomoaVelocityparanovasideiaseprojetos.
Comasferramentasquevamosver,éfáciltestardeformacontroladanovasideiasapresentadasnestescanais.Nãoémandatórioadotarouseassociaraqualquergrupooumetodologiaparaterbenefícios.Sãoboaspráticascolhidasecompartilhadasporpessoascomexperiênciadesistemasemprodução.Ocustoébaixoeomaiorinvestimentoéotempoparaconsumiromaterialdisponível.
VouassumirqueseusistemaoperacionalébaseadoemLinuxouMacOSX.UsuáriosdeWindowspodemseguirasmesmasinstruções,masprovavelmenteterãoquetrocaradireçãodabarra(de/para\),encontrarumeditordetextoslegalepensarumpoucoondedeclararvariáveisdeambientesebibliotecasdePython.OcódigodemonstradonestelivroestarádisponívelemumrepositórioemminhacontanoGitHub(https://github.com/gleicon/caixa-de-ferramentas-devops).Estecódigoélivreexcetoaondealicençadasbibliotecasutilizadasinformem.
ParaasmaquinasvirtuaisereceitasdeAnsible,vouutilizaraúltimaversãoLTSdeUbuntuServer.VoumarcarospontosespecíficoseexplicarumpoucodecomofazeromesmoparadistribuiçõesbaseadasemRPM─érealmentefácilemostracomovaleapenainvestirtempoemumframeworkdeautomaçãocomooAnsible.Tambémvouassumirquevocêconsegueusaroterminal(Terminal,iTerm,RXVT,XTermetc.)disponível.Novamente,paraWindowsvouficardevendoalgoalémdocommandpromptedaversãodoPuTTYquefuncionalocalmente.Sesouberemdeumaalternativalegalquenãosejainstalarcygwin+XWindowme
contem.
Porúltimo,tenteicobrirexemplosdeaplicaçõessimpleserepeti-lossobcondiçõesdiferentesparacriarumahistóriadeevoluçãodousodasferramentas.
VamosinstalarumWordpressemváriasconfiguraçõeseprovedoresdeserviçoeposteriormenteumBancodedadosNoSQLchamadoCassandra.Sãoaplicaçõesquecobremalgunspadrõesdeusoeconfiguraçãoqueserepetem.Comisso,queroestimularadiscussãoeareflexãodaarquiteturadesuasaplicações.Penseemcomoelassãocompostasequalamelhormaneiradeorganizá-las.
Enjoy!
147
14
1516172027
2929313436
38
Sumário
1Linux,SSHeGit1.1Linux1.2SSH1.3Git1.4Conclusão
2Vagrant2.1Introdução2.2CaixadeFerramentas─VagranteVirtualBox2.3InstalaçãodoVirtualBox2.4InstalaçãodoVagrant2.5Conclusão
3Ansible3.1Instalação3.2AconfiguraçãodoAnsibleeoformatoYAML3.3AnsibleeVagrant3.4Refatoração3.5Conclusão
4InstalandoWordPressemumamáquina4.1Expandindonossoplaybook─UmblogcomWordPress
SumárioCasadoCódigo
5257606870
73778387
899498
100
102103105112118
120122125134
5ProxyReversoeWordPressemduasmáquinas5.1nginxeproxyreverso5.2WordPressemduasmáquinas5.3InstalandoseuWordPressemmáquinasvirtuais.5.4DigitalOceanAPIv25.5Conclusão
6CassandraeEC26.1VagranteCassandra6.2ProvisionamentonaAWS6.3CassandraeAWS6.4Conclusão
7Métricasemonitoração7.1Monitoração7.2CollectDeLogstash7.3Profiling7.4Conclusão
8AnálisedeperformanceemcloudcomNewRelic8.1WordPressnaAWS8.2InstalandooNewRelic8.3Gerandocarga─profilingdaaplicação8.4Simulandolimitaçõesderede8.5Conclusão
9Docker9.1Virtualização9.2ContainerseCGroups9.3Docker9.4Boot2Docker
CasadoCódigoSumário
135141151
153154158159164
9.5CriandonossocontainerdePHPeNGINXeusandooDockerHub9.6DockerCompose9.7Conclusão
10Emprodução10.1Deploy10.2BuildingBlockseLock-In10.3Blue/GreenDeployepacotes10.4Testes10.5Conclusão
SumárioCasadoCódigo
CAPÍTULO1
Nestecapítulovamosverumresumodetrêsassuntosquepermeiamolivro:Git,SSHeLinux.Sevocêéfluentenestastecnologiaspodepularestaintroduçãotranquilamente.
Estesassuntosemsicriaramlivrosbemcompletoseinteressantes.Voudemonstrareexplicaronecessárioparasobreviveraospróximoscapítulos.Vocêdeveprocuraroutroslivrosematerialnainternetparaseaprofundarcasotenhainteresse.
OsistemaoperacionalutilizadoemtodososexemplosdestelivroéoGNU/Linux,distribuiçãoUbuntunasuaversão14.04LTSde64bits.Compoucasadaptações,outrasdistribuiçõespodemserutilizadas.Escolhireduzirasopçõesparanosconcentrarmosnoobjetodolivro,principalmentequandofalarmossobreAnsible.
AssumitambémquesuamáquinatemalgumavariantedeLinuxouMacOSX.Faleiumpoucosobreissonaintrodução.Nãovamosutilizarcomandoscomplexos,masvouutilizaroTerminalsemprequepossível.NoMacOSXeuusooITerm2masnadaimpededeutilizaroTerminal.app.NoLinuxfiqueàvontadeparausaroterminalcomoqueestáacostumado.
Ointerpretadordeshellqueusoéobashqueestiverinstalado,eoeditordetextoséoVim,tambémnaversãoqueestiverdisponível.
LINUX,SSHEGIT
1.1LINUX
LINUX,SSHEGIT 1
Ondeforpreciso,fornecereilistagensdecódigosparaseremdigitadasecópiasemumrepositóriodoGitHub.
EstaversãodeLinuxéencontradanosprovedoresdeserviçoquevamosutilizar,oquefacilitaatransposiçãodosexemplosparaforadamáquinalocal.ExploreasdiferençasentreumLinuxexecutandolocalmenteeremotamente.Criemáquinaseobserveocomandotopnelas.
AconselhoquedigiteosexemplosnoambienteLinuxparasefamiliarizarcomasferramentasecomandos.Nospróximoscapítulosvousugerirqueoquefizermoslocalmentesejafeitoemumamáquinaemumprovedordecloudexterno.Aprogressãodoscapítulosnoslevaráacriarasmáquinasautomaticamente,masenquantonãochegamoslá,vocêprecisarádemáquinascriadascomautenticaçãoporchavedeSSH.
Adiante,veremoscomocriarmáquinasnaAWS(http://aws.amazon.com)enaDigitalOcean(http://digitalocean.com).Escolhiestesdoisprovedorespoiselestêmcuponseopçõesdecriareutilizarmáquinassemcustoporumperíodolimitado,oqueéidealparaoaprendizado.
Qualquerprodutousadoemprovedoresdecloudtemumcusto.Loadbalancersãocobradosportráfego,evolumesdestoragesãocobradosportráfegoearmazenamento.Máquinasvirtuaisgeralmentesãocobradasenquantoestãoligadasouenquantoexistirem.Leiabemadocumentaçãooferecidaeasregrasdecobrança.
NaDigitalOcean,oprocessoésimples:procurenoTwitterdeles(@DigitalOcean)umcódigooulinkecrieumaconta.Àsvezes,naprimeiravezquevocêcriaumacontajáganhaumcréditode5dolares,osuficienteparaummêscontínuodamenormáquinavirtualqueelesoferecem.Seutilizarmosmaismáquinasporum
2 1.1LINUX
periodomenordetempo,criandoedestruindoasinstâncias(outronomeparamáquinavirtual)estevalordáesobra.
Figura1.1:PaineldecriaçãodemáquinasdaDigitalOcean
NaAWS,sevocêjánãotemumaconta,precisacriar,configurarumVPC(VirtualPrivateCluster),umsecuritygroupesubnet.Vocêconsegueexecutarumamáquinasemissoapenasentrandonoconsole,selecionandoaopçãoEC2enopainelqueaparecerclicarnobotãoaseguir:
Figura1.2:BotãodecriaçãodemáquinasnaAWS
OprocessodecriaçãoeutilizaçãodaAWSécomplexopoisoferecetodaainfraestruturadeumdatacenterdeformavirtualeutilizávelprogramaticamenteviaAPI.Leiaadocumentaçãoem(https://aws.amazon.com)paraentendermelhoreuseofreetierparaseguirosexemplosoferecidos.
1.1LINUX 3
Nasopçõesdecriaçãodeinstânciasserãofeitasváriasperguntas.Éseguroinicialmenteusarasopçõespadrão.Lembre-sesemprededesligarasmáquinasnoconsoleparaevitarcobrançaextra.
OSSHéoprotocoloutilizadoparaseconectardeformaseguraemservidores.Pormeiodecriptografia,elecriaumcanalseguroentreduasmáquinas.OSSHpodeserutilizadotambémparaexecutarcomandosremotamentesementarnoshelldamáquina.
AconfiguraçãodoSSHérica,masparaospropósitosdestelivroéimportanteaprenderumatécnicadeautenticaçãoapenas.Normalmente,quandonosconectamosaumamáquinaapareceumpedidodesenha.
Paraautomatizarogerenciamentodeconfiguraçãoprecisamosconectaraosservidoressemestepedidodesenhadeformasegura.ProvedoresdecloudcomoaAmazonoferecemestaopçãocomoaprincipalerecomendadaparaoacessoaservidores.Outrossistemasdegerenciamentodeconfiguraçãopreveemainstalaçãodeumagentenasmáquinas.OAnsiblesóprecisadesteacessoporSSH.
Namaioriadosprovedores,vocêencontraráumaopçãoparaadicionarumachavedeSSHpública(PublicSSHKey).NaAWS,ocaminhodaschavesficadentrodoitemEC2nosubitemKeyPairs.
Vocêpodecriarsuaschavesnoconsoleeumarquivocomaextensão.pemserásalvoemseucomputador.NaDigitalOcean,vocêdeveadicionarumachaveexistenteeogerenciamentoédiferentedaAWSmasoresultadoéomesmo:asmáquinascriadasterãoestachaveconfiguradaautomaticamente.
OpaineldegerenciamentoecriaçãodechavesdaAWS:
1.2SSH
4 1.2SSH
Figura1.3:GerenciamentodechavesnaAWS
OpaineldegerenciamentodechavesdaDigitalOcean:
Figura1.4:GerenciamentodechavesnaDigitalOcean
Vamosgerarumpardechaveslocalmente.Noterminaldigite:
$ssh-keygen-trsa
Nomomentoemqueocomandoperguntarsobreumapassphrase,digite[ENTER]duasvezessementraropassphrase.Oresultadoesperadoéodapróximafigura:
1.2SSH 5
Figura1.5:ssh-keygen
Nossachavefoicriadacomonomeid_rsa_devopsedoisarquivosforamcriadosdentrododiretóriosshnohomedoseuusuário:id_rsa_devopseid_rsa_devops.pub.
Comopardechavespúblicaeprivadapodemosconfiguraroacessoremotoaoutrasmáquinas.Oarquivocomextensão.pubéoúnicoquedeverásercopiadoparaoutrasmáquinaseparapainéisdeconfiguração.ParaconfigurarachavenaDigitalOcean,sigaestetutorial(https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets)apartirdotrês.Éumasequênciadetelasindicandoondevocêcolocaachavepúblicacriadadentrodopaineldecontrole.
Otestedestetutorialécriarumamáquinaeexecutarocomando:
$sshroot@ip-da-maquina
Achaveserácolocadanousuárioroot.Sevocêjátemumamáquinacriadaougostariadefazerlogincomoutrousuárioquenãosejaoroot,façaumacopiadasuachaveúublica,entrena
6 1.2SSH
máquinapelométodonormaldeconexãocomsenhaecrieumaentradanoarquivoauthorized_keysqueficadentrododiretório.ssh/comoconteúdodoarquivoquetemsuachavepública─nonossocaso,id_rsa_devops.pub.
OGitéumsistemadecontroledeversãogratuita.Seusiteficaem(http://git-scm.com/).Emtermospráticos,suafunçãoécontrolarmudançasemrepositóriosdedados.Eudigodadosporqueelepodeserusadoparaoutrostiposdedadosalémdecodigo-fontedeprogramas.
Estelivro,porexemplo,foiescritoutilizandoumsistemabaseadono(https://www.gitbook.com),queutilizaoGitparacontrolarversõeseoprogressodocódigo-fontedeumlivro.
Éumaferramentasimplesmasbempensada,portantoalgunsconceitoseideiaspodemdemorarparafazersentidoparaquemnãousouumsistemadecontroledeversão.Maséotipodeferramentaquevocêaprendemuitorápidoquandoaincluiemseudiaadia.
UmadasformasdeutilizaroGitemseusprojetosécomoGitHubem(https://github.com).VamosinstalaroGitemseusistemaoperacional.NositedoGitedoGitHubvocêencontraráinstruçõesmaisdetalhadas.Minharecomendaçãoéutilizarogerenciadordepacotesdoseusistemaoperacional:
#Paralinuxbaseadoemdebian:$sudoapt-getinstallgit-core
#ParalinuxCentOS/RH$sudoyuminstallgit
#ParaMacOSXcomhomebrew$brewinstallgit
1.3GIT
1.3GIT 7
ParaWindows,procureumaversãocompatívelnosite(http://git-scm.com/downloads).ExisteminterfacesgráficasparautilizaroGitmasvoumemanternoterminal.Vocêpodeutilizá-lasseestáacostumado.
ApósinstalaroGit,executeoscomandosaseguir:
gitconfig--globaluser.name"Seunome"gitconfig--globaluser.email"[email protected]"
OGithubéumsitequefornecerepositóriosremotosdeGitemsuacontasemcusto,casooprojetosejaaberto,ecomcustocasovocêqueirarepositóriosprivados.Adiferençaéquerepositóriosprivadossóserãovistosporpessoasquevocêautorizar.Parautilizá-lo,váatéositeecrieumaconta.Oprocessoésimplesevocêseráredirecionadoaoseupaineldecontrole,que,senãomudouatéapublicaçãodestelivro,éassim:
Figura1.6:PaineldoGithub
Nesteponto,precisamosdeumpardechavesparaoSSH.OGitHubtemumaboaexplicaçãoparaesteprocedimentoem
8 1.3GIT
(https://help.github.com/articles/generating-ssh-keys/)sobaperspectivadesuaconfiguração.Comoquevimosanteriormentenãodeveserumproblema.Vocêpodecopiarachavecriada(~/.ssh/id_rsa.pub)diretamentenopasso4sejátemsuachavecriada.Senãocriouanteriormente,sigaestetutorial.
Comachaveconfigurada,vamoscriarumnovorepositório.Noteumbotãochamado+NewRepositorydoladodireito,aoladodotextoYourrepositories.Cliquenele.
Figura1.7:Criaçãoderepositório
EupreenchiacaixaembaixodotextoRepositoryNamecomonomeprojeto-simples.DeixeiorestodasopçõescomoestavamecliqueiemCreateRepository.
1.3GIT 9
Figura1.8:Repositóriocriado
Nabarradeendereçosdoseubrowserestáoendereçopúblicodoseurepositório.Nolugardousuáriogleiconapareceráseuusuário.Comonenhumcódigofoienviadoainda,atelaqueapareceéumaajudaparaaconfiguraçãodeumnovorepositórioouparaaativaçãodeumnovoremoteemumrepositórioexistente.
Remote,naterminologiadoGit,éumrepositórioremoto.Vamoscriarumrepositóriolocalqueconheceesterepositórioremotoemediantecomandossincronizaouenviaasmudançasparalá.
Estatrocadedadosébilateral.Podemosrecuperarmudançasemumrepositórioremotoparaorepositóriolocal,porexemploquandoumcolegatemautorizaçãoaorepositórioemodificaocódigo.OGitchamaestastransferênciasdedeltas.
Abraoterminaldoseusistemaoperacionalecrieumdiretóriochamadoprojeto-simples:
10 1.3GIT
$mkdirprojeto-simples
Entrenestediretóriocomcdprojeto-simpleseuseseueditordetextosparacriarumarquivochamadoREADME.md.Nestearquivodigiteotextoaseguir:
#READMEdomeuprojeto-simples
Esteprojetoéapenasumshellscriptquecontaitensunicosnodiretório/etc
Crieumarquivochamadoitens_unicos.sh:
#!/bin/sh
echo"Itensunicos"ls/etc|cut-d''-f1|sort|uniq|wc-l
VamosseguirasinstruçõesdoGitHub,comumapequenamudançaemgitadd:
gitinitgitadd.gitcommit-m"firstcommit"[email protected]:gleicon/projeto-simples.gitgitpush-uoriginmaster
Nobrowser,façareloaddapáginadoseurepositório.Eladeveseparecercomapróximaimagem:
1.3GIT 11
Estecomandomostraoestadoatualdorepositórioedasmudanças.AsaídadestecomandotemumasessãochamadaUntrackedfileseoarquivoportas.shestarálácomumaindicaçãodocomandogitadd<file>paraadicioná-lo.
$gitaddportas.sh
AgoraogitstatusvaimostrarumasessãochamadaChangestobecommittedcomoarquivoportas.sheumaindicaçãodeusodogitresetparareverteraúltimamudançaemrelaçãoaoestadodorepositório.Vamosemfrentecomocomandogitcommit.
$gitcommit-m"novoarquivo"
Oparâmetro-mdocomandogitcommitéapenasumamensagemqueindicaomotivodamudança.Apósocommit,gitstatusmostraumamensagemindicandoqueseubranchlocalestáumcommitàfrentedorepositórioorigin/masteresugereousodogitpush.
$gitpushoriginmaster
Apósogitpush,amensagemdogitstatuséYourbranchisup-to-datewith'origin/master'.nothingtocommit,workingdirectoryisclean.VolteàpaginadoseurepositórionoGitHubeconfiraamudança.
Comesteconhecimento,vocêjáestáaptoausaroGitparaseusprojetoseacriarmáquinasquepodemseracessadassemsenha,comousodechavepúblicadeSSH.Sevocêjáexecutaestastarefasdeoutramaneira,nãotemproblema,oscapítulosaseguirforamescritosdeformaafuncionarcomumavariaçãograndedosprocessosdescritos.
1.4CONCLUSÃO
14 1.4CONCLUSÃO
CAPÍTULO2
Oprimeiropassoparacriarumambientedeproduçãooudesenvolvimentoéterumamáquinadedicadaouumespaçoemumamáquina.Comapopularizaçãodetécnicasdevirtualização,háalgumtempovocêpodetermáquinasvirtuaisexecutadasemsuamáquinalocal.
Umamáquinafísicaconsegueexecutarmaisdeumamáquinavirtualemparalelo.AplicativoscomoVirtualBox,ParallelseVMWaresãoutilizadosparagerenciareexecutá-las.
Umamáquinavirtualparadanadamaiséqueumaimagemdeumdiscoemetadadosquedescrevemsuaconfiguração:processador,memória,discoseconexõesexternas.Amesmamáquinaemexecuçãoéumprocessoquedependedeumscheduler(agendadordetarefaseprocessos)paracoordenarousodosrecursoslocais.
Vocêpodegerenciarsuasmáquinasvirtuaisdiretamentedasinterfacesdasaplicaçõescitadasanteriormenteoupodeutilizarbibliotecasesistemasqueabstraemasdiferençasentreessasplataformas,cominterfaceconsistenteparacriar,executar,pararemodificarumamáquinavirtual.
Éimportantenaescolhadestesistemalevaremcontaqueexistemdiferentesformatosdemáquinasvirtuaisediferentes
VAGRANT
2.1INTRODUÇÃO
VAGRANT 15
sistemasoperacionais,portanto,umformatodetemplateealgunsconceitosadicionaisqueauxiliemnacriaçãodestasmáquinassãodesejáveis.
Precisamostambémdefontesdemáquinasvirtuais,inicialmentecomosistemaoperacionaloriginal,mastambémcomapossibilidadedetermáquinascustomizadas.Apósacriaçãodamáquina,queremosexecutarumpassoposterior,quechamaremosdeprovisionamento,paramodificarosistemaoperacionalentregue,instalandopacoteseconfigurações,alémdeinstalarsuaaplicaçãoepossivelmentesalvaraquelaversãodamáquinavirtualparausoposterior.
Paracriaregerenciarosambientesdemáquinasvirtuaislocais,escolhioVagrant(https //www vagrantup com/) Paraexecutarasmáquinasvirtuais,escolhioVirtualBox(https://www.virtualbox.org/).
OVagrantgerenciaeabstraiprovedoresdemáquinasvirtuaislocaisepúblicos(VMWare,VirtualBox,AmazonAWS,DigitalOcean,entreoutros).Eletemumalinguagemespecífica(DSL)quedescreveoambienteesuasmáquinas.Alémdisso,eleforneceinterfaceparaossistemasdegerenciamentodeconfiguraçãomaiscomunscomoChef,Puppet,CFEngineeAnsible.
ComoVirtualBox,temosumaalternativadecódigoabertoegrátisparaexecutarasmáquinasvirtuaislocalmente.EleébemintegradocomoVagrantetemtodasasopçõesdeoutrasplataformas.Porumpreçomódicovocêpodetrocarporoutroprovedoreaindaassimutilizaramesmalinguagemeinterfaceparagerenciarsuasmáquinaseambientesdamesmaforma.
2.2CAIXADEFERRAMENTAS─VAGRANTEVIRTUALBOX
16 2.2CAIXADEFERRAMENTAS─VAGRANTEVIRTUALBOX
VáatéositedoVirtualBoxem(https://www.virtualbox.org),façaodownloaddaúltimaversãoestávelparaseusistemaoperacional.EledevepedirparainstalaralgumasextensõesquepermitemaexecuçãodemáquinasvirtuaisepacksdeexpansãoparaoutrosdispositivoscomoUSBevolumesdedisco.VocêveráquequandoexecutaoVirtualBoxelemostraummenuquepermitecriarmáquinasapartirdeimagensISOouimportarmáquinasexistentes.
Seocorreralgumproblemanestafase,verifiqueseoseusistemaoperacionalestáatualizado,seaversãodoVirtualBoxéacorreta,setemespaçoemdiscoesejánãotemumaversãoinstaladaquepossaestaremconflito.Leiaadocumentaçãodetroubleshootingantesdepostarumbuge,seencontraralgonovo,aviseosdesenvolvedores.
Nesteponto,vocêpodefazerodownloaddeumaISOdeUbuntunesteendereço(http://www.ubuntu.com/download/server)etestaracriaçãodeumamáquinavirtual.
ExecuteoVirtualBoxecliqueemNewnocantosuperioresquerdo.Umdiálogoquepedeonomeeotipodesistemaoperacionalaparecerá.Preenchacomonomedasuamáquinavirtual,sistemaoperacionaleversãodosistema.
2.3INSTALAÇÃODOVIRTUALBOX
2.3INSTALAÇÃODOVIRTUALBOX 17
Figura2.1:VirtualBox-criaçãodamáquinavirtual
Ospróximosdiálogosserãosobretamanhodamemória,tamanhoetipodedisco.Selecioneaquantidadedememóriade1GB,indiquequeodiscoseránovo,dêumnomeaele,digaqualoespaçoalocadoesecrescedinamicamente.Mantenhaasopçõesdefaultemcasodedúvida.
Suamáquinafoicriadamasaindaestávazia.Deumduplocliqueemcimadelaeexecute(ouRunseestivereminglês).
18 2.3INSTALAÇÃODOVIRTUALBOX
Figura2.2:VirtualBox-primeiraexecuçãodamáquinavirtual
Odiálogoaseguiraparecerá,comatelapretadefundo.Nesteponto,selecioneaimagemISOdequefezdownloadanteriormenteeaguardeainstalaçãodosistemaoperacional.FinalizeainstalaçãodoUbuntu(setiverdúvidas,leiaadocumentação).Marqueotempofinalequantosminutoslevouparainstalarestamáquina.Estainformaçãoseráimportanteparaapróximasessão.
2.3INSTALAÇÃODOVIRTUALBOX 19
Figura2.3:VirtualBox-instalaçãodosistemaoperacional
Ainstalaçãodemáquinasvirtuaisemprovedoresdeinfraestruturanãoédiferentedestasequência.Emalgunscasos,algumasopçõessãopredefinidasparapouparousuário,porexemplo,imagensdisponíveis.
SelecioneefaçaodownloaddaversãodeVagrantparaseusistemaoperacionalemhttps://vagrantup.com.Leiaadocumentaçãopoisháinformaçõesinteressantesesempreatualizadasdasplataformassuportadas.Uminstaladoréfornecidoevocêtemtudodequeprecisaempoucoscliques.
Abraseuterminaledigitevagranthelp.
2.4INSTALAÇÃODOVAGRANT
20 2.4INSTALAÇÃODOVAGRANT
AsopçõesapresentadaspodemvariardeacordocomaversãoatualdoVagrant.Vamoscomeçarcomalgumasopçõescomunsparagerenciarociclodevidadamáquinavirtual.
CriaremosumamáquinausandooVagrant.Noterminal,crieumdiretóriochamadotestevm.Entreneleecomseueditordetextospredileto(porexemplo,oVim)digiteoseguintecódigoemumarquivochamadoVagrantfile(ocódigoestádisponívelemumrepositóriomaseusugiroqueinicialmentevocêdigiteparaterfamiliaridadecomoqueestamosfazendo):
#-*-mode:ruby-*-#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.define"testvm"do|testvm|testvm.vm.box="ubuntu/trusty64"testvm.vm.network:private_network,ip:"192.168.33.2 "end
config.vm.provider"virtualbox"do|v|v.customize["modifyvm",:id,"--memory","1024"]end
end
Salveesaídadoseueditorpredileto(ESC:wqnoVim)edigitevagrantupnoterminal.Aguardealgunssegundosouminutosdeacordocomaconfiguraçãodesuamáquina.Verifiquequantotempolevouparaexecutarestespassos.Paratestar,digiteocomandovagrantssh.
Utilizesuamáquinanormalmente(executartopparaverosprocessos,examinarodiretório/etc,instalaralgumpacotemanualmente).
Dentrodamáquina,digitecd/vagrantevejaqueoseu
2.4INSTALAÇÃODOVAGRANT 21
diretóriolocalfoimapeadocomoummountpointdentrodamáquinavirtual.Vocêpodecriarestepontocomoutronomeoudeixardecriá-lodeacordocomaconfiguraçãodoVagrantfile.
Digitevagrantdestroynoterminaleyquandoperguntadosepoderealmentedestruirestamáquinavirtual.
Semconsideraracapacidadedesuamáquinafísicaesuaproficiênciadigitandocódigo,vimospelasimagensdopassoapassodoVirtualBoxqueonúmerodepassosparacriarumamáquinavirtualégrande.SomeaotempodoVirtualBoxotempodedownloaddaimagemISOdeUbuntueofatodequeparaapagaramáquinavirtualteráquesepassarportodosospassosnovamenteetemosumprocedimentolongoaserreplicado.
ApóscriaresteVagrantfile,vocêpodesubir(up)amesmamáquinaváriasvezes,emocasiõesdistintassemutilizarainterfacedoVirtualBox.Épossívelversionarestearquivoquedescrevesuamáquinavirtualjuntocomseucódigoequandomudaraconfiguraçãodememória,porexemplo,estamudançaestaránohistóricojuntoàsmudançasdecódigo.
MeçaquantotempolevaparasubirumanovamáquinavirtualdeUbuntuutilizandooVagrant,agoraqueaimagemestágravadaemsuamáquina.Estecachedeimagenséimportantequandovocêestáemumestágioemqueprecisacriaredestruirmáquinasrapidamente.
Atéagora,aprendemosacriarumdiretóriocomumarquivoquedescreveumamáquinavirtual,asubir,conectaredestruí-la(vagrantup,sshedestroy).Agoravouexplicaroqueestearquivosignifica.
OVagranteasuaconfiguraçãoutilizamRuby.ExistemversõesdistintasdeAPIsevamosutilizaraversão2.Dentrodeuma
22 2.4INSTALAÇÃODOVAGRANT
instânciadaconfiguraçãodefinimosmáquinasesuascaracterísticas,emumblocodecódigoRuby.Vejaomesmocódigocomentado:
Vagrantfile
#-*-mode:ruby-*-#vi:setft=ruby:#aslinhasacimaindicamalinguagemparaoeditordetexto
VAGRANTFILE_API_VERSION="2"#versãodaAPIdoVagrant
#EsteblocoderubycontémtodasasatividadesqueoVagrant#deveexecutarrepresentadaspeloobjetoquechameideconfigVagrant.configure(VAGRANTFILE_API_VERSION)do|config|#config.vmcriaumobjetoquedescreveumamáquinavirtual.#Chameiestavmde"testevm"equeroutilizaroUbuntuTrusty#IndiqueiquequeroumIPprivadoparaestamáquinaconfig.vm.define"testvm"do|testvm|testvm.vm.box="ubuntu/trusty64"testvm.vm.network:private_network,ip:"192.168.33.2 "end
#Esteblocomedáacessoaoprovedordamáquinavirtual#(VirtualBox)#Configureiestamáquinacom1GBdememóriaconfig.vm.provider"virtualbox"do|v|v.customize["modifyvm",:id,"--memory","1024"]end
end
Nestearquivo,descreviminhamáquinavirtualedissequegostariadeusaroUbuntuTrusty(14.04)de64bits.OVagrantfornecealgumasimagensetemumacomunidadequepermiteaosseususuárioscompartilharemimagenscustomizadas.Éinteressantenotarqueelecriaumabibliotecalocalcomasimagensquevocêutiliza,portanto,ocustodefazerdownloaddaimageméamortizadoentreasvezesemquevocêsobeedestróisuasmáquinasvirtuais.
OnomedasimagensnoecossistemadoVagrantéboxouboxesnoplural.Oboxqueutilizeiéchamadodebasebox,porseruma
2.4INSTALAÇÃODOVAGRANT 23
dasimagensqueelesmantêmsócomosistemaoperacional.
Alémdesubiredestruirsuamáquinavirtual,vocêpodedesativá-lausandoocomandovagranthalt.LeiaadocumentaçãodoVagrantsobrecriarsuasprópriasmáquinas.Nesteponto,seuexercícioéexploraramáquinaquecriamosecustomizá-ladeacordocomseugosto.
Comvagrantup,subaamáquinaeconectecomvagrantssh.Comcuidadoparatercertezadequeestáconectadoequenãovaiexecutarumcomandoemsuamáquinafísicalocal,executeasequênciadecomandos:
$sudoapt-getupdate$sudoapt-getinstallnginx
Abraseubrowserlocaleaponteparaoendereçohttp://192.168.33.2.Vocêdeveveramensagemdeboas-vindasdonginx.Volteaoterminaledigite:
$sudo-s$echo"boacabelo">/usr/share/nginx/html/index.html
Volteaoseubrowseredêreloadnapagina,deveaparecerotexto"boacabelo".Imagineoutrasconfiguraçõesquegostariadefazernestamáquinaalémdecolocarumwebservercomumíndiceservindoafrase"boacabelo".Executeecrieumamáquinapersonalizadaparaisso.
SeupróximopassoémodificaroVagrantfileparautilizarestamáquina.Seerraremalgumaconfiguração,lembre-sequeépossíveldestruiramáquinaerecriá-ladozero.Testeoutrossistemasoperacionaiseimagenscriadasparafinsdistintosem(https://atlas.hashicorp.com/boxes/search).
Criaramáquinarápidoeterqueinstalaronginxmanualmenteémelhordoquecriarusandoométodomanualnainterfacedo
24 2.4INSTALAÇÃODOVAGRANT
VirtualBox,masaindapodemelhorar.
OVagrantimplementaoconceitodeprovisionadorcomdriversparaquasetodosossistemasdegerenciamentodeconfiguraçãoexistentes.Estessistemasvãodereceitassimplesparainstalarpacotesatéagentesqueverificamaintegridadedearquivosdeconfiguraçãoevariáveisdosistema.
VamosutilizarumdriverdeprovisionamentodoVagrantquepermitequeumarquivocomcomandosdoshellsejaexecutadologoapósacriaçãodamáquinavirtual.Crieoarquivowebserver.shnomesmodiretórioedigiteosseguintescomandos:
#!/bin/bash
echo"Atualizandorepositórios"sudoapt-getupdateecho"Instalandoonginx"sudoapt-get-yinstallnginx
SalveoarquivoeediteoarquivoVagrantfileparaativaroprovisionador.Eledeveficarcomoalistagemaseguir:
#-*-mode:ruby-*-#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.define"testvm"do|testvm|testvm.vm.box="ubuntu/trusty64"testvm.vm.network:private_network,ip:"192.168.33.2 "testvm.vm.provision"shell",path:"webserver.sh"end
config.vm.provider"virtualbox"do|v|v.customize["modifyvm",:id,"--memory","1024"]end
end
Alinhatestvm.vm.provision"shell",path:webserver.shdiz
2.4INSTALAÇÃODOVAGRANT 25
paraoVagrantqueparaaquelamáquinavirtualdeveserusadoodriverdeprovisionamentodeshellscriptepassacomoparâmetrooarquivocomcomandosquecriamos.
Destruaecrieamáquinavirtualnovamentecomvagrantdestroyecriecomvagrantup.Observeasaídanoterminalefaçaomesmotestenobrowser,semanecessidadedeseconectarporsshparaexecutarocomandoqueinstalaonginx.
VamosinstalaroPHP5namáquina.Modifiqueoarquivowebserver.shdeacordocomalistagemaseguir:
#!/bin/bash
echo"Atualizandorepositórios"sudoapt-getupdateecho"Instalandoonginx"sudoapt-get-yinstallnginxecho"InstalandooPHP"sudoapt-getinstall-yphp5-fpm
Nesteponto,nãoprecisamosdestruirerecriaramáquinaparaexecutarnovamenteoprovisionamento.Contamoscomofatodequeogerenciadordepacotesnãoinstalaráumpacoteduasvezes.Poderíamosexecutaromesmoscript,quesóoPHPseriainstalado.OVagrantofereceumcomandoqueativasomenteafasedoprovisionamentovagrantprovision.Executevagrantprovisionemseuterminaleobserveaexecuçãodoscript.
AtéestepontovimoscomocriarumadescriçãodemáquinavirtualcomoVagranteosseguintescomandos:
$vagrantup$vagrantssh$vagrantdestroy$vagranthalt$vagrantprovision
Comestescomandos,conseguimosgerenciardeformarápidaelimpaasmáquinasvirtuaiscriadasdeacordocomoVagrantfile.
26 2.4INSTALAÇÃODOVAGRANT
NotequeelessófuncionarãodentrododiretórioemqueoVagrantfileestá.Executeocomandols-larthevejaquefoicriadoumdiretóriochamado.vagrantquecontémtodososdadosdociclodevidaeprovisionamentodamáquinavirtual.
Vocêjáconheceasferramentasdegerenciamentodemáquinasvirtuaisinstaladasemsuamáquinaejáconsegueusá-lasparatarefasbásicas.ExploreadocumentaçãoparaentendercomoelaspodemfacilitarseutrabalhoatécomprovedoresreaisdeIaaS.ParticipedaslistasdediscussõeseprocureVagrantfilesnoGitHub(https://github.com)paraternovasideiasdecomoutilizá-lo.Explorenovasimagensdesistemasoperacionais.
OVagrantabstraimuitastarefasdegerenciamentodemáquinascomoautomaçãodatrocadechavesdeSSH,criaçãodeusuáriosemontagemdediretórios.Elepermiteprovisionadoresplugáveiseacomposiçãosimplificadadeclusterscommáquinasdeconfiguraçõesdistintas.OquevimosatéagoradoVagrantésuficienteparacontinuarmoscomoAnsiblenopróximocapítulo.
2.5CONCLUSÃO
2.5CONCLUSÃO 27
CAPÍTULO3
Nestecapítulo,vamosretomaroexemplodocapítuloanteriorusandoAnsible.OAnsibleéumsistemadeautomaçãodeconfiguraçãofeitoemPython,quepermitedescreverprocedimentosemarquivosnoformatoYAMLquesãoreproduzidosutilizandoSSHemmáquinasremotas.
Existemoutrasferramentasdestacategoriaqueexecutamlocalmenteequefornecemservidoresparaogerenciamentodedadosremotamente,comoCHEF,PuppeteCFEngine.
VamosutilizaroAnsiblelocalmentesemseuservidordedados,oAnsibleTower.OAnsiblevemcombibliotecascompletasparaquasetodasastarefasalémdeumalinguagemdetemplate.Alémdastarefasdentrodeumservidor,oAnsiblefornecemódulosparaprovisionamentodemáquinaseaplicaçõesremotas.Provisionaréojargãoparainstalareconfiguraritensdeinfraestruturaeplataformacomomáquinas,bancosdedadosebalanceadoresdecarga.
Nocapítuloanterior,terminamoscomumVagrantfileeumshellscriptparainstalarnginxePHP.VamostraduzirliteralmenteparaoAnsibleeprogressivamentevamosutilizarseusmódulosparafazerdojeitocerto(tm).PosteriormenteutilizaremosoAnsibleparacriarmáquinasvirtuaisemprovedoresegerenciarociclodevidadelas.
Poderíamostercontinuadoausarshellscriptparaconfigurar
ANSIBLE
28 ANSIBLE
nossasmáquinas,massistemascomooAnsibleimplementamtarefascomumacaracterísticaimportante:idempotência.Aidempotênciaéumapropriedadeque,aplicadaaogerenciamentodeconfiguração,garantequeasoperaçõesterãoomesmoresultadoindependentementedomomentoemqueserãoaplicadas.Acriaçãodesuamáquinautilizandoesteconjuntodeconfiguraçõessempreteráoresultadoprevisível.
TemosqueinstalaroAnsibleemnossamáquinalocal.Elenãotemnenhumagenteoubibliotecaquedevaserinstaladonamáquinavirtual.OAnsibleéfeitoemPythonefuncionaemmuitasplataformas.AmaneiracomosecomunicacomasmáquinasvirtuaisoufísicasconfiguradaéporintermédiodeSSH.
SeoseusistemaoperacionalforMacOSX,useohomebrew.Abraoterminaledigitebrewinstallansible.Nãousahomebrew?Use:
$sudoeasy_installpip$sudopipinstallansible
ParaLinux,sigaadocumentaçãoem(http://docs.ansible.com/intro_installation.html#latest-releases-via-apt-ubuntu).VoureproduziroprocedimentoparaUbuntu:
$sudoapt-getinstallsoftware-properties-common$sudoapt-add-repositoryppa:ansible/ansible$sudoapt-getupdate$sudoapt-getinstallansible
Paratestarsefoiinstalado,digitenoterminalansible-playbook-h.DeveapareceraajudadoAnsible.
3.1INSTALAÇÃO
3.2ACONFIGURAÇÃODOANSIBLEEO
3.1INSTALAÇÃO 29
Entrenodiretóriotestvmedigiteoarquivoaseguircomonomedewebserver.yml:
-hosts:allsudo:Trueuser:vagranttasks:-name:"Atualizapacotes"shell:sudoapt-getupdate
-name:"Instalaonginx"shell:sudoapt-get-yinstallnginx
Esteéumarquivonoformatoyaml.Usedoisespaçoscomotab(setts=2noVim).Presteatençãonosinalde:(doispontos)apósosatributos.OAnsiblevaireclamarsenãoentenderoarquivoevocêpoderáconsertá-lo.
Sempreconfiraaindentaçãoeosdoispontosapósosatributos.Confiratambémohífenantesdosatributosquandonecessário.Aformataçãoésimplesmasimportante.
YAMLéumformatoqueserveparaserializaçãoetransmissãodedados.Eleécompostodepalavras-chavesseparadasdeumvalorpor:(doispontos).Seusdadospodemserchavesevalores,listasdechavesevaloresedicionários.Porexemplo:
Umalista:
-gato-cachorro-limão
Dicionário:
nome:gleiconsobrenome:moraeslinux:simporfavor
Osvalorespodemseralfanuméricos.Acombinaçãosegueo
FORMATOYAML
30 3.2ACONFIGURAÇÃODOANSIBLEEOFORMATOYAML
padrãodetabspace=2(cadaníveléseparadopor2espaços).ÉumformatosimpleseoAnsibleutilizaumsubsetdetudoqueelepoderepresentar.VocêpodeusaroYAMLLintem(http://www.yamllint.com/)paraverificarseuplaybooksemterqueexecutá-lo.
Vamosvermaissobreoarquivodeconfiguraçãonesteenospróximoscapítulos.Onomecorretodestearquivoéplaybook,poisoAnsibletemumarquivodeconfiguraçãodesuaspropriedadesquenãodependemdeumhostespecífico.
AbraoarquivoVagrantfileemodifique-oparaquefiquedeacordocomalistagemaseguir:
#-*-mode:ruby-*-#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.define"testvm"do|testvm|testvm.vm.box="ubuntu/trusty64"testvm.vm.network:private_network,ip:"192.168.33.2 "
testvm.vm.provision"ansible"do|ansible|ansible.playbook="webserver.yml"ansible.verbose="vvv"end
end
config.vm.provider"virtualbox"do|v|v.customize["modifyvm",:id,"--memory","1024"]end
end
Adiferençaentreosdoisarquivoséoblocoaseguir:
3.3ANSIBLEEVAGRANT
3.3ANSIBLEEVAGRANT 31
testvm.vm.provision"ansible"do|ansible|ansible.playbook="webserver.yml"ansible.verbose="vvv"end
Adefiniçãodemáquinavirtualdetestvmtemumatributoquedefineumprovisionador.Nocapítuloanterior,useiumshellscriptparainstalaronginx.Comestamudança,oVagrantutilizaráoAnsiblecomoprovisionadorcomoplaybookwebserver.yml.DeixeioatributoverbosedoAnsiblecomovalorvvvparaindicarquequerotodasasmensagensenviadasparaoconsole.
Vamosexaminaroarquivowebserver.ymllinhaalinhaeadicionarainstalaçãodoPHP.Aprimeiralinhaquecontémoatributohostséonívelmaisaltodoplaybook.Eladefineemqualmaquinaougrupodemáquinasadescriçãoseráaplicada.Ovalorallindicaquepodeseraplicadoaqualquerumadefinidanoarquivoquecontémosendereçosdasmáquinas.ComooVagrantexecutaoAnsibleindiretamente,eleforneceestearquivo.
SeexecutarmosoplaybookdiretamentenoterminalsemoVagrant,teríamosquepassarumarquivodeinventário(eminglês,inventoryfileouhosts.ini).Oformatodestearquivoésimples:
[grupo1]10.0.0.110.0.0.210.0.0.3
[grupo2]10.0.0.410.0.0.5
Seovalordoatributohostsfossegrupo1eestivéssemosexecutandooAnsiblemanualmente:
$ansible-playbook-ihosts_filewebserver.yml
OplaybookseriaaplicadoapenasnasmáquinascomIPs10.0.0.1,10.0.0.2,10.0.0.3.Seovalorfosseall,eleseriaaplicado
32 3.3ANSIBLEEVAGRANT
emtodasasmáquinas.Esteéocasoutilizadocasovocêtenhaumamáquinavirtualemalgumprovedorequeiraexecutaroplaybook.
BastasecertificardequeseuusuáriotemautenticaçãoporchavedeSSH(sshusuario@maquinadevelogarsempedirsenha).AjusteonomedousuárionoarquivodoAnsibleeexecuteoplaybookcomoindicadoanteriormente.
Vocênãoprecisarásepreocuparcomestearquivoagora,masposteriormentevamosutilizaromesmoplaybookparadesenvolvimentolocaledeployemumaVPSeestearquivoseráutil.
sudo:Trueuser:vagrant
EstesatributosindicamqueoAnsiblepodeusarsudoeousuáriodeconexãonamáquinaéousuáriovagrant.EsteparâmetrotambémserámodificadoparainstalaçãoemumaVPSparaseuusuárioouousuáriodefaultdadistribuição.
tasks:-name:"Atualizapacotes"shell:sudoapt-getupdate
-name:"Instalaonginx"shell:sudoapt-get-yinstallnginx
OatributotaskséumalistadetarefasqueoAnsiblevaiexecutar.Elaécompostapornome/ação.Nestearquivo,utilizamosumataskchamadashellqueexecutaocomandoemseguidadiretamentenoterminaldamáquina.
Agora,executevagrantupeobserveainstalaçãodoAnsibleatéreceberumstatusfinalsemelhanteaeste:
PLAYRECAP******************************************************testvm:ok=3changed=2unreachable=0failed=0
PLAYRECAPéoresumodaaplicaçãodoplaybook.Paraohosttestvmduastasks(ok=3)foramexecutadas.Umadelascausou
3.3ANSIBLEEVAGRANT 33
umamudançanohost(changed=2).DuranteaexecuçãodoprovisionamentocadaumadastasksfoiexecutadaeindicadapeloAnsible,alémdopassochamadoGATHERINGFACTS.
ComonossoVagrantfiletemumindicadordeníveldeverbosidadedoAnsibleconfigurado,vocêviubemmaisdoqueisso.Vocêpoderemoverestaopçãoquandoterminarumplaybookpoiselasóéútilparadebugdurantedesenvolvimento.
Seexecutarmosoprovisionamentonovamentenamesmamáquinacomvagrantprovision,teremosamesmasaída:
PLAYRECAP******************************************************testvm:ok=3changed=2unreachable=0failed=0
OAnsibleexecutouamesmasequênciadecomandosnasduasvezes.AtaskshelléumadasmaissimplesdoAnsibleetempoucocontroledeestado,oquenãocontribuicomaidempotênciaentreasrodadasdoprovisionamento.Nestaconfiguração,ocontroleéexecutarasduastaskscomsucessosemguardarumestadoatualoulevá-loemconta.VamosmelhorarissoeaprendercomoutilizarmelhorosmódulosqueoAnsibleoferece.
TodataskéumafunçãodeummódulodoAnsible.OsmódulosquevêmnainstalaçãopadrãoelesãochamadosdeCoreModules.VocêpodeconstruirseusmódulosutilizandoalinguagemPythoneestenderoAnsible.
Vamosrefatorarnossoplaybookparautilizarummódulocorechamadoapt_module(http://docs.ansible.com/apt_module.html)emvezdomóduloshell.Omóduloshelléútilparaautomatizarmuitastarefas,masvocêvaiencontrarmódulosespecializadosdoAnsiblequecuidamdaconsistênciadatarefaecriamestadosparamanteraidempotência.Atualizeoarquivowebserver.ymlde
3.4REFATORAÇÃO
34 3.4REFATORAÇÃO
acordocomalistagemaseguir.
-hosts:allsudo:Trueuser:vagranttasks:-name:"Atualizapacoteseinstalanginx"apt:name=nginxstate=latestupdate_cache=yesinstall_recommends=yes
ReduzimosasduastasksparaumaqueutilizaomóduloaptedizparaoAnsibleinstalaronginxnoúltimoreleasepresentenorepositório.Umdosatributosdestataskéindicarqueumupdatenocachedogerenciadordepacotesdeveexecutado.
Outroatributoqueutilizaremoséaindicaçãodequeasdependênciasrecomendadasdevemserinstaladasautomaticamente.Noteque,utilizandoomóduloshell,eupreciseipedirexplicitamentepelaatualizaçãodorepositórioetambémadicionaroparâmetro-yaocomandoapt-getinstallparaevitarqueataskficasseesperandoumaentradadousuário.
OAnsibletambémforneceummóduloparaogerenciadordepacotesyum(http://docs.ansible.com/yum_module.html)ediretivascondicionaisquepodemserusadasparadetectarosistemaoperacionaledistribuiçõesdeLinux.VejacomodeclararamesmataskparainstalarnginxparaduasfamíliasdedistribuiçõesdeLinuxutilizandoocondicionalwhenevariáveisinternasdoAnsible:
-name:Installthenginxpackagesyum:name={{item}}state=presentwith_items:redhat_pkgwhen:ansible_os_family=="RedHat"
-name:Installthenginxpackagesapt:name={{item}}state=presentupdate_cache=yeswith_items:ubuntu_pkgenvironment:envwhen:ansible_os_family=="Debian"
Podemostestaronovowebserver.ymlcomvagrantupou
3.4REFATORAÇÃO 35
apenasvagrantprovisioncasosuamáquinavirtualaindaestejasendoexecutada.Apósaprimeiraexecuçãodovagrantupouvagrantprovision,executevagrantprovisionnovamenteeanaliseasaídanoconsole.OPLAYRECAPdeveserdiferente.
Executeoprovisionamentoemseguidaparanotaradiferençaentreaprimeiraeasegundaexecução.Estaéumamaneirasimplesdeverificaraidempotênciadoplaybook:nasegundarodada,oatributochangeddeveser0.
Apósvagrantup:
PLAYRECAP******************************************************testvm:ok=2changed=1unreachable=0failed=0
Apósvagrantprovision:
PLAYRECAP******************************************************testvm:ok=2changed=0unreachable=0failed=0
Estemódulonosdeumaiscontroleeumestado:ainterpretaçãodogerenciadordepacotes.ExistemmódulosparaRPMeoutrasdistribuiçõesdeLinuxalémdapossibilidadedeautomatizarainstalaçãoougeraçãodeumpacoteapartirdeumrepositóriodecódigo.
Oparâmetrostateconfiguradoparalatestdescrevedoisestados:opacotedeveestarinstaladoedeveseraúltimaversãodisponível.Senomomentodaexecuçãoestascondiçõesforemverdadeiras,nenhumaaçãoserátomada.Sealgumadelasforfalsa,aaçãocorretaseráexecutadautilizandoogerenciadordepacotesapt.
Nestecapítulo,vimoscomooAnsiblefuncionaecomosairdeumprovisionamentobaseadoemshellscriptparao
3.5CONCLUSÃO
36 3.5CONCLUSÃO
provisionamentobaseadonoAnsible.
ExploreadocumentaçãoemódulosdoAnsibleparaentendercomoabibliotecaquevemcomeleabordatarefasdeadministraçãodesistemascomoinstalaçãodepacotes,arquivosdeconfiguraçãoediferentesdistribuiçõesdesistemasoperacionais.
Procuremaisinformaçõessobreoutrossistemasdegerenciamentodeconfiguraçãojácitados:CFEngine(http://cfengine.com/),Puppet(https://puppetlabs.com/)eCHEF(https://www.chef.io/chef/).Entendacomoaarquiteturadelesinterferenasuaarquiteturadesistemasatualequalocomprometimentodetempoeestruturaestáenvolvidonaadoçãodeumsistemamaiscompletoecomplexo.
3.5CONCLUSÃO 37
tasks:-name:"Atualizapacoteseinstalanginx"apt:name=nginxstate=latestupdate_cache=yesinstall_recommends=yes
Estesarquivossãoasversõesfinaisdocapítuloanterior.Seguindoanossalista,coloqueiainstalaçãodePHP-FPMeMySQL.UmadasmaneirasdeutilizaroPHPcomnginxéutilizaraversãoFPMdoPHP.ÉumaimplementaçãoalternativadoprotocoloFastCGIquejátemumgerenciadordeprocessos.AinterfaceentreoservidorHTTPeointerpretadorseráfeitaporumUnixDomainSocketqueoPHP-FPMdisponibiliza.
NossapróximatarefaécriarumarquivodeconfiguraçãononginxparaumsitequesaibaintepretararquivoscomextensãoPHP.VouexplicarcomoissoficanonginxeposteriormentecomofaremosoAnsiblemontaroarquivodeconfiguraçãocorreto.Parafacilitar,voucriarodocumentrootnolugarondeoWordPressficaráinstalado,/opt/wordpress.
server{listen80;server_namebloglocalhost;
access_log/var/log/nginx/blog.access.log;
root/opt/wordpress;indexindex.htmlindex.htmindex.php;
location/{try_files$uri$uri//index.html;}
location~\.php${try_files$uri=404;fastcgi_passunix:/var/run/php5-fpm.sock;fastcgi_indexindex.php;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;includefastcgi_params;}}
40 4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS
Onginxpodeservirváriossites.Adefiniçãodecadaumdeleficaemumadiretivachamadaserver.NoUbuntu,aestruturadeconfiguraçãoficaem/etc/nginxeossitesdentrode/etc/nginx/sites-availablecomumlinkdentrode/etc/nginx/sites-enabledquandoativo.
Apróximatarefaétransportaraconfiguraçãodonossositedonginxparaestaestrutura.Vamoscriartrêstasks:criaro*/opt/wordpress,copiaraconfiguraçãoeativaronovosite.Parafacilitar,vamosremoverositedefaultereiniciaronginx.
Paratestarestespassos,vamoscolocarumataskquevaicriarumarquivosimpleschamadotest.phpcomocomandophp_info().NossotesteéabriroIP192.168.33.2 owsereverateladeinformaçõessobreoPHPimpressa.
<?phpphpinfo();?>
-hosts:allsudo:Trueuser:vagranttasks:-name:"Atualizapacoteseinstalanginx"apt:name=nginxstate=latestupdate_cache=yesinstall_recommends=yes
-name:"InstalaPHP-FPM"apt:name=php5-fpmstate=latestinstall_recommends=yes
-name:"InstalaMySQL"apt:name=mysql-serverstate=latestinstall_recommends=yes
-name:"Criadiretório/opt/wordpress"shell:mkdir-p/opt/wordpress
-name:"Copiaconfiguraçãodeblog.nginxpara/etc/nginx/sites-available/blog"copy:src=blog.nginxdest=/etc/nginx/sites-available/blog
-name:"Ativaosite"shell:ln-fs/etc/nginx/sites-available/blog/etc/nginx/sites-enabled/blog
4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS 41
-name:"Apagaositedefault"shell:rm-f/etc/nginx/sites-enabled/default
-name:"ReiniciaoNGINX"shell:servicenginxrestart
-name:"CriaumapaginadetestedoPHP"copy:src=test.phpdest=/opt/wordpress
Nesteplaybook,introduziumanovatask,chamadacopyquecopiaarquivoslocaisparaohost.Tambémvolteiautilizarataskshellcomoomodomaissimplesdeexecutarumatarefa.
Vamosexecutarofluxocompleto.Sesuamáquinavirtualestácriada,usevagrantdestroyparaapagá-laevagrantupparaexecutarnossainstalação.Abraseubrowsereaponteparahttp://192.168.33.2/test.php.
42 4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS
Figura4.1:test.php
PLAYRECAP
PLAYRECAP******************************************************blogvm:ok=10changed=9unreachable=0failed=0
SeotestefalharouoseuPLAYRECAPestiverdiferente,observeasaídadoprovisionamentoporerros.Asaídadotest.phppodeserumpoucodiferentedependendodeatualizaçõesdebibliotecasoucomponentesdosistemaoperacional.
VamoscolocaroWordPressnesteplaybookeconfigurá-locomoMySQLcomobancodedados.AsdistribuiçõesdeLinuxvêmcom
4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS 43
pacotesdoWordPress,masvamosbaixaraversãolatestdositeparailustrarcomoinstalarumsoftwarediretamentedocódigo-fonte.Sevocênavegaraté(https://wordpress.org)nasessãodedownloadsveráqueoúltimoreleasesempretemonomedelatest.
AURLhttps://wordpress.org/latest.tar.gzéaqueutilizaremosparafazerodownloaddoWordPress.TambémvamosutilizarmódulosdoAnsibleemsubstituiçãoàstarefasdecriarumlinksimbólicoeapagarumdiretório.
Introduzinovasdiretivas,comounarchive,url_get,módulosdoMySQLenovosusosdomódulofile.Temosoconceitodevariáveisvarsedetemplates.
Vamosexperimentaroplaybookantesdaexplicaçãocompleta.Sevocêestiverexecutandodiretamentedorepositório,podepularparadepoisdalistagem,poisvamosveralgumastasksespeciaisediscutircomorefatoraresteplaybook.
AlistagemaseguirinstalaoWordpresscompletoemumamáquinavirtual:
-hosts:allsudo:Trueuser:vagrantvars:mysql_root_password:rootmysql_wp_user:wordpressmysql_wp_password:wordpresswordpress_db_name:wordpress
tasks:-name:"Atualizapacoteseinstalanginx"apt:name=nginxstate=latestupdate_cache=yesinstall_recommends=yes
-name:"InstalaPHP-FPM"apt:name=php5-fpmstate=latestinstall_recommends=yes
-name:"InstalaMySQL"apt:name=mysql-serverstate=latestinstall_recommends=yes
44 4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS
-name:"InstalaExtensõesdeMySQLparaPHP"apt:name=php5-mysqlstate=latestinstall_recommends=yes
-name:"Instalabibliotecapython-mysqldb"apt:name=python-mysqldbstate=latestinstall_recommends=yes
-name:"Copiaconfiguraçãodeblog.nginxpara/etc/nginx/sites-available/blog"copy:src=blog.nginxdest=/etc/nginx/sites-available/blog
-name:"Apagaositedefault"file:path=/etc/nginx/sites-enabled/defaultstate=absent
-name:"Ativaosite"file:src=/etc/nginx/sites-available/blogdest=/etc/nginx/sites-enabled/blogstate=link
-name:"ReiniciaNGINX"service:name=nginxstate=restarted
-name:"Cria/opt/wordpress"file:dest=/opt/wordpressmode=755state=directoryowner=www-data
-name:"DownloaddoWordpress"get_url:url=https://wordpress.org/latest.tar.gzdest=/tmp/latest.tar.gz
-name:"Abrewordpressem/opt/wordpress"unarchive:src=/tmp/latest.tar.gzdest=/optcopy=no
-name:"Corrigepermissões"file:path=/opt/wordpressrecurse=yesowner=www-datagroup=www-data
-name:"IniciaMySQL"service:name=mysqlstate=startedenabled=true
-name:"Cria.my.cnf"template:src=my.cnf.j2dest=~/.my.cnfmode=0600
-name:"Criasenhaderootpararoot@mysql"mysql_user:name=rootpassword="{{mysql_root_password}}"check_implicit_admin=yespriv="*.*:ALL,GRANT"state=present
4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS 45
host="{{item}}"with_items:-"{{ansible_hostname}}"-127.0.0.1-*1-localhost
-name:"Criawordpressdatabase"mysql_db:name=wordpresslogin_user=rootlogin_password="{{mysql_root_password}}"state=present
-name:"Criausuáriowordpress"mysql_user:name="{{mysql_wp_user}}"password="{{mysql_wp_password}}"priv="{{wordpress_db_name}}".*:ALLcheck_implicit_admin=yeslogin_user=rootlogin_password="{{mysql_root_password}}"host="{{item}}"state=presentwith_items:-"{{ansible_hostname}}"-127.0.0.1-*1-localhost
Aponteseubrowserparahttp://192.168.33.2econfigureoWordPress.Estespassostambémpodemserautomatizadosmasficacomoexercício.
Esteplaybookcontémumasessãonovachamadavars.Estasvariáveispodemserusadasnopróprioplaybook,comonastasksdeMySQLouemarquivosexternoschamadostemplates.AsintaxeésimplesbaseadanoenginedetemplatesJinja2.
DetodososrecursosdoJinja2sóutilizaremosasubstituiçãodevariáveisentrechavesduplas,masalinguagempossuidesvioscondicionais,loopsemuitosrecursosparacriartemplatesinteligentes.Eurecomendoleradocumentação,mastambémmanterostemplatessimples:templatemodule(http://docs.ansible.com/template_module.html).
46 4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS
Algumastaskstêmumaconstruçãosemelhanteaoexemploaseguir:
-name:"Criausuáriowordpress"mysql_user:name="{{mysql_wp_user}}"password="{{mysql_wp_password}}"priv="{{wordpress_db_name}}".*:ALLcheck_implicit_admin=yeslogin_user=rootlogin_password="{{mysql_root_password}}"state=presenthost="{{item}}"with_items:-"{{ansible_hostname}}"-127.0.0.1-*1-localhost
Estaestruturapermitequepassemosumalistadeitensàqualataskseráaplicada.Estesitenspodemserlocaiscomwith_itemsouprovenientesdeumtemplateouvariável.Sãoúteisparamanterocódigomodularsemrepetiçõesdesnecessárias.Valearegrademanteroplaybooksimplessemutilizarestruturascomplexasparaoloopdastasks.Nestecaso,ositensnasessãowith_itemssãohostsutilizadosparaacriaçãodousuário.Osdireitos(GRANTS)dosusuáriosdoMySQLsãoespecíficosparacadahostouIPdeorigemdaconexão(omesmousuáriopodeterpermissãodecriartabelasapartirdolocalhost,massóler,sevindodeoutrohost).
AstasksdeMySQLdesteplaybookforamestruturadasassumindoqueainstalaçãodopacotedomysql_servercriaumusuáriorootsemsenha.
Paraqueotemplatetenhacomportamentoidempotenteemtodasasexecuções,seguimosarecomendaçãodadocumentaçãodoAnsible:instalamosummódulodePythonparaMySQL,criamosumasenhaparaousuáriorooteumarquivochamado.my.cnfquemoranodiretório/root.Existemoutrasmaneirasdetrabalharcomautenticaçãoetokensquesãomaisseguras,quevocêpode
4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS 47
pesquisarnadocumentaçãodoAnsible.
Oplaybookfuncionaepoderíamospararaíparainstalarumblog.Tudoestánamesmamáquina,vocêpodesubiredescerquantasvezesquiser,modificarparâmetrosatéficaracontentoeposteriormentefazerodeployemumamáquinadeprodução.
Vamosrefatoraresteplaybookparaintroduziraideiaderoles.Umplaybooktemroles(papéisemportuguês)queagemsobrepartesespecíficasdosistemaoperacional.Estamudançacontribuiparaamodularidadeereaproveitamentodecódigo:umrolepodeserutilizadoemváriosplaybooks.Arefatoraçãocontribuitambémparaalegibilidadedoplaybook.
Vamossepararnossoplaybookem5roles:common(sistemaoperacionaletarefasgenéricas),nginx,php,mysqlewordpress.Vamosseparartambémasvariáveisecriarummodelodevariáveisparaevitarquecoloquemossenhasetokensdeacessoporenganoemumrepositóriodecódigo.Amudançanãointroduztarefasdiferentes,apenasmudaaorganizaçãodosarquivos.Aárvoredediretóriosficaráassim:
|--.gitignore|--blog.yml|--roles||--common|||--tasks||||--main.yml|||--templates||--mysql|||--tasks||||--main.yml|||--templates||||--my.cnf.j2||--nginx|||--tasks||||--main.yml
REFATORAÇÃO
48 4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS
|||--templates||||--blog.nginx||--php|||--tasks||||--main.yml|||--templates||--wordpress|||--tasks||||--main.yml|||--templates|--Vagrantfile|--vars||--mysql.yml||--mysql.yml.dist
Agoratemosumdiretóriochamadorolescomcincosubdiretórios,cadaumrepresentandoumelementoquedescrevemosanteriormente.Dentrodecadadiretórioderoletemosossubdiretóriostasketemplates.Astasksmoramdentrodoarquivomain.yml.
Vocêpodedividiremquantosarquivosquiserparaorganizar,masnestemodelousaremosapenasomain.yml.Dentrodosubdiretóriotemplatesficamosarquivos.j2ouarquivosquevamoscopiarparaoservidor.
Odiretóriovarsnaraizdoprojetotemarquivoscomvariáveisqueserãoutilizadaspelosroles.Eucrieiomysql.yml.distqueéomodelodoarquivo.No.gitignorecoloqueipropositalmenteocaminhovars/mysql.ymlparaevitarqueminhascredenciaissejamversionadas.Vocêvaicopiaromysql.yml.distparamysql.ymldentrodomesmodiretórioecompletá-locomsuascredenciaisesenhas.
Oarquivoblog.ymlficoubemsimpleseagorautilizaadiretivaroles:
-hosts:allsudo:Trueuser:vagrantvars_files:
4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS 49
-vars/mysql.ymlroles:-common-mysql-php-nginx-wordpress
Oexercíciodestecapítuloémaisumarefatoração.Existeumacondiçãoquefazcomqueorolewordpressdependadorolecommon:acriaçãododiretório/opt/wordpress.
Vocêpoderiautilizarorolewordpressemoutroplaybookmasprecisariacriarestediretório.
Amelhorformaderemoverestadependênciaécriarumavariávelparaodiretóriodestino,substituirtodasasocorrênciasde"/opt/wordpress"porelaeemcadarolecriarodiretóriocasoelenãoexista.
Nestecapítulo,vimosnovastasksdoAnsibleeumexemplocompletodecomofazerodeploydeumaaplicaçãoemumamáquinavirtual.SevocêimaginarquenolugardoWordPressvocêacessouorepositóriodoseucódigo,podeverquenãoédifícilcriarumambienteportávelparadesenvolvimentoeaestruturaparadeploycomoquevimosatéaqui.
Éinteressantenotarqueaprogressãododesenvolvimentodoplaybookésemelhanteaoprocessoqueusamosparaprogramar.
Atérefatoraçãofizemose,comoosarquivosestãoestruturados,poderíamosterversionadocomGitououtrocontroledeversão.Vocêpoderiaterversõesdesoftwareoumáquinassendoexecutadasparatestesderegressãoouperformancerapidamente.
CONCLUSÃO
50 4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS
Aúltimarefatoraçãoquefizemosorganizouoplaybookemrolesquepodemserreaproveitadosemoutrosplaybooks,assimcomooscomponentesqueoAnsibleprovêcomomóduloseplaybooksdoAnsibleGalaxy(http://galaxy.ansible.com).
4.1EXPANDINDONOSSOPLAYBOOK─UMBLOGCOMWORDPRESS 51
CAPÍTULO5
Estecapítuloéousadomassimples:vamosaproveitaroquevimosanteriormenteparamelhorarnossoplaybookeusaroVagrantparacriarumaestruturaquetemmaisdeumamáquina.Antesvamosentenderumpoucomaisatécnicadeproxyreversocomonginxecomoestepadrãodearquiteturapodeserusadoparadiferentesinterpretadoreselinguagens.
OexemplodestecapítuloedoanteriorservemparaoutrasaplicaçõesqueutilizamPHPeMySQL.OqueprecisariasermodificadoparainstalarumCMS(ContentManagementSystem)comooJoomla(http://www.joomla.org/)?Eparaoutraslinguagenseplataformas?
Nestescasos,devemosvoltaraatençãoaopassodeconfiguração:sedependedeumarquivocomosdadosdasmáquinasinstaladas,seprecisadepassoscompletadospelobrowserousepodemosfornecerumarquivocomasconfiguraçõescorretas,semintervençãomanual.
Amaneiracomoconfiguramosonginxéchamadadeproxy
PROXYREVERSOEWORDPRESSEMDUASMÁQUINAS
5.1NGINXEPROXYREVERSO
52 PROXYREVERSOEWORDPRESSEMDUASMÁQUINAS
reverso.SeemvezdeexecutaroPHP-FPMumaaplicaçãoemPythonestivesseouvindoemumaportalocal,nãomudariamuitooplaybook.
Vamosconstruirumaaplicaçãosimplesqueouvenaporta10000erespondeumaAPIdeecho:elarecebeumPOSTcomoparâmetromsgeimprimeovalordevolta.SeométodochamadoforGET,umformuláriocomumacaixadetextoaparecerá.
Éumexemplosimplesmasdemonstraoconceitodeproxyreversoedeoutrointerpretador.Esteexemploestánodiretóriopython-nginxdorepositóriocomonomedehttp_server.py:
#!/usr/bin/python
importSimpleHTTPServerimportSocketServerimportcgiimportsocket
PORT=10000
classReuseAddrTCPServer(SocketServer.TCPServer):defserver_bind(self):self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)self.socket.bind(self.server_address)
classServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):defdo_GET(self):
self.wfile.write("<html><body><formaction='/'method=POST>")self.wfile.write("<textareaname=msgrows='10'cols='100'></textarea>")self.wfile.write("<br><inputtype='submit'name='submit'>")self.wfile.write("</form></body></html>")return
defdo_POST(self):self.send_response(200)self.end_headers()form=cgi.FieldStorage(
5.1NGINXEPROXYREVERSO 53
fp=self.rfile,headers=self.headers,environ={'REQUEST_METHOD':'POST','CONTENT_TYPE':self.headers['Content-Type'],})
forfieldinform.keys():self.wfile.write('\t%s=%s\n'%(field,form[field].value))
return
ReuseAddrTCPServer(("",PORT),ServerHandler).serve_forever()
EstecódigocriaumservidorHTTPcomasbibliotecaspadrãodoPython,ouvenaporta10000esórespondearequestsHTTPdotipoGETePOST.Paratestá-lo,abradoisterminais;emumdelesexecuteocomando:
$pythonhttp_server.py
Nooutro,ocomandocurlparamandarumrequestPOSTparanossoservidor:
$curl-XPOST-d"msg=aaaa&oi=123"http://localhost:10000
Noterminalemqueoservidorestásendoexecutado,asaídadeveserparecidacom:
$curl-XPOST-d"msg=aaaa&oi=123"http://localhost:10000msg=aaaaoi=123$
Oservidornãotemomínimonecessárioparaumaboaaplicaçãowebcomologs,monitoração,arquivodeconfiguraçãoparadadoscomoaportaeoendereço,masserviráparaopropósitodedemonstraramudançaemnossoplaybookparautilizarumaaplicaçãoPythoneonginxcomoproxyreverso.
OVagrantfiledesteexemploéparecidocomodocapítuloanterior:apenasumamáquinavirtualserácriadaeoarquivo
54 5.1NGINXEPROXYREVERSO
web.ymlseráexecutado.Dentrodestamáquina,teremosonginx,Pythonenossoprograma.Eleseráexecutadodentrodeumprogramachamadosupervisord.
Osupervisordéumprogramaquecuidadaexecuçãodeoutrosprogramas:redirecionaasaídapadrãoparaumarquivodelogemonitorasuaexecuçãoparareiniciarcasooscriptparederesponder.
Dentrodestamáquina,nossohttp_server.pyseráexecutadoevaiouvirnaporta10000delocalhost.
OnginxteráumsitequevaiouvirnoIP192.168.33.10equefaráorequestparaesteserviçodebackend.Elevaigerenciarasconexõesvindasdeusuárioseasrespostasvindasdobackend.
Esteéoweb.yml:
-hosts:allsudo:Trueuser:vagrantvars_files:-vars/mysql.ymlroles:-common-nginx-app
Paraorganizarodeploydaaplicação,crieiumrolechamadoapp.Esterolecriaumdiretório/opt/app,copiaohttp_server.pyparalá,configuraosupervisordeiniciaaaplicação.Esteéoarquivotasks/main.ymldoroleapp
-name:"Criaodiretório/opt/appseelenãoexiste"file:dest=/opt/appmode=755state=directoryowner=www-data
-name:"Copiaoarquivohttp_server.pypara/opt/app"copy:src=http_server.pydest=/opt/app/
-name:"Criaaentradaappparaosupervisord"template:src=app.confdest=/etc/supervisor/conf.d/
5.1NGINXEPROXYREVERSO 55
-name:"Reiniciasupervisord"service:name=supervisorstate=restarted
-name:"Iniciaaaplicação"supervisorctl:name=appstate=started
Norolecommon,instalamosopacotesupervisordparasuportaratasksupervisorctleocontroledaaplicação.Nospassosanterioresimplementamosoquejádiscutimos.
Aconfiguraçãodonginxmudouumpouco:
server{listen80;server_nameapplocalhost;access_log/var/log/nginx/app.access.log;root/opt/app;indexindex.htmlindex.htmindex.php;
location/{proxy_passhttp://127.0.0.1:10000/;proxy_redirectoff;proxy_set_headerHost$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;
client_max_body_size5M;client_body_buffer_size5M;
proxy_connect_timeout30;proxy_send_timeout30;proxy_read_timeout30;
proxy_buffer_size16k;proxy_buffers16128k;proxy_busy_buffers_size512k;proxy_temp_file_write_size512k;}}
Subaamáquinacomvagrantupeacessehttp://192/168.33.10emseubrowser.Digitealgoecliqueemsubmit.Repitaostestescomocurlnoterminal:
$curl-vvv-XPOST-d"msg=oie"http://192.168.33.10 /
56 5.1NGINXEPROXYREVERSO
Entrenamáquinavirtualcomvagrantsshetesteoserviçolocalmente:
$curl-vvv-XPOST-d"msg=oie"http://localhost:10000/
Oresultadodevesersemelhante,mascomosheadersdabibliotecaSimpleHTTPServerdoPython.Nesteteste,vocêacessouobackenddiretamente,antesdonginx.Analiseoslogsem/var/log/nginx/eologdaaplicaçãoem/var/log/app.log,redirecionadopelosupervisord.
Nãoéoobjetivofazerumaanálisedasopçõesdeconfiguraçãodonginx,bastadizerqueadiretivaproxy_passredirecionaotrafegoquecheganaURI/paraobackend.
AsopçõesemseguidasãorelacionadasaHTTPHEADERSquedevemserrepassadosparaaaplicaçãodebackendeotamanhodosbuffersdisponíveis.Comonginxépossívelfazerproxy,loadbalancingecachealémdeservirpáginasHTTP.Procuremaisinformaçõesem(http://nginx.org/en/docs/).
OmotivodestedesviofoitécnicaqueutilizamosparafastcgieHTTPemaplicaçõesdebackend.
Oobjetivoagoraésimples:queroquemeubancodedadosfiqueemumamáquinaeoWordPressemoutra.QuerorodaresteambientelocalmentecomoVagrant,masqueroqueoplaybookestejaprontoparaprovisionaremduasmáquinasexternas.
VamosusaroVagrantfileparacriarasmáquinaseaplicaroprovisionamentocorretoemcadauma.DividiremosnossosrolesparaindicaroquepertenceaobancodedadoseoquepertenceaowebservercomWordPress.AdocumentaçãodoVagrantem(http://docs.vagrantup.com/v2/multi-machine/)sobreissoébem
5.2WORDPRESSEMDUASMÁQUINAS
5.2WORDPRESSEMDUASMÁQUINAS 57
clara.AdaptandoaonossoVagrantfile,ficaassim:
#-*-mode:ruby-*-#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
Vagrant.configure(VAGRANTFILE_API_VERSION)do|config|
config.vm.define"web"do|webvm|webvm.vm.box="ubuntu/trusty64"webvm.vm.network:private_network,ip:"192.168.33.2 "
webvm.vm.provision"ansible"do|ansible|ansible.playbook="blog.yml"ansible.verbose="vvv"ansible.groups={"web"=>["192.168.33.2 "],"db"=>["192.168.33.2 "],}ansible.limit="web"endend
config.vm.define"db"do|dbvm|dbvm.vm.box="ubuntu/trusty64"dbvm.vm.network:private_network,ip:"192.168.33.2 "
dbvm.vm.provision"ansible"do|ansible|ansible.playbook="blog.yml"ansible.verbose="vvv"ansible.groups={"web"=>["192.168.33.2 "],"db"=>["192.168.33.2 "],}ansible.limit="db"endend
config.vm.provider"virtualbox"do|v|v.customize["modifyvm",:id,"--memory","1024"]end
end
AsmudançasnoVagrantfileforamsimples:duassessõespara
58 5.2WORDPRESSEMDUASMÁQUINAS
criarmáquinasvirtuaisdistintas.Comooscomponentesdestaarquiteturasãoindependentes,umamáquinawebeumadebancodedados,crieidoisgruposeprogramaticamenteuseioVagrantparaindicaraoAnsibleoquecadaumarepresenta.NomomentodeconfiguraroWordPresspelainterfaceweb,coloqueoIP192.168.33.2nocampohostname.Éaúnicamudançaemrelaçãoaosetupanterior.
ApósaconfiguraçãoeoprimeiropostnoWordPress,usevagrantsshdbevagrantsshwebparainspecionarasduasmáquinas.Emumsetupcommaisdeumamáquinao,Vagrantusaonomequedemosparaconfig.definecomoidentificadorparaseuscomandos.Paraprovisionarnovamentesóamáquinadebanco,vagrantprovisiondb;paraseconectaràmáquinadefrontendvagrantsshweb;omesmoparadestroy,halteup.
PoderíamosautomatizartotalmenteaconfiguraçãodoWordPresssemutilizarainterfaceweb,comtemplatesdearquivosnoformatocorretocomasvariáveis.Éumatarefarelativamentesimples,sóprecisadeumpoucodeengenhariareversa:entrenamaquinadefrontendetransformeowp-config.phpemumtemplate.Paraemularofinaldaconfiguração,vocêdeveolharnobancodedadoscriadopeloWordPressepreencherseubancodedadosdeacordo.ExistemplaybooksparaWordPressbemcompletosqueoferecemestaopção.
PreciseimodificarumpoucoorolemysqlparaqueeletrocasseoarquivodeconfiguraçãodoMySQLporumqueouçaemtodasasinterfacesderededamáquina(originalmente,oMySQLsóouvenainterface127.0.0.1)etambémumacorreçãoparaqueousuárioWordPresstenhapermissãoparaconectardeoutrasmáquinas.
PoderíamosterusadooAnsibleparacorrigirapenasestalinhanoarquivooriginalmasminharecomendaçãoéversionarseusarquivosdeconfiguraçãodamaneiraqueprecisamsernofinale
5.2WORDPRESSEMDUASMÁQUINAS 59
variarparâmetrosutilizandotemplates.Destaforma,dadoscomoIPs,senhas,tokenseatéconteúdodebancodedadossãofacilmenteidentificadoscasooutrapessoapreciseutilizarseuplaybook.
Aoexecutarvagrantup,osdoisblocosdecódigosãoexecutadosemsériecomosrespectivosprovisionadores.Oplaybookmudoutambém:temduassessõesmarcadaspeloatributohost.Sefôssemosinstalaremduasmáquinasvirtuaisemprovedoresexternos,teríamosquepreencherumarquivohosts.inicomdoisgruposcomonoexemploaseguir:
[web]IPdaVPS1[db]IPdaVPS2
Executaríamos,portanto:
$ansible-playbook-ihosts.iniblog.yml
SeamáquinaestiverconfiguradacorretamenteparaaceitarconexãoutilizandochaveSSHsemsenha,oAnsibleconectaráemcadaumadasmáquinaseexecutaráosplaybooks.
Oexercícioqueproponhoantesdeprosseguiréescolherumprovedordeinfraestruturaeinstalaresteplaybookemduasmáquinasvirtuaisforadasuamáquinalocal.Asinformaçõesatéaquisãosuficientes,vocêdevecriarasduasmáquinasmanualmenteecriarumhosts.inicomosendereçosIPscorretos.
ParafazerissonaDigitalOcean,sigaospassosdoprimeirocapítuloparacriarumaconta,váaopainelecrieumachaveSSH.ADigitalOceantemumbompreçoentreprovedoresdemáquinasvirtuaisenãoédifícilconseguirumcupomdedescontos.Procureo
5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS.
60 5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS.
itemyoursettingsnoseuprofileeescolhaotabsecurity(https://cloud.digitalocean.com/settings/security).NesteitemprocureSSHKeysecrieumanovachave.CasotenhadúvidasparacriarumachaveSSH,consulteomesmocapítulo.
Figura5.1:PaineldecontroledaDigitalOcean
Comachavecriada,vamosumfazerumplaybookquecriaduasmáquinascomUbuntu14.04einstalawebedbemcadaumadelasusandooAnsible.OAnsibletemmódulosqueinteragemcomprovedoresdeserviçousandosuasAPIs.
ADigitalOceanlançouumanovaAPIemabrilde2015,portantoseumóduloaindanãohaviasidoatualizadonoAnsibleatéadatadeediçãodestelivro.Vouindicarasduasmaneirasdeacessá-la,masoexemploutilizaráaV1(versão1)daAPI.
NopaineldaDigitalOceanváatéoitemAPI:
5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS. 61
Figura5.2:APIdaDigitalOcean
Paraaversão1.0daAPI,cliquenolinkViewAPIv1.ApareceráumatelaparaacriaçãodeumpardeClientIDeApyKey.CliqueemGenerateNewKeyecopieosvaloresapresentados:
Figura5.3:APIversão1daDigitalOcean
Estesdoisvaloresserãoimportantesparaoprovisionamento.Exporteosdoisemvariáveisdeambiente:
$exportDO_CLIENT_ID=<seuclientid>$exportDO_API_KEY=<suaapikey.
Vamostestarcomcurl:
$curl"https://api.digitalocean.com/v1/sizes/
62 5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS.
?client_id=$DO_CLIENT_ID&api_key=$DO_API_KEY"|python-m"json.tool"
DeveretornarumjsoncomtodosostamanhosdemáquinasvirtuaisdaAPI.OmódulodaDigitalOceandoAnsibledependedeIDsderegião,SSHkey,imagemetamanhoparaprovisionar.EufizumpequenoscriptparaencontrarosIDsfacilmenteusandoasvariáveisdeambientequeforamdeclaradas,chamadodo_api_v1.py:
"""dependencias:sudopipinstalldopypyopensslndg-httpsclientpyasn1"""
importosfromdopy.managerimportDoManagerimporturllib3.contrib.pyopensslurllib3.contrib.pyopenssl.inject_into_urllib3()
cliend_id=os.getenv("DO_CLIENT_ID")api_key=os.getenv("DO_API_KEY")
do=DoManager(cliend_id,api_key)
keys=do.all_ssh_keys()print"Nomedachavessh\tid"forkeyinkeys:print"%s\t%d"%(key["name"],key["id"])
print"Nomedaimagem\tid"imgs=do.all_images()forimginimgs:ifimg["slug"]=="ubuntu-14-04-x64":print"%s\t%d"%(img["name"],img["id"])
print"Nomedaregiao\tid"regions=do.all_regions()forregioninregions:ifregion["slug"]=="nyc2":print"%s\t%d"%(region["slug"],region["id"])
print"Nomedotamanho\tid"sizes=do.sizes()forsizeinsizes:
5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS. 63
ifsize["slug"]=="512mb":print"%s\t%d"%(size["slug"],size["id"])
ParaoAnsibleprovisionarnaDigitalOcean,precisamosdeummóduloPythonchamadodopy,alémdebibliotecasauxiliaresparaoscriptdebuscanaAPI:
$sudopipinstalldopypyopensslndg-httpsclientpyasn1
Executeoscriptparaconferirosdadosqueserãocompletadosnoplaybook.Aversãoquecoloqueinolivroenorepositórioestáatualizadamasosvalorespodemmudar.
$pythondo_api_v1.py
ComaAPIeachaveSSHconfigurados,vamosverumexemploparacriaredestruirumamáquinavirtualusandooAnsible.Criamosumarquivochamadodo_hosts.ini:
[local]localhost
VamosusarummódulocoredoAnsibleparacriarumamáquina:
-hosts:allconnection:localuser:ubuntu
tasks:-name:"CriaumamáquinanaDigitalOcean"digital_ocean:state=presentcommand=dropletname=testevmsize_id=66region_id=4image_id=9ssh_key_ids= 44virtio=yesregister:testvm
-name:"Iddamáquina"debug:msg="{{testvm.droplet.id}}"
64 5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS.
-name:"IPdamáquina"debug:msg="{{testvm.droplet.ip_address}}"
Osvalores66,4,9 indicamrespectivamentetamanhodamáquina,regiãoesistemaoperacional.Ovalordessh_key_idsdeveseroquevemdasuachamadadaAPI.EstesdadosindicamqueoAnsibledevecriarumamáquinanaregiãonyc2,tamanhode512mb,sistemaoperacionalUbuntu14.0464bitseincluiraminhachaveSSHdeid 44 diretivadebugvaiimprimirumjsoncomovalordoatributoregistradonavariáveltestvm.Anoteestevalorparapreencheroplaybookderemoçãodemáquina.
Depoisdecriadaamáquina,verifiquenoseupainelseelafoirealmentecriadaeseconecteparatestar.Umdosparâmetrosimpressosdeveseratualizadonoplaybookremove_maquina.ymlnoatributo´id`pararemoveramáquina:
-hosts:allconnection:localuser:ubuntu
tasks:-name:"RemoveumamáquinanaDigitalOcean"digital_ocean:state=deletedid=<iddamaquinacriada>command=dropletname=testevm
Paraexecutaresteplaybook:
$ansible-playbook-v-ido_hosts.iniremove_maquina.yml
Sabemoscriareremoverumamáquinaprogramaticamente.Sejuntarmoscomosplaybooksdb.ymleweb.yml,teremosoplaybookparainstalarnossoWordPresscomduasmáquinasaseguir:
-hosts:allconnection:localuser:ubuntu
tasks:
5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS. 65
-name:"Criaamaquinaweb"digital_ocean:state=presentcommand=dropletname=wordpress-websize_id={{do_size_id}}region_id={{do_region_id}}image_id={{do_image_id}}ssh_key_ids={{do_ssh_key_ids}}virtio=yesregister:web
-name:"Criaamaquinadb"digital_ocean:state=presentcommand=dropletname=wordpress-dbsize_id={{do_size_id}}region_id={{do_region_id}}image_id={{do_image_id}}ssh_key_ids={{do_ssh_key_ids}}virtio=yesregister:db
-name:"Esperaconfirmaçãoantesdeseguir,verificandoaporta22"wait_for:port=22host="{{web.droplet.ip_address}}"search_regex=OpenSSHdelay=30
-name:"Esperaconfirmaçãoantesdeseguir,verificandoaporta22"wait_for:port=22host="{{db.droplet.ip_address}}"search_regex=OpenSSHdelay=30
-name:"Iddamáquinaweb"debug:msg="{{web.droplet.id}}"
-name:"IPdamáquinaweb"debug:msg="{{web.droplet.ip_address}}"
-name:"Iddamáquinadb"debug:msg="{{db.droplet.id}}"
-name:"IPdamáquinadb"debug:msg="{{db.droplet.ip_address}}"
-name:"Adicionahostaogrupoinstanciasweb"add_host:hostname={{web.droplet.ip_address}}groupname=instancias_web
66 5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS.
-name:"Adicionahostaogrupoinstanciasdb"add_host:hostname={{db.droplet.ip_address}}groupname=instancias_db
-hosts:instancias_websudo:Trueuser:rootroles:-common-php-nginx-wordpress
-hosts:instancias_dbsudo:Trueuser:vagrantvars_files:-vars/mysql.ymlroles:-common-mysql
ParasepararosdadosgeradospelaAPI,crieiumdiretóriochamadogroup_varseumarquivochamadoalldentrodele.EstediretórioélidopeloAnsibleautomaticamenteecadaarquivocontémvariáveisaplicadasagruposespecíficos.Oarquivoallcontémvariáveisaplicadasatodososgruposdehosts.
do_size_id:66do_region_id:4do_image_id:9do_ssh_key_ids:<iddasuachavessh>
Acriaçãodemáquinasvirtuaispoderiatersidoseparadaemumrolemaspreferideixá-laassimparademonstrarasequênciadeoperações.NãoéumaoperaçãoinstantâneaeaAPIpodedemorararesponder.Paragarantiracriaçãodemáquinasíntegras,coloqueiumachecagemextradaporta22TCP.
Paracriarasduasmáquinaseinstalarosrolescorretamente,execute:
$exportANSIBLE_HOST_KEY_CHECKING=False$ansible-playbook-v-ido_hosts.iniwordpress_do.yml
5.3INSTALANDOSEUWORDPRESSEMMÁQUINASVIRTUAIS. 67
OprocessodeconfiguraçãodoWordPresscontinuaomesmo:pelainterfacewebconfigureoIPdamáquinaefaçaumpost.Emalgunspassos,aAPIpoderespondercomtimeoutsouerrosdeSSH.
ComoaremoçãodasmáquinasenvolvemseusIDs,eurecomendofazê-lopelopaineldaDigitalOceaneapagarasentradasdosIPscriadosdoarquivo~/.ssh/known_hosts.
TantoaAPIdaDigitalOceanquantoomódulodoAnsiblesãonovoseatéadatadaediçãodestelivronãohaviamsidolançadosoficialmente.VamosvercomocriarumtokendanovaAPI,eposteriormenteadocumentaçãodoAnsibledeveseratualizadaparapermitirousodanovaversão.Enquantoissonãoacontece,recomendoqueuseav1daAPIcomoexplicadoanteriormente.
Natelaprincipal,vamoscriarumtoken.AdiferençaéqueoCLIENT_IDnãoserámaisnecessário.
Figura5.4:APIdaDigitalOcean
CliqueemGenerateNewTokenaoladodePersonalAccessTokens.Apróximatelateráumespaçoparadigitaronomedestetokeneselecionaroescopo.MantenhaReadeWritemarcadospois
5.4DIGITALOCEANAPIV2
68 5.4DIGITALOCEANAPIV2
precisaremosdepermissõesdeescritaeleitura.
Figura5.5:CriaçãodoTOKENdaAPIdaDigitalOceanv2
Quandogerarotoken,serálevadoparaoutratelacomoresultado.Guardeseutokenemumlocalseguro.Elenãoaparecerámaisnestatelaporquestõesdesegurança.Oacessoqueeleprovêéomesmodeumasenhaquepodecriar,removerecoletardetalhesdemáquinas.Certifique-sedequeelenãoseráinseridoacidentalmenteemnenhumrepositóriodecódigopúblicoouprivado.
5.4DIGITALOCEANAPIV2 69
Figura5.6:Tokencriado
Paratestar,exporteovalordoseutokennavariáveltokeneuseocurl:
$exportTOKEN=<seutokendaapi>$curl-XGET"https://api.digitalocean.com/v2/droplets"-H"Authorization:Bearer$TOKEN"
SevocêjátemalgumamáquinanaDigitalOcean,eladeveaparecernaresposta,casocontrárioarespostadeveservazia.Setiverdúvida,aumenteoníveldeverbosidadedocurladicionandooparâmetro-vvvantesdoparâmetro-X.
ComaevoluçãodestemódulonoAnsible,algumasmudançasdevemacontecernadocumentação.AmaisimportanteseráqueemvezdeutilizarmosIDsvamosutilizaroqueéchamadodeSLUG,umnomecompactoparaorecurso,porexemplo512mbnolugarde66.
Nesteexemplo,asmáquinaseramindependentes.Eseprecisássemosinstalarumsoftwarequefuncionerealmenteemcluster,equedependadeoutroselementosdestecluster?Nopróximocapítulovamosmontarumplaybookparainstalare
5.5CONCLUSÃO
70 5.5CONCLUSÃO
executaroCassandralocalmenteenaAWSeesseexercícioseráútil.
5.5CONCLUSÃO 71
CAPÍTULO6
VamoscriarumplaybookparaobancodedadosnãorelacionalCassandra.OCassandrausaJAVA,temumprotocolodecomunicaçãoentreoclusterporTCP/IPeprecisaconhecerseusvizinhos.AarquiteturadoCassandraéparecidacomoutrossistemasdistribuídos.AdiscussãoeconstruçãodesteplaybookeaexecuçãolocalenaAWSvainosajudarapensarmelhoremcomoorganizarnossasaplicações.
Nesteplaybook,vamosutilizarrolesprontosparaainstalaçãodoJAVAeorepositóriodaDatastaxparainstalaroCassandra.Seráumclusterlocaldetrêsmáquinasvirtuais,oqueérealmentelimitadoparaoCassandra.Paraexperimentá-lo,vocêdeveprocurarmáquinascompelomenos4GBdememóriaeduasvcpus.
OCassandraéumbancodedadosdistribuídoque,entreoutrastécnicasdesistemasdistribuídos,utilizaumprotocolochamadoGossipparadetecçãodefalhaseatualizaçãodoestadodocluster.Esteprotocoloépeer-to-peer(P2P),oquesignificaquecadanódeveconhecertodosoupelomenosumapartedosnóscomosquaisvaisecomunicar.
Existecomunicaçãoetrocadeinformaçõesentreosnósmesmoquandonãotemosconsultasouescritasnobancodedados.UmadascondiçõescomqueoGossipajudaénoHintedHandOff,aguardadoestadodeumaescritaporumnóequepodeserentregueaonódedestinoassimqueelevoltarouserremanejadoparaoutro.
CASSANDRAEEC2
72 CASSANDRAEEC2
VamosestruturarumroleparaainstalaçãodoCassandraqueéflexívelosuficienteparaconhecertodososnósqueestásubindoeproveraconfiguraçãocorretaparaoclusterdeacordocomainfraestruturaescolhida.Estedadoéimportantepoisosnósdoclusterdevemterasinformaçõesdeseuambientedisponível.
OCassandratemumcomponentecomestaresponsabilidade,chamadoSnitch.Elecontémalógicaparalocalizareclassificarosnósparaqueaconsistênciaeparticionamentoindicadosemníveismaisaltosdosistemasejarespeitada.VamostornaraopçãodeSnitchflexível.
NaconfiguraçãodoCassandra,precisamosenviaroIPemqueonódeveouvirlocalmenteeosIPsdosvizinhos,quechamaremosdeseeds.Vamosusarorestodaconfiguraçãosemmudanças,massevocêforexecutaroCassandranaAWSououtroprovedordeinfraestrutura,teremosquemudaroSnitch(vejamaissobreosSnitchsdisponíveisnadocumentação(http://docs.datastax.com/en/cassandra/2.0/cassandra/architecture/architectureSnitchesAbout_c.html)).
OSnitchéumcomponentedoCassandraquedescobreorganizaainfraestruturaemqueosnóssãoinstalados,parasaberemquerackedatacenterasréplicasdosdadosserãoarmazenadas.Parainfraestruturaslocaisedatacenterstradicionais,podemosusaroDynamicSnitchingouoSimpleSnitch.ParaaAWSusaremosoEC2Snitch.
ÉoSnitchquedescobreoutemasdefiniçõesdedatacenter,rackeredesqueserãoaproveitadasnadefiniçãodaestratégiadereplicaçãodokeyspace,alémdoprotocoloGossip.EmarquiteturasemqueamáquinanãopossuioIPválidoemumadesuasinterfaces
6.1VAGRANTECASSANDRA
6.1VAGRANTECASSANDRA 73
(comonaAWS),acomunicaçãoentredatacenterséfeitaporoutroscanaiseoSnitchéresponsávelporestasinformações.VamosmudarestaconfiguraçãoquandoinstalarmosomesmoclusternaAWS.
ParainstalaroCassandra,vamosprecisardeumroleparainstalarJavaquenãosejaoOpenJDK.Euescolhiesterole(https://github.com/vrischmann/ansible-role-java)porsercompletoesimplesdeutilizar.OroledeinstalaçãodeCassandraémeuealémdissoinstalosuporteaPythonnasmáquinas,poiséoqueeucostumousar.AestruturadediretóriosseráparecidacomaúltimaversãodoplaybookdoWordPress.
OVagrantfiledesteplaybookusaRubyparafacilitarnossotrabalhodedeploy:
#-*-mode:ruby-*-#vi:setft=ruby:
VAGRANTFILE_API_VERSION="2"
#Preparaosdadosparatodososnodesdoclusternodes=['192.168.33.100','192.168.33.101','192.168.33.102']cluster_name="VagrantCluster"
servers=[]nodes.each_with_indexdo|node,idx|servers<<{'hostname'=>'node'+idx.to_s,'ip'=>node,'seeds'=>nodes.join(","),'cluster_name'=>cluster_name,}end
#Paracadaitemdalistadeservidores(servers)umavmVagrant.configure(VAGRANTFILE_API_VERSION)do|config|servers.eachdo|server|config.vm.defineserver['hostname']do|cfg|cfg.vm.box="ubuntu/trusty64"cfg.vm.host_name=server['name']cfg.vm.network:private_network,ip:server['ip']cfg.vm.provision"ansible"do|ansible|ansible.extra_vars={
74 6.1VAGRANTECASSANDRA
cluster_name:server["cluster_name"],seeds:server["seeds"],listen_address:server['ip'],rpc_address:server['ip']}ansible.verbose='vvvv'ansible.playbook="cassandra.yml"endcfg.vm.provider"virtualbox"do|v|v.customize["modifyvm",:id,"--memory","2048"]endendendend
Alistanodescontém3endereçosIP,combasenosquaisvamosinstruiroVagrantacriareprovisionarestesnós.Paracadamáquina,vamospassarasvariáveisqueoroledeinstalaçãodoCassandravaiutilizarparaconfigurarcadanó.
Oatributoextra_varsdoAnsibleaceitaumdicionário(HashemRuby)comvaloresqueserãorepassadoscomovariáveisdoAnsible.Oblocodentrodeservers.eachrepeteoprocessodecriaçãoeprovisionamentodemáquinasvirtuaisparacadaitemdeservers.
Apreparaçãoinicialdalistaserversusanodesparacriarnomesparacadaumdoselementosdocluster(node0,node1enode2),dáumendereçoIPparacadanóecriaoparâmetroseedscomtodososIPs,alémdonomedocluster.
EstaéaconfiguraçãomínimaparaoCassandra,entreascentenasdeitensquepodemsermodificados.Comisso,criamosumclusterde3máquinas.NãoinstaleioopscenternemoutrasferramentasnecessáriasparaexecutaroCassandraemambientedeprodução,apenasobancodedados.
Estaconfiguraçãoficapesadaemumcomputadornormal,poisasmáquinasprecisamdepelomenos2GBdememóriaparaevitar
6.1VAGRANTECASSANDRA 75
queokerneldoLinuxrodeoOOMKiller(outofmemorykiller).Poderíamoshabilitaroswapmassairiadoescopodoprovisionamento.Éumexercícioqueeusugiro:melhoraraconfiguraçãodestasmáquinasvirtuaisecriarastasksnoplaybook.
Otesteparacadanóésimples:vagrantsshnode[0..2]eexecuteocomandonodetoolstatusparaveroestadodonó.Esteplaybookcompletopodeserencontradonorepositóriodolivro.
ParainstalaresteclusterforadoVagrantvamosprecisardasvariáveisparacadanó.Vejacomoficaoinventáriohosts.iniparaestecaso,assumindoquecadaumdosIPséumamaquinaprontaecomoSSHconfiguradoparaautenticarsemsenhaporchavepública:
[cassandra]192.168.33.100cluster_name="SuperCluster"seeds="192.168.33.100,192.168.33.101,192.168.33.102"listen_address="192.168.33.100"rpc_address="192.168.33.100"192.168.33.101cluster_name="SuperCluster"seeds="192.168.33.100,192.168.33.101,192.168.33.102"listen_address="192.168.33.101"rpc_address="192.168.33.101"192.168.33.102cluster_name="SuperCluster"seeds="192.168.33.100,192.168.33.101,192.168.33.102"listen_address="192.168.33.102"rpc_address="192.168.33.102"
ParaexecutaroAnsiblenastrêsmáquinas:
ansible-playbook-ihosts.inicassandra.yml
Vocêpoderiagerardinamicamenteestearquivovindodeumsistemadegerenciamentodemáquinasoudeconfiguração.OAnsiblechamaissodedynamicinventoryeéumdosprincipaisrecursosdoAnsibleTower,asoluçãocentralizadadegerenciamentoqueoAnsibleoferece.
ExistempluginsparagerenciaroinventáriodinâmicosemusarAnsibleTower.EscolhiaAWSparatestaresteplaybook.Vamosinstalar3máquinasparaoCassandra,masantesvamosexaminar
76 6.1VAGRANTECASSANDRA
somenteoprovisionamento.
OAnsibletemocódigoemódulosnecessáriosparautilizaraAPIdaAWS.Mascomoprovisionadoreledevemanterumconjuntodeinformaçõessobreoinventáriodemáquinasqueestamosutilizando.AAWSfazissodoladodaAPIeprecisamosdemeiosderecuperarestainformaçãoemumformatoqueoAnsiblecompreenda.
PrecisamosdoplugindeinventáriodinâmicoparaEC2instalado.EstepluginnadamaiséqueumprogramaquefacilitaacomunicaçãocomaAPIdoEC2esubstituiohosts.ini.Paraqueelefuncione,vocêvaiprecisardeumacontanaAWS,credenciais(AWS_ACCESS_KEY_IDeAWS_SECRET_ACCESS_KEY)eachavepública/privadadeSSHconfigurada.AscredenciaissãoencontradasnomenuIAMdopaineldaAWS.VamosseguirasinstruçõesdoAnsible:
$sudopipinstallboto#oruseyourfavoritepackagemanager$curlhttps://raw.githubusercontent.com/ansible/ansible/devel/plugins/inventory/ec2.py>ec2.py$chmod+xec2.py$curlhttps://raw.githubusercontent.com/ansible/ansible/devel/plugins/inventory/ec2.ini>ec2.ini$exportAWS_ACCESS_KEY_ID=seuaccesskeyid$exportAWS_SECRET_ACCESS_KEY=seusecretaccesskey$./ec2.py--help
AnoteonomedasuachavenaAWS.Senãotiverchave,noconsole,menuEC2,váaoitemKeyPairsecrieuma.Umarquivocomextensão.pemserásalvoemsuamáquina.Aminhatemonomedeaws_devel,portantooarquivosechamaaws_devel.pem.
ParausarestachavecomoSSH,copieparaseudiretório~/.ssh/emudeaspermissõespara0600comchmod0600
6.2PROVISIONAMENTONAAWS
6.2PROVISIONAMENTONAAWS 77
~/.ssh/aws_devel.pem.Quandoamáquinaestiverinstalada,testecomssh-i~/,ssh/aws_devel.pemubuntu@ip_publico,trocandoaws_devel.pempelonomedoarquivocomasuachave.
Dentrododiretóriogroup_varscriamosumarquivochamadoallcomosdadosdechaveSSH,região,nomedaimagem,VPC(VirtualPrivateCluster),subnetetipodeinstância.Odiretóriogroup_varscontémarquivoscomonomedosgruposeallparavariáveisqueseaplicamparatodososgrupos.
key_name:aws_develaws_region:us-east-1ami_id:ami-9instance_type:t2.microvpc_id:vpc-XXXXXXXXsubnet_id:subnet-XXXXXXX
EstaéadescriçãoparamáquinasdoEC2naregiãous-east-1,sistemaoperacionalUbuntu14.04t2.micro(at1.microéapenasPVeaimagemquequeremosusaréHVM.Sãotiposdevirtualizaçãoqueimpactamnaperformanceetamanhodamáquina).VamosprecisardeumaVPCcriadaeumasubnetatreladaaestaVPC.ExisteumwizardparaissoeprovavelmentevocêjáestáusandoVPCesubnets.
ParasefamiliarizarcomoAnsiblecomoprovisionador,crieidoisplaybooksqueexecutamatarefaquejáfizemosanteriormente:instalarumamáquinacomnginx.Vamosfazerumdesvioaquiparaexecutaresteplaybookeconferirsetudoestáconfiguradocorretamente.Executeocomando:
$ansible-playbook-vvvv-iaws_hosts.inicria_maquina.yml--private-key~/.ssh/aws_devel.pem
Oparâmetro--private-keydeveapontarparaseuarquivocomachavepública,oparâmetro-vvvvserveparanosmostrartodosospassosqueestãosendoexecutados.Oarquivoaws_hosts.iniapontaparalocalhost,poisamaioriadastarefasserãoexecutadasa
78 6.2PROVISIONAMENTONAAWS
partirdamáquinalocal.
Aconstruçãodesteplaybookéinteressantepoistemduassessões:oprovisionamentodamáquinanaAWSeoprovisionamentonamáquinajácriada.Introduzimostambémataskwait_forparaesperaracriaçãodamáquinavirtual.
Comoacriaçãodemáquinasvirtuaiséremota,otempopodevariarmaisdoqueacriaçãolocalcomoVagrant.EstaprimeirasessãosubstituialgumastarefasdoVagrantaocoletardadosdamáquinacriadaerepassarparaasegundasessão,quecontémataskqueinstalaonginx.
Vamosexaminarcadataskdoprovisionamento:
#Criaumamáquina-hosts:localhostconnection:localgather_facts:Falsetasks:-name:"Criasecuritygroup"ec2_group:name:cassandra_groupdescription:"CassandraSecuritygroup"vpc_id:"{{vpc_id}}"region:"{{aws_region}}"rules:-proto:tcptype:sshfrom_port:22to_port:22cidr_ip:0.0.0.0/0-proto:tcptype:httpfrom_port:80to_port:80cidr_ip:0.0.0.0/0rules_egress:-proto:alltype:allcidr_ip:0.0.0.0/0register:ec2_firewall
Oiníciodesteplaybookindicaqueestastarefasserãoexecutadas
6.2PROVISIONAMENTONAAWS 79
localmente.ComaajudadabibliotecabotoemPython,oAnsiblepodeusaraAPIdaAWSparacriarmáquinaseoutrosserviços.Opassogather_facts:FalseinstruioAnsibleanãocoletarinformaçõesdoambientelocal.
AprimeirataskcriaumSecurityGroupchamadocassandra_groupnoVPCeregiãoindicadas.
ParaestegruposãocriadasalgumasregrasdefirewallparaliberaroacessoaSSHeHTTP.EgresseIngresssãopalavrasindicadasparadescreverosentidodospacotesderedes.Egresssignificapacotesderedequesaemdamáquina.Porúltimo,adiretivaregistercolocaoresultadodestatarefaemumavariávelglobaldoplaybookquepodeseracessadaporoutrastasks.
-name:"CriaumainstancianoEC2"local_action:ec2key_name="{{key_name}}"vpc_subnet_id="{{subnet_id}}"region="{{aws_region}}"group_id="{{ec2_firewall.group_id}}"instance_type="{{instance_type}}"image="{{ami_id}}"wait=yesassign_public_ip=yesregister:ec2
Nestatarefa,criamosamáquinavirtual.CrieiumamáquinaealémdosdadosdechaveSSH(key_name),subnet_id,regiãodaAWS(region),imagemetipodeinstância,passeiogroup_idquefoigravadodentrodavariávelec2_firewallvindadatarefaanterior.EstainstânciateráumIPválido(assign_public_ip=yes).
AtaskestáconfiguradaparaesperaraconclusãodachamadadaAPIcomwait=yes.SeestivéssemosemumVPCqueusaumamáquinadegateway,poderíamoscriarasmáquinassemIPválidoeutilizarapenasaredeinternadoVPC.Registramosoresultadodatasknavariávelec2.
-name:"Adicionahostaogrupoinstancias"
80 6.2PROVISIONAMENTONAAWS
add_host:hostname={{item.public_ip}}groupname=instanciaswith_items:ec2.instances
-name:"Esperaconfirmaçãoantesdeseguir,verificandoaporta22"wait_for:port=22host="{{item.public_ip}}"search_regex=OpenSSHdelay=10with_items:ec2.instances
Avariávelec2serveparaapróximataskAdicionahostaogrupoinstanciascriarumalistademáquinasqueposteriormenteusaremoscomohostsparaasegundapartedoplaybook.
Éimportanteentenderqueesteinventárionãoexisteemumarquivopoisaindaestamoscriandoasmáquinas.Oartifícioparatantoéusarumauxiliarexterno,comooec2.pyetambémutilizarosdadosquesãoretornadosaofinaldecadatask.
Aúltimataskdaprimeiraparteéumaprecauçãoparaesperaracriaçãoebootdamáquinavirtual.Elaapenasesperaqueaporta22(SSH)estejaabertaequedevolvaumastringcom"OpenSSH"apósterumaconexão.Podetestardiretamentedoseuconsolecomumtelnetip_da_maquina22evocêveráqueantesdotrfegocriptografadooservidorSSHmandaumbrevecabeçalhocomestastring.
#Usandoamáquinaquecriamos,vamosinstalaroNGINX.-hosts:instanciassudo:Trueuser:ubuntugather_facts:Truetasks:-name:"Atualizapacoteseinstalanginx"apt:name=nginxstate=latestupdate_cache=yesinstall_recommends=yes
Nasegundapartetudoficousimples:usamosavariávelinstanciasquecriamosapartirdoIPpúblicovindodoresultadodaexecuçãodataskCriaumainstancianoEC2eutilizamoscomoumplaybooknormal.Esteéoinventáriodinâmicodentroda
6.2PROVISIONAMENTONAAWS 81
mesmarodadadoplaybook.
Sevocêexecutaroplaybooknovamente,elenãoagirásobreinstânciascriadasemoutrasexecuções.Opapeldoec2.pyficarámaisclaroaoanalisarmosoplaybookderemoçãodemáquina.Antesdeexecutá-lo,faça:
$./ec2.py--list
OretornodocomandoseráumJSONcomtodasasmáquinascriadaseseusstatus.Exploreasoutrasopçõesdestecomandotrocando--listpor--help.Amaneiradefazerumplaybook"lembrar"doestadodeexecuçõesanterioresparaaAWSéusaroec2.pycomoseuhosts.ini(inventoryfile).Vamosutilizá-lopararemoveramáquinaquecriamos.Antesdeapagá-la,testeoSSHeowebserver.Paraseconectaràmáquinause:
$ssh-i~/.ssh/aws_devel.pemubuntu@ip_publico_da_sua_máquina
Executenovamenteoprogramaec2.py(./ec2.py)eexaminesuasaida.Onomedegrupoquecolocamosanteriormenteaparececomoprefixosecurity_group.Estasessãoéinterpretadacomoumasessãodeinventárioestático.Portanto,conseguimosexecutartasksnasmáquinasqueestãonestegrupo.Éoqueaprimeirapartedoplaybookfaz.Vamosremoveramáquinaanteseposteriormenteexaminaroplaybook.
$ansible-playbook-i./ec2.pyremove_maquina.yml
-hosts:security_group_cassandra_groupconnection:localgather_facts:Falsetasks:-name:Removeainstâncialocal_action:module:ec2state:'absent'region:'{{aws_region}}'instance_ids:'{{ec2_id}}'
-hosts:localhost
82 6.2PROVISIONAMENTONAAWS
connection:localgather_facts:Falsetasks:-name:Removeosecuritygroupcassandra_grouplocal_action:description:"Cassandragroup"module:ec2_groupname:security_group_cassandra_groupregion:"{{aws_region}}"state:'absent'
Nesteplaybook,inicialmenteremovemosamáquinaeposteriormenteosecuritygroup.Poderíamosnãotê-loremovidomasopteipordeixaresteciclocompleto.Notequeasvariáveisqueestãonoarquivogroups_var/allsãoaplicadasàstarefastambém,poispertencematodososgruposetodosplaybooksdestediretório.
Emambasastarefasusamosoestado(state)absentparaindicarqueaqueladescriçãoindicaumitemquedeveestarausente(removido)aofinaldatarefa.EstasemânticaserepeteparatodasastarefasdoAnsible:instalaçãodepacote,movimentaçãodearquivos,templateseprovisionamento.
AgoraestamosprontospararetomaroprovisionamentodoCassandra.ExamineoplaybookparavercomointegreioquetínhamosparausocomoVagrantcomoqueaprendemossobreEC2.Crieiumplaybookseparadoparafacilitaracomparação.Esteplaybookvaiparecergrandepoisteráasfunçõesdeprovisionamentoeconfiguraçãodeambiente,mascomoquevimosnãoparecerácomplexo.
Adescriçãodenossatarefaécombinarosplaybooksanteriores,criarumaconfiguraçãodefirewallquepermitaqueosnósdeCassandrasecomuniquem,criarmáquinasumpoucomaioresparaqueosistemaconsigaserexecutadoefazercomqueasmáquinasse
6.3CASSANDRAEAWS
6.3CASSANDRAEAWS 83
comuniquempelaredeinterna.Temosqueextraireorganizarasinformaçõesdasinstânciascriadasparasatisfazerosrequerimentosdasvariáveisdosrolesquevamosusar.
Esteplaybookestánomesmorepositóriocomonomedecassandra_aws.yml.Nãoesqueçadedesligarsuasmáquinasquandoterminardeusá-laspoisocustopodeseralto.
UseiinstânciasmenoresdoqueasrecomendadasparaaoperaçãoseguradeumclusterCassandrapoismeuobjetivoémostraroprovisionamento.Vamosexaminarohosts.inidoprovisionamentolocal:
[cassandra]192.168.33.100cluster_name="SuperCluster"seeds="192.168.33.100,192.168.33.101,192.168.33.102"listen_address="192.168.33.100"rpc_address="192.168.33.100"192.168.33.101cluster_name="SuperCluster"seeds="192.168.33.100,192.168.33.101,192.168.33.102"listen_address="192.168.33.101"rpc_address="192.168.33.101"192.168.33.102cluster_name="SuperCluster"seeds="192.168.33.100,192.168.33.101,192.168.33.102"listen_address="192.168.33.102"rpc_address="192.168.33.102"
Temosquecriarasvariáveiscluster_name,seeds,listen_addresserpc_address,cadamáquinavirtualutilizandoosdadosdecriaçãodecadainstância.Criamosumataskparaacumularseedsemodifiqueiocódigodorolecassandra,notemplatecassandra.yaml.j2useiumadiretivadoJinja2paracriarumvalordefaultbaseadoemumavariáveldoinventáriodoAnsible.Comparandoantesedepois:
Antes:listen_address:{{listen_address}}Depois:listen_address:{{listen_address|default(ansible_default_ipv4.address)}}
ParainstânciascomIPinterno,comoaAWSemumVPCnamesmaregião,estaconfiguraçãojuntocomoEC2Snitchsãoascorretas.PodeserdiferenteemoutrosprovedoresqueforneçamapenasumainterfacecomIPválidoouentreregiõesdaAWScomo
84 6.3CASSANDRAEAWS
EC2MultiRegionSnitchquedemandamudançasderegrasnafirewallenoVPC.AproveiteiamesmatécnicaparaadefiniçãodeSnitch,comumvalordefaultparaoSimpleSnitch.
endpoint_snitch:{{snitch|default(SimpleSnitch)}}
Paraesteclustervamoscriartrêsinstâncias,portantocrieiataskdecriaçãocomoparâmetroextra*count=3*.OAnsibleconsegueprovisionarasmáquinasvirtuaisemparalelo.VamosmudaroparâmetrosnitchparaEC2Snitch.SnitchnoCassandraéocomponentequeajudaagerenciarainfraestrutura.Nossoplaybooktemumajogadaninjaparamontaroseeds:criamosumgrupodehostscomosIPsprivadoseposteriormenteoutilizamosparacriaroparâmetroseeds.
-name:"CriainstanciasnoEC2paraocluster"local_action:ec2key_name="{{key_name}}"count="{{vm_count}}"vpc_subnet_id="{{subnet_id}}"region="{{aws_region}}"group_id="{{ec2_firewall.group_id}}"instance_type="{{instance_type}}"image="{{ami_id}}"wait=yesassign_public_ip=yesregister:ec2
-name:"Adicionahostaogrupoinstancias"add_host:hostname={{item.public_ip}}groupname=instanciaswith_items:ec2.instances
-name:"CriaavariávelseedscomosIPsprivadosdasinstâncias"add_host:hostname={{item.private_ip}}groupname=private_ipswith_items:ec2.instances
vars:-java_versions:oracle-java7-installer-cluster_name:"CassandraClusterAWS"-snitch:EC2Snitch-seeds:"{{groups['private_ips']|join(',')}}"
UtilizamosotemplateengineJinja2embutidonoAnsiblepara
6.3CASSANDRAEAWS 85
acessarogrupochamadoprivate_ipspreenchidonataskCriaavariávelseedscomosIPsprivadosdasinstâncias.EstesIPs,porsuasvezes,foramextraídosdasvariáveisec2geradasporcadaprovisionamento.
Adiretivawith_itemsiterasobrealistacontidaemec2eparacadaitemextraímosoIPprivado.FizemosomesmoparaoIPválidoparagerarogrupochamadoinstancias.Apósexecutaroplaybook,naveguenoconsoledaAWSparaversuasinstâncias,securitygroupseregrasdefirewall.
ExistemmaisdadosedetalhesincluindoodimensionamentodasmáquinasparaexecutaroCassandra.EurecomendooguiadaDatastax(http://www.datastax.com/documentation/cassandra/2.1/cassandra/install/installAMISecurityGroup.html).DependendodasuaconfiguraçãodeSSH,podeaparecerumamensagemreclamandosobre"known_hosts"parecidacomesta:
Theauthenticityofhost'111.111.111.111(111.111.111.111)'can'tbeestablished.RSAkeyfingerprintis: : :ff:ff:ff:ff:ff: : : : : : :ff:ff.
Areyousureyouwanttocontinueconnecting(yes/no)?
Issopodeserresolvidoseguindoasinstruçõesem(http://docs.ansible.com/intro_getting_started.html#host-key-checking)oucomssh-keygen.
Nofinal,oarquivogroup_vars/allganhounovosparâmetrosparaindicaroblocodeIPseonúmerodeVMscriadas(count_vm).
key_name:aws_develaws_region:us-east-1ami_id:ami-9instance_type:t2.microvpc_id:vpc-5subnet_id:subnet-d9fffffvm_count:3cidr_ip:10.0.0.0/16
86 6.3CASSANDRAEAWS
Nestecapítulo,vimoscomoutilizaroAnsiblecomoprovisionador,comousarseudriverdeAWSeEC2ecomotrabalharcomuminventáriodinâmico.
Adificuldadeenvolvidaéentenderosconceitosdeprovedoresexternosedasferramentasquevocêusa.
OexercícioquesugiroéportaroquefizemosparaoutroprovedorcomoDigitalOceanetambémexecutarosplaybooksanterioresnaAWS.Nãoesqueçadedesligarsuasmáquinassevocêgostadoseucartãodecrédito.
6.4CONCLUSÃO
6.4CONCLUSÃO 87
CAPÍTULO7
Adiferençaentrecoletarmétricasemonitorarumaaplicaçãoésutil:omecanismoutilizadopodesersemelhante,masotempoeasaçõestomadassãodiferentes.
Nacoletademétricas,vocêcriavisibilidadedecomosuaaplicaçãorealmentesecomportaemtemporeal─nãosãotestessintéticoscomumroteirogeradopreviamente.
Vocêpodenotarmudançasdetempoderespostaedegradaçãodepartesmodificadasdeumaaplicaçãoapóscadadeploy.Asaçõessãotomadasemtempodedesenvolvimentoeemproduçãoparaprevençãoediagnóstico.
Amonitoraçãotradicionalusaferramentasqueexecutamtestesemintervalospredefinidosdetempoetomaconclusõescomo"serviçolento"ou"serviçoindisponível".Asaçõessãotomadasapenasemtempodeprodução,sendopaliativasoucorretivasparamanterosistemafuncionando.
Métricassãoocaminhoparaentendercomosuaaplicaçãosecomportaentredeploysemudançasdearquiteturas.Existemmaneirasdecoletarmétricascominstrumentaçãodecódigoecomacoletadedadosdoambientedaaplicação.
Entreestesdoisconceitos,existeodeprofiling,queéoexamede
MÉTRICASEMONITORAÇÃO
88 MÉTRICASEMONITORAÇÃO
métricadeaplicaçõesdivididasporcamadasparaavaliarcaminhosdecódigoeproblemasdecapacidade.
Asferramentasparaprofilegeralmenteseconectamaointerpretadorouacamadasdosistemaoperacionalparacapturarainteraçãodocódigoegerarmétricas.
Omelhordosmundoséentendercomocombinardadosdemonitoração,métricaseprofiling,alémdeeventosdodiaadiacomomudançaseproblemasdeinfraestrutura.
Esteéoestadodaartedeumaorganizaçãoeumtrabalhocomplexo.Podemosestudarbonsexemplosdecadatipodeferramentaseimplementarobásicoparanossasnecessidades.Muitasferramentaslegaispodemserutilizadascombaixoounenhumcusto.
ProcuretambémmaterialdeconferênciascomoVelocity(http://velocityconf.com/)evídeosdaMonitoramaem(https://vimeo.com/monitorama/videos).Estesvídeosapresentamcasosdeimplementação,construçãodedashboardsedesenvolvimentodemétricasparadetectaradegradaçãodeserviços.
Amonitoraçãofuncionalnasceudoping.AmaioriadossistemasdisponíveishojeemdianasceudeantecessoresoucombinaçõesdoNagios(http://www.nagios.org/).Cadaetapadetestesechamaprobeecomeçaporexecutarping,testarportasTCP/IPabertas,arespostadesiteseaexistênciadestringsemlogs.
Esteestilodemonitoraçãotradicionalsebaseiaemservidorescentraisqueexecutamosprobesemintervalospredefinidosdetempoetomadecisõescomoenviare-maileguardarosvalores
7.1MONITORAÇÃO
7.1MONITORAÇÃO 89
testadosparaanáliseposterioremumbancodedadosRRD(RoundRobinDatabase).Quandoapresentamestasinterfaces,estessistemastêmdescendênciadiretadoMRTG(http://oss.oetiker.ch/mrtg/),porexemploCacti(http://www.cacti.net/).
Apesardeteremumvalorimensoeseremutilizadosatéhoje,nãovoumeconcentrarnestessistemasparacriarplaybooksouinstalaçõescompletas.Vouindicarumplaybookedeixarcomoexercíciocriarumainstalaçãodecheck-mkseoleitortivercuriosidadenestestiposdemonitoração,OpenMonitoringandCheck-MK(https://github.com/sfromm/ansible-omdistro).
EmvezdissovamosolharparaserviçosdemonitoraçãonoestiloSaaS(SoftwareasaService).OmaisfamosodeleséoPingdom(https://pingdom.com)queoferecefreetrial.
OqueeugostodeusarporsercompletoeiniciarcomumacamadagrátisalémdeboaprogressãodepreçoéoUptimeRobot(https://uptimerobot.com/).Égrátisparachecagensde5em5minutosdeaté50itens.Elescobramparaintervalosmenores,enviodeSMSeretençãodehistórico.EmambososplanosvocêpodeusarumaAPIparainclusãoeexclusãodesites.
Esteémeudashboardconfiguradoparapoucossites:
90 7.1MONITORAÇÃO
Figura7.1:DashboardexemplodoUptimeRobot
Estedashboardéparecidocomodeoutrasferramentasecontém3sessõesprincipais:seusprobes/Monitorsnoladosuperioresquerdo,QuickStats(umresumovisualrápidonoladosuperiordireito)enoinferiordireitoumalistadosúltimoseventos(quedas,errosemáquinasreestabelecidas).
Vamoscriarumprobeparahttps://google.com.Casovocêjátenhaalgumsite,apenastroqueoendereçopelodoseusite.
Entrecomsuacontaecliqueobotãonoalto,ladoesquerdocomotítuloAddNewMonitor.Deveapareceratelaemseguida:
7.1MONITORAÇÃO 91
Figura7.2:Addnewmonitor
SelecioneMonitortypeparaHTTPeateladevemudar:
Figura7.3:Selecionaoendereço
Preenchacomodomíniodoseusiteoucom
92 7.1MONITORAÇÃO
"https://google.com"ecliqueobotãoCreateMonitor.
OAnsibleofereceumpacotedemódulosextra(https://github.com/ansible/ansible-modules-extras)quetemsuporteaoUptimeRobot,entreoutros.Podemosutilizarestemóduloparapararereiniciaramonitoraçãodeumsitecriadopelainterfaceweb.
Parautilizarestesmódulos,vocêdeveteraúltimaversãodoAnsible(aqueestouusandoagoraéa1.9,HEADdorepositórioGit).Comamonitoraçãocriada,váemSettings->APISettings->CreatethemainAPIkey,atéreceberamensagemThemainAPIkeyis:x111111-1111111111111111.
ComachavedeAPIcriada,procureoIDdesuamonitoração.ÉonúmeroqueficaapósdaURLquandovocêclicaemcimadonome,porexemplo:
https://uptimerobot.com/dashboard#77
OIDdomonitoré77 .Copieoarquivovars/uptimerobot_creds.yml.distparaoarquivovars/uptimerobot_creds.ymlealtereosdados.ExecuteoAnsibleparapausaramonitoração:
$ansible-playbook-ihosts.iniuptimerobot_pause.yml
Ocódigoésimples:
-hosts:localhostconnection:localvars_files:-vars/uptimerobot_creds.yml
tasks:-name:"Pausaamonitoraçãodoitem"uptimerobot:monitorid="{{monitor_id}}"apikey="{{api_key}}"state=paused
7.1MONITORAÇÃO 93
Reinicieamonitoraçãocom:
$ansible-playbook-ihosts.iniuptimerobot_start.yml
Paraestecaso,oestado(state)mudaparastarted.Estastaskspodemsercolocadasnoinícioenofinaldoprovisionamentoparaevitarfalsospositivosoualertaserrados.
Paraefeitosdemonitoraçãotradicionaldeuptime,pingeportaaberta,vamospararporaqui.AmaioriadasferramentaswebseráparecidacomoUptimeRobotportantoencontreasuaeprocureummódulooumaneiradeautomatizaracriaçãoeocontroledoseumonitor.
Norepositóriodestecapítulotemumplaybookchamadologstash.EsteplaybookéumexemplodeinstalaçãodoCollectD(http://collectd.org)edoLogstash(http://logstash.net/).Ocollectdéumframeworkdeagenteseservidoresparacoletademétricasecontadores.
Eletemumabibliotecadepluginsquecobremsistemasoperacionais,aplicaçõeseAPIs.Ologstashéumsistemadeprocessamentoeindexaçãodelogsemétricascomumconstrutordedashboardsbemflexível.EleusaoElasticsearch(https://www.elastic.co/products/elasticsearch),ummotordebuscaeindexaçãopoderosobaseadonoApacheLucene.
EstasfuncionalidadessãoencontradasemprodutoscomerciaiscomooSplunk(http://www.splunk.com/),mascomacombinaçãodeprojetosdecódigoabertoaflexibilidadedeadicionarcomponentesedelimitesdeusoémaior.
Amáquinavirtualcriadaéautocontida,serveparaexaminarocollectdeologstash.OIPdelaé192.168.33.100.Apósocomando
7.2COLLECTDELOGSTASH
94 7.2COLLECTDELOGSTASH
vagrantup,coloqueoendereçohttp://192.168.33.100/emseubrowserenaveguepelainterfacewebdologstash,construídaemcimadoKibana(https://www.elastic.co/products/kibana).
Aestaaltura,vocêdevesaberoqueprecisafazerparainstalarumplaybookemumamáquinadeprodução.Ocollectddeveserinstaladoemtodasasmáquinasquevocêquermonitorar,easuaconfiguraçãoem/etc/collectd/collectd.confdeveserparecidacomaseguinte:
Hostname"nome_da_sua_maquina"
FQDNLookupfalseLoadPlugincpu
LoadPlugindf<Plugindf>Device"/dev/sda1"MountPoint"/"FSType"ext4"ReportReservedtrue</Plugin>
LoadPlugininterface<Plugininterface>Interface"eth0"Interface"eth1"IgnoreSelectedfalse</Plugin>
LoadPluginnetwork<Pluginnetwork><Server"192.168.33.100""25 ">#ipdoservidorcomlogstash</Server></Plugin>
LoadPluginmemory
LoadPluginsyslog<Pluginsyslog>LogLevelinfo</Plugin>
LoadPluginswap
7.2COLLECTDELOGSTASH 95
<Include"/etc/collectd/collectd.conf.d">Filter"*.conf"</Include>
Vocêpodeaproveitaromesmoplaybookparaosclientes,sódevemodificá-loparacolocaroIPdoservidorcomlogstashnoblocoindicado:
LoadPluginnetwork<Pluginnetwork><Server"192.168.33.100""25 ">#ipdoservidorcomlogstash</Server></Plugin>
Opluginnetworkenviaosdadoscoletadosparaumservidor.Noframeworkdocolelctdsãodefinidostransportesearmazenamentosdedados.Elegravaosdadoscoletadosemarquivos.rrdlocaiseenviaasmétricasporesteplugin.Ologstashestáconfiguradoem/etc/logstash/conf.d/logstash.confcomummóduloquerecebeoprotocolodocollectd:
input{udp{port=>25buffer_size=>1452codec=>collectd{}type=>"collectd"}}output{elasticsearch{cluster=>"dashboard"protocol=>"http"host=>"192.168.33.100:92 "}}
Sãodefinidosdoisblocos,umdeentrada(input)eoutrodesaída(output).Ologstashsuportamaisblocosdeentradaesaídasimultaneamente.Noblocooutput,oparâmetrohostapontaparaoservidorElasticsearch.Nonossocaso,seráamesmamáquina,masvocêpoderiaterumclusterdeelasticsearchparaconseguiralta
96 7.2COLLECTDELOGSTASH
disponibilidade.Comestamáquinavirtual,sigaospassosparaexploraroelasticsearch(http://www.elastic.co/guide/en/elasticsearch/reference/current/_exploring_your_cluster.html).Elepodeserútilemoutrosprojetos.
VocêpodeconstruirumsistemacomamesmafuncionalidadeutilizandoSOLR(http://lucene.apache.org/solr/),InfluxDB(http://influxdb.com/),Grafana(http://grafana.org/),StatsD(https://github.com/etsy/statsd/)ouGraphite(http://graphite.wikidot.com/).PodeexperimentartambémoGrayLog(https://www.graylog.org/).Oobjetivodestalistaédizerqueoimportanteéaideiaprincipaldaarquiteturadecoletademétricas,explicadanafiguraaseguir:
Figura7.4:Arquiteturadecoletademétricas
Oselementosdestaarquiteturapodemestarnamesmamáquinaoudivididosemclustersparaaltadisponibilidadeepoderdeprocessamento.Estemododeenviodemétricassechamapushecontacomumagentequeenviamétricasaumrepositório,porum
7.2COLLECTDELOGSTASH 97
indexador.
Asmétricassãoarmazenadascomotimeseries(seriesdetempo).Esteconceitoéimportantíssimonacoletademétricaspois,namaioriadasanálises,umadesuasvariáveisseráotempo(requestsporsegundo,KB/s,visitasporhora,queriesporsegundo).Todosossistemasdearmazenamentodemétricasoferecemoperaçõesprimitivasparaamanipulaçãodetimeseries.
Oindexadorpodeserintegradoaobancodedadosouseparado.MóduloscomunsligadosaelesãoAPIsparaintegraçõesexternas,sistemasdenotificação(e-mail,SMS)edashboards.Estessistemaspodemseradaptadosdepraticamentequalquerinfraestruturaquevocêjátenhaequecoletemétricas.Omelhorsistemadecoletademétricaséoquelheatendeequenãoconsometempoexcessivoparaadministração.OqueaprendemoscomoAnsiblepodeajudaracriarmáquinasquejáentrememproduçãomonitoradasecoletandoumconjuntomínimodemétricas.
Omesmoprincípiopodeserusadoparacoletarmétricasdedentrodesuasaplicaçõesparacombinarcomasdosistemaoperacional(tempodeconsultaembancodedados,tempoderespostaspararequestsHTTP,numerodeclientesautenticados).
SeestesdadosforemexpostosporumarotaHTTPqueéconsultadadetemposemtempos(polling)ouenviadosdiretamenteaorepositóriodemétricas(push),podemserexibidasnomesmodashboardoucombinadasnomesmográfico(porexemplo,consumodeCPUvs.usuáriosautenticados).Alémdecoletademétrica,estemétodotemfunçãoderastreamentodelatência.
Aúltimapartedestecapítulovaiapresentarferramentasde
7.3PROFILING
98 7.3PROFILING
profiling.Nocontextodesistemasemprodução,trata-sedacoletademétricasdoambientederuntimeedaaplicação.Estasinformaçõessãoúteisparaentendercaminhosdecódigoquepodemserotimizados,oefeitodeaumentodelatênciaemredeoubancodedadosparaoclienteeparacapturarerrosquenãoaparecememtestesdeintegração.
ParaaplataformaJavaporexemplo,ainterfaceJMXfornecemuitoscontadoresedadosparaprofiling.InterpretadoresdelinguagensdinâmicascomoRuby,PythonePHPtêmpontosdeinterceptaçãoquesãousadosparacoleta.Atémesmoobrowsertemestespontosepodesermonitoradoparaerroseperformances.
VamosvertrêsferramentasSaaSfamosasecomerciais,mascomumníveldeentradasemcusto,paraintroduziresteconceito:NewRelic(http://newrelic.com/),AirBrake(https://airbrake.io/)eBoundary(http://www.boundary.com/).
Elastrabalhamcomagenteslocaisetêminstruçõesespecíficasparacadaplataforma.ONewRelicéumprofiledelinguagemeintroduzumamonitoraçãodeusuáriofinalparaaplicaçõeswebchamadadeRUM(RealUserMonitoring).Estetipodemonitoraçãocoletadadosdosbrowsersdosusuárioseacumulaparainferiríndicesdequalidade,tempodecarga,errosqueousuáriovê.Emsuainterface,ostemposdeaplicação,redesebancodedadossãoexibidosseparadamenteeacumulados,alémdanavegaçãopormétodosefunçõesmaisexecutadasequetomammaistempodeCPU.
OAirbrakecapturaexceçõesdocódigoemváriaslinguagensemcompilaumíndiceedashboardparaconsultarápida.Emlinguagenscomambienteruntimedinâmicoerico,asexceçõesquesóaparecememtempodeexecuçãopodemficaremlogssemadevidaatenção.Mesmocomcargasintéticadetestes,édifícilexercitartodososcaminhosdecódigoetodasassituaçõesqueambientesde
7.3PROFILING 99
produçãocolocamnasaplicações.
Paramonitorareconhecersuaarquitetura,aBoundaryofereceagentesquecoletamflows(fluxosdecomunicaçãoderede)ecatalogamemumsistemaquepermiteidentificarqualofluxoequantidadededadosquetrafegaentreoselementosdoseusistema.
Esteassuntorendeumlivroporsisóeonossoobjetivoécriarumaestruturaminimamenteaceitáveleautomatizadaparaquenenhumamáquinaentreemproduçãosemamonitoraçãomínima.
Monitorareconheceroqueacontececomsuaaplicaçãoeinfraestruturaéumhabitosaudável.Emaltonível,asmétricasqueimportamparaonegóciopodemserderivadasdemétricasligadasdiretamenteàtecnologia.
Portanto,oexercíciodepensaremmétricasdotipo"Novosclientespordia,paginasvisitadas,cartõesdecréditosaprovadosevendas"ajudaaentendercomocombinarmétricasdebaixonívelparacriarumhistóricoeavaliarqualoimpactodemudançaseincidentesnoseuresultadofinanceiroedesatisfaçãodocliente.
7.4CONCLUSÃO
100 7.4CONCLUSÃO
CAPÍTULO8
EstecapítuloéumexercícioqueusaoquevocêaprendeunoscapítulosanterioresparamontarumambientenaAWScomWordPressusandoduasmáquinaseanalisarmétricascoletadassobresuaperformance.
Nesteambiente,vamosinstalaroNewRelicegerarumacargasintéticaparaentenderasmétricasqueestaferramentaproduz.Emseguida,vamossimularintermitênciaentreamáquinadeaplicaçãoeadebancodedadosparaavaliarqualoimpactonasmétricascoletadas.
Oexercícioquevamosfazerépartedodiaadiadequemadministraaplicaçõesemcloud.Asmáquinasvirtuaisnemsempretêmperformanceeconectividadeconstantes,naturalmentevariamdeacordocomacargaerecursosdistribuídospelamáquinafísicaqueashospeda.
CadamáquinavirtualdivideotempodeprocessamentoerecursosdeI/Ocomseusvizinhos.IssodeuorigemaumtermochamadodeNoisyNeighbour,queexplicaporquemáquinasdetamanhosemelhantetêmcomportamentodiferente.
Sesuaaplicaçãoésimplesdeserprovisionada,podeserumaboa
ANÁLISEDEPERFORMANCEEMCLOUDCOMNEWRELIC
ANÁLISEDEPERFORMANCEEMCLOUDCOMNEWRELIC 101
práticamonitoraraperformancedasmáquinaseasrecriarparaquecaiamemoutrohost,evitandoqueumamáquinacomperformanceruimdegradeaqualidadedeserviço.
Tersuasaplicaçõesmonitoradasemétricasbemdefinidasnãoserveapenasparasaberquandooserviçoestánoarenãoserpegodesurpresaemcasodeproblemas.
Instrumentarsuaaplicaçãoparacoletarmétricasajudaaserproativonaidentificaçãodefuturosproblemasefornecedadosimportantesparanovasversõesdasuaaplicação.Alémdisso,ajudaamanteroscustoseperfisdeusodesuaaplicaçãocontrolados.
Paraestecapítulo,euadapteioplaybookdeinstalaçãodeWordPresscomumbancodedadosMySQLparaserinstaladonaAWS.AinstalaçãoéparecidacomadoCassandra,vamoscriarduasmáquinasvirtuais.EstasmáquinasvãosecomunicarpelarededoVPCdaAWS.Parafacilitaralocalizaçãodasmáquinas,adicioneiumataskparacriaçãodetags.Achavedatagsechamawordpresseovaloréotipodamáquina:dbouweb.
Executeoplaybook:
$ansible-playbook-iaws_hosts.iniwordpress_aws.yml--private-key~/.ssh/aws_devel.pem
Sehouveralgumproblemacomacriação,revisiteospassosdocapítulosobreCassandraesuasconfiguraçõesdaAWStaiscomoVPC,chaveSSHetokensdeautorização.Apósacriação,configureoWordPressnormalmenteacessandooIPdamáquinaweb.Setiverdúvidassobrequalmáquinaéaweb,olhenologdeexecuçãodoAnsible.
Conecte-seàmáquinacomocomando
8.1WORDPRESSNAAWS
102 8.1WORDPRESSNAAWS
$sshubuntu@ip_da_maquina-i~/.ssh/aws_devel.pem
Achaveusadadeveseramesmaconfiguradanoarquivoalldodiretóriogroup_vars.ApósaconfiguraçãodoWordPress,façaumpostdeteste.Setudoestivercerto,vamosinstalaroNewRelic.Nãoautomatizeiestespassospoisqueroqueoleitortenhaaexperiênciadestaconfiguração.
CrieumacontanoNewRelic(https://newrelic.com),selecioneotipodeprodutoparaserconfiguradocomoAPMe,napáginaseguinte,selecionePHP.VamosinstalaroNewRelicnamáquinawebdonossoWordPress.
SigaasinstruçõesdesetupparaPHP,aquireproduzidas:
$sudowget-O-https://download.newrelic.com/ .gpg|sudoapt-keyadd-$sudoecho"debhttp://apt.newrelic.com/debian/newrelicnon-free">/etc/apt/sources.list.d/newrelic.list$sudoapt-getupdate$sudoapt-getinstallnewrelic-php5$sudonewrelic-installinstall
Apósainstalaçãodopacotenewrelic-php5,surgiráumatelapedindoachavedelicença(LicenseKey)queestáacessívelpelasuaconfiguraçãodoNewReliceumnomeparaestaaplicação.Achaveaparecenapáginaemquevocêescolhequalplataformavaiconfigurar.MaisinformaçõespodemserencontradasnapáginadoagentePHP(https://docs.newrelic.com/docs/agents/php-agent/installation/php-agent-installation-ubuntu-debian).
Aconfiguraçãopodeaparecercomumatelapedindoapenasalicençaoupodeserumsistemademenu,dependedomomentodainstalação.Emcasodedúvidaexecutenewrelic-installesigaasinstruções.
8.2INSTALANDOONEWRELIC
8.2INSTALANDOONEWRELIC 103
ReinicieonginxeoPHP5-FPM:
$/etc/init.d/nginxrestart$/etc/init.d/php5-fpmrestart
VolteàpáginadoNewReliceverifiqueseosdadosdesuaaplicaçãojáchegaram.Emcasodedúvida,verifiqueseoprocessonewrelic-daemonestásendoexecutado:
$sudops-ef|grepnewrelic
Senenhumprocessoaparecer,execute:
$sudonewrelic-daemon
Examineoslogsdonewrelicem:
$tail-f/var/log/newrelic/*
Navegueumpouconoblog,crieumposte,devoltaaositedoNewRelic,cliquenaopçãoBrowsereselecioneonomedesuaaplicação.Deveaparecerumatelacomoaseguir:
Figura8.1:NewRelic
Dentrodamáquinawebexecuteocomando:
$sudotcpdump-ieth0|grep-inewrelic
Ocomandotcpdumpcolocaainterfaceemmodopromíscuo─
104 8.2INSTALANDOONEWRELIC
todosospacotesderedequepassamporelasãointerceptadosefiltradosdeacordocomaregrapassadaaocomando.
Aregraqueusamosésimples,sódefineainterface.Ofiltrousadoemgrep-inewrelicserveparaisolarlinhasquetenhamestastring.OquevemosemseguidasãoospacotesenviadosdamáquinalocalaocoletordedadosdoNewRelic,comonoexemploaseguir:
Nossoblognãoéfamoso,masvamossimularumacertacargaparaentender,porvariáveisdosistemaoperacional,oqueaconteceemummomentodecarga.
ExistemmuitoscontadoreseferramentasemambienteLinuxparaprofilingdesistemaoperacionaleaplicações.Profilingéumconjuntodetécnicasqueajudaadiagnosticarproblemasecomportamentosdosistemaoperacionaledaaplicação.
8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO
8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO 105
Aobservabilidadeéimportanteantesenomomentodealgumproblema.Antes,servepararcriaroquechamamosdebaseline,ocomportamentopadrãodoconjuntoedesviosperigososquepodemgerarindisponibilidades.Nomomento,servemparaencontrarproblemasepontosdecontenção.
Amaioriadosrecursosdeumsistemaoperacionalémodeladacomofilas.Asfilasdependemdeumoumaisprodutoreseconsumidores.Emummomentodealtarequisição,estasfilaspodemcrescereprovocarlentidões.Alémdisso,oacumulodeitensoudepedidosparaitenspodegerarocolapsodosistemaoperacional.Osprincipaisofensoressãodispositivosdedisco,rede,CPUememória.
Entreparadigmasdeconcorrência,problemasdecódigoesobrecarga,ascausasesintomaspodemsecombinar.ONewRelicpermiteumavisãosistêmicadaaplicaçãodivididaentreelementosquecombinamrequisitosdistintosdeCPU,memóriaeI/O.
Emnossamáquinalocalouemumamáquinavirtualforadestecluster,vamosexecutarocomandoaseguirparagerarumacargaprevisível:
$whiletrue;doab-c10-n100http:// . . . /;sleep5;done
Estecomandousaoab(apachebenchmark)paraenviar100requests,comconcorrênciade10requestsporvezde5em5segundos.Nãoéumacargarealistanempossuiumcrescimentorápido,maséumacargasintéticaqueajudaráaentenderoselementosapresentadosnoNewRelic.
AprimeiratelaquevamosexaminarédasessãoAPM,chamadaOverview:
106 8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO
Figura8.2:NewRelicWebTransactions
Estatelatemoresumodotempoderespostadastransaçõesweb.Acurvateminícionomomentoemqueageraçãodecargasintéticacomeçou.
Aolado,temosoApdexScore─umíndicepadrãodaindústriaparadescreveraqualidadequeousuáriofinalestávivenciando,umpequenográficodethroughputqueusaamétricaRPM(requestsperminute)paradescreverpedidosdeclientesparaaaplicação.Descendoatela,teremosumalistadetransaçõesdescritapelaspáginaserotasdeAPIchamadas.
ApróximatelaqueveremoséasessãodatabasesdoAPM:
Figura8.3:NewRelicDBTransactions
8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO 107
OgráficoprincipaléoacumuladodetodasastransaçõesdebancodedadosrecuperadaspeloNewRelic.Lembre-sequenãoinstalamosnadanamáquinadbmasoNewRelicconseguerecuperarestastransaçõespeloPHP.
Aordemdasqueriesédamaislentaparaamaisrápida.Nesteregimedecarga,ostempossãobembaixos,maspodemosverumpadrão:aquerywp_optionsselectéaqueocupamaistemponestegráfico.Omenupull-downacimadalistadequeriescomalegendaSort-byofereceoutroscritériosdeordenação.
Vamosaumentaronúmerodetransaçõesdotestedecarga:
$whiletrue;doab-c20-n200http:// . . . /;sleep5;done
Dobramosaconcorrênciaeonúmeroderequests,mantivemosotempoentreoslotesderequests.Ateladedatabasesficouassim:
Figura8.4:NewRelicDBTransactions
Ostemposdasqueriesdobraram,oquepodedaraideiadequeoconsumoderecursosélinear.Apráticaensinaquenemsempreéassim,queapartirdeumnúmeroderequestsporsegundoalgunsrecursosesgotamantesdeoutros.
Abaixodográficodetempodeoperações,háográficodetempoderespostadobancodedados:
108 8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO
Figura8.5:NewRelicDBResponsetime
Osdoispicosforampostsquecrieinoblog.Paraopadrãodeacessodotestedecarga,aoperaçãopredominanteéoSELECT.Paraumnovopost,quasetodasasoperaçõessãoutilizadas.
Ostemposderespostamudamporcontadisso.Seolharmosonossotestedecarga,umarodadanormaltemaseguintedistribuiçãodepercentuaisnaconfiguraçãodemáquinasqueutilizamos:
Percentageoftherequestsservedwithinacertaintime(ms)
8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO 109
Duranteumpost,adistribuiçãomudapara:
Percentageoftherequestsservedwithinacertaintime(ms)
De90%emdiante,ostemposaumentamsignificantemente.Em99%,otempoaumentaemquase1segundo.Oconsumoderecursosfoiafetadoporumaoperaçãodiferentedaoperaçãoutilizadanotestedecarga.Umtestedecargacompletodeveriasimularusuáriospostandomensagensdeformaconcorrente.
Dentrodamáquinaweb,vamosveracarga(loadavg)eestatísticasdeCPU.
root@ip-10-0-0-100:/etc/php5/fpm#uptime
root@ip-10-0-0-100:/etc/php5/fpm#vmstatprocs-----------memory-------------swap-------io----rbswpdfreebuffcachesisobibo
-system--------cpu-----incsussyidwast
Vamosaumentaracarga:
$whiletrue;doab-c40-n400http:// . . . /;sleep5;done
Asaídadoscomandosmudouumpouco:
root@ip-10-0-0-100:/etc/php5/fpm#uptime
root@ip-10-0-0-100:/etc/php5/fpm#vmstat
110 8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO
procs-----------memory-------------swap-------io----rbswpdfreebuffcachesisobibo
-system--------cpu-----incsussyidwast
Acargaaumentoueoconsumodememóriatambém,masnadaagressivo.Nasduasmedições,aúltimacolunadoblocoCPU,chamadast,estácomvalor1.Estacolunarepresentaotemporoubado(stolentime)pelohypervisor.Éumindicadordequeamáquinavirtualnãotemotempoqueesperavaparaexecutar.Éumcontadorimportanteparasermonitorado.Casootemporoubadocresçaoufiqueconstanteacimade0,éhoraderecriaramáquinavirtualemoutrohost.Comaautomaçãoqueconstruímosissoéfácil.
Paranossotesteestaéumadificuldadeinteressante.NoNewRelic,estaéacaradoconsumoderecursos:
Figura8.6:NewRelicDBResponsetime
OstemposaumentarameduranteotesteminhaconexãoSSHtravou.Comooperfildemáquinaqueescolhiépequeno,este
8.3GERANDOCARGA─PROFILINGDAAPLICAÇÃO 111
comportamentonãoéraro.
Otestequequerofazeragoraéreduzirabandadainterfacedamáquinadebancodedadosparagerarfilasemambososlados.Conecte-seàmaquinadbevamosvercomoestãoacargaeoscontadoresdeCPU:
ubuntu@ip-10-0-0-242:~$uptime
ubuntu@ip-10-0-0-242:~$vmstatprocs-----------memory-------------swap-------io----rbswpdfreebuffcachesisobibo
-system--------cpu-----incsussyidwast
VamosusaradocumentaçãodoLinuxAdvancedRoutingHow-To(http://lartc.org/howto/lartc.ratelimit.single.html)paralimitarabandadestamáquinaem256kbps.
root@ip-10-0-0-242:~#exportDEV=eth0root@ip-10-0-0-242:~#tcqdiscadddev$DEVroothandle1:cbqavpkt1000bandwidth100mbitroot@ip-10-0-0-242:~#tcclassadddev$DEVparent1:classid1:1cbqrate256kbitallot1500prio5boundedisolatedroot@ip-10-0-0-242:~#tcfilteradddev$DEVparent1:protocolipprio16u32matchipdst10.0.0.100flowid1:1
Aprimeiramudançaquevemosénospercentuaisdotestedecarga.Antesdalimitaçãodainterface:
Percentageoftherequestsservedwithinacertaintime(ms)
8.4SIMULANDOLIMITAÇÕESDEREDE
112 8.4SIMULANDOLIMITAÇÕESDEREDE
Apósalimitação,otestedemoramaisparafinalizar.Estestempostendemaaumentarconformemaisrequestssãolançadosnobancodedados.
Percentageoftherequestsservedwithinacertaintime(ms)
Osnúmerosdamáquinadebancodedadoscontinuambons:
root@ip-10-0-0-242:~#uptime
root@ip-10-0-0-242:~#vmstatprocs-----------memory-------------swap-------io----rbswpdfreebuffcachesisobibo
-system--------cpu-----incsussyidwast
Namáquinaweb:
ubuntu@ip-10-0-0-100:~$uptime
ubuntu@ip-10-0-0-100:~$vmstatprocs-----------memory-------------swap-------io----rbswpdfreebuffcachesisobibo
-system--------cpu-----incsussyidwast
8.4SIMULANDOLIMITAÇÕESDEREDE 113
Oloadavgmelhoroueostolentimeestáalto.VamosolharoNewRelic:
Figura8.7:NewRelicDBResponsetime
Amaiorinflexãodetempoaconteceunomomentoemquealimitaçãofoiinstaladanainterfacedamáquinadebancodedados.Vamosremoveralimitaçãoeverificarostempos.
root@ip-10-0-0-242:~#tcqdiscdeldev$DEVroot
Apósalgunsminutos,vemosospercentuaisdotestevoltaremaospatamaresanteriores:
Percentageoftherequestsservedwithinacertaintime(ms)
Oscontadoresdamáquinamudaram.Porcontadavazãoqueoservidortem,oloadaverageaumentou.Otestedecargaéexecutado
114 8.4SIMULANDOLIMITAÇÕESDEREDE
maisrápido,portantoexecutamaisvezes.
ubuntu@ip-10-0-0-100:~$uptime
ubuntu@ip-10-0-0-100:~$vmstatprocs-----------memory-------------swap-------io----rbswpdfreebuffcachesisobibo
-system--------cpu-----incsussyidwast
SeolharmosnoNewRelic:
Figura8.8:NewRelicDBResponsetime
Oimpactodareduçãodebandadainterfacedamáquinadebancodedadosfoisignificativo.Seotestesimulasseumfluxonormaldeclientes,haveriamaisfalhasdoladodocliente.
Estamosfalandodeumblogsimplessemacessorespondendoàpáginaem15semtestescom400conexõesdistribuídasemlotesde40conexõessimultâneas,quesubiupara36segundosnopiormomentodoteste:
Percentageoftherequestsservedwithinacertaintime(ms)
8.4SIMULANDOLIMITAÇÕESDEREDE 115
EstenúmeroaltoéefeitodotemporoubadoedalimitaçãoderedenoMySql.VamosverográficodoOverview:
Figura8.9:NewRelicWebTransactions
Ahistóriaqueelecontaéqueacargafoiaumentandoumpoucoantesde7:10PM,equeacomposiçãoentrePHPeMySQLmudouquandofoiinstaladaumarestriçãode256kbps(kbitspersecond).OstempossubirammasaaplicaçãoPHPesuamáquinapareciammaistranquilas.
Estaimpressãosedeveaofatodequecadarequisiçãodemoravamaisevinhadamesmaorigem.Oefeitoécontrárioaoqueestavaacontecendo.Seolhássemosapenasoload,teríamosaimpressãodequerestringiravelocidadefoiumamelhoria.Sóque,olhandoparaorelatóriodoteste,ostemposagrupadosporpercentuaisdosrequestsaumentavadramaticamente.
116 8.4SIMULANDOLIMITAÇÕESDEREDE
ONewRelictemummódulochamadoBrowserquemedealgunsdadosrelacionadosaofrontend.OABnãosimulaumbrowsercompleto,portantoacoletadedadosdoNewRelicficaprejudicada.MasosdadosdospostsforamcolhidoseodoAPDexcalculado.Desdeoiniciodoteste,eufizalgunspostsnoWordPresse,apósdesligaroteste,fizoutropostparaanalisarmosarecuperaçãodaaplicação.
ComoalgumasinstânciasdaAWStentamfazerbursting,aaltacargaimpostapelotestesolicitoumaiscapacidade,quenãoestavadisponível.Paraestevolumedotesteainstâncianãoeraomelhortipo,masfoiumalimitaçãoqueescolhiparademonstrarestescontadoreseefeitos.Aofinalizaroteste,oscontadoresdamáquinavoltaramaonormal:
ubuntu@ip-10-0-0-100:~$uptime
ubuntu@ip-10-0-0-100:~$vmstatprocs-----------memory-------------swap-------io-----system--rbswpdfreebuffcachesisobiboincs
------cpu-----ussyidwast
AprimeiramedidadoVMSTATnãotemcomoquecomparar,portantovalecomoumamedidatópicamasdeveserobservadaaolongodotempo.
Apósalgunsminutoscoletando,vamosveroNewRelic:
8.4SIMULANDOLIMITAÇÕESDEREDE 117
Figura8.10:NewRelicBrowser
Selecioneiumespaçode3horasparamostrarcomoospostsanterioresaotesteficaramquasenulospertodoresultadodosistemasobestresse.OAPDextambémcaiurapidamente.VoltandoaoAPM,vamosolharoitemMap:
Figura8.11:NewRelicBrowser
Ocrescimentodetempoderespostadaaplicaçãocoincidecomodobancodedados.Ajanelaéadarestriçãodainterfacemasoimpactode100msnobancoémultiplicadonacamadadeaplicação.
Estecasoquecriamosassumiualgumassimplificações:fonteúnicadetrafego,constâncianovolumederequisiçõessemcurvade
8.5CONCLUSÃO
118 8.5CONCLUSÃO
crescimentoeumsetupsimplesdeduasmáquinas.Eleserviuparademonstraralgumasferramentaseumametodologiasimplesparasimularerroscomuns.
Umaaplicaçãorodandoemcloudestásujeitaavariaçõesdeperformancequepodemgerarresultadosimprevisíveis.Umsistemaoperacionalquetemvelocidadevariávelderedeediscopodemudarocomportamentodeumaaplicaçãotradicionaldesenvolvidaemmáquinafísica.Alémdasvariaçõesdeambiente,asvariaçõesdecargapodemcriarsintomasquenosafastamdacausaraiz.
EurecomendolerolivroSystemsPerformance:EnterpriseandtheCloud(http://www.brendangregg.com/books.html)doBrendanGregg.Paracadaelementodosistemaoperacionalelepropõeferramentasemétodosparadescobrirpontosquepodemsermelhorados.
Nestecapítulo,abordeisobaperspectivadeumaaplicaçãowebsimplesmasexistemcasoscomplexosqueenvolvembancosdedadosesistemasassíncronosenãosãotriviais.
Aexperiênciacontaeamelhormaneiraécomeçarcomonocapítuloanterior:criandomonitoraçãoemétricasparasuasaplicações.
8.5CONCLUSÃO 119
CAPÍTULO9
NestecapítulovamosverumaoutracategoriadevirtualizaçãochamadaOperatingsystemvirtualization.
Avirtualizaçãomaisconhecidaenvolveaemulaçãodeumamáquinacompleta,controladaporumagendadordetarefasquedivideotempoerecursosdohostentremúltiplasinstânciaschamadasdemáquinasvirtuais.
PrepareiumplaybookdoAnsiblequecriaumamáquinavirtualcomokerneleaplicaçõesnecessáriasparaexecutarcontainers.ElatambémtemoDockerinstalado,queéumaAPIedaemonqueimplementaumaformadeutilizarcontainers.
Todotipodevirtualizaçãolidacomadivisãoderecursoseoisolamentodostenants(usuários).Aoemularumamáquinacompleta,ohostentregaumainterfacequesimulaobare-metal,termoutilizadoparadescreverohardware,comBIOS,driverseespaçodememória.Navirtualizaçãotradicionalpodemosterguests(maquinasvirtuais)dostiposPVeHVM.
PVéasigladeparavirtualization,naqualaCPUdohostnãoprecisaterextensõesespecíficasdevirtualizaçãoedependeinteiramentedosuportedokerneldosistemaoperacionaldohostedoguestparaemulareacessardispositivos.Estaformade
DOCKER
9.1VIRTUALIZAÇÃO
120 DOCKER
virtualizaçãopermiteboaperformanceesignificaqueosguestsconhecemohost.
HVMsignificaqueohostutilizaextensõesecamadasdesoftwareparaemulardispositivos.AmaisfamosasechamaQEMUeéutilizadaemvárioshypervisors(softwareutilizadoparagerenciarmáquinasvirtuais).
Entreestesdoismodelos,existemcombinaçõesdedrivers,acessosemodelosdeperformance.
AcategoriadeOperatingsystemvirtualizationenglobasistemasqueisolammaisdeumainstânciadeuserspace.EstamodalidadeexisteháalgumtemposobdiferentesnomeserecursosemdiferentestiposdeUnices(pluraldeUnix)enoWindows.
AquelaemquevamosnosconcentrarestápresentenoLinuxesechamacontainers.Juntoaoscontainers,paragerenciarosuserspaceséutilizadoCGroups.
Adiferençadeperformanceeoverhead(custo)aosistemaoperacionalésignificativa.Comovamosconfirmar,executarumcontainerémaisrápidodoquebootarumamáquinavirtual.
Issoacontecepoisemmáquinasvirtuaisosistemaoperacionalrecebeaabstraçãodehardwareque,implicitamente,temcamadasquedevemsergerenciadas,eocontaineréisoladoporabstraçõesdenamespaceemummesmosistemaoperacional.
9.1VIRTUALIZAÇÃO 121
Figura9.1:VMecontainers
Máquinasvirtuaisecontainersnãosimplesdecomparar.Afiguraanterioréumadescriçãosimplesdecamadasentreaaplicaçãoeosrecursosdehardwaremasexistemmaiscontrolescomplexosemambososlados.Umatecnologianãoanulaaoutrapoisosavançosnatecnologiadevirtualizaçãonospermitemdividirmáquinasqueumsistemaoperacionalnãoseriatãoeficienteemdividir.Sãoduasaplicaçõesdetimeshareedeisolamentocomputacionalimportantes.
CGroupséaimplementaçãodoLinuxdenamespaces.Juntocomasferramentasedriversdecontainers,compõeainfraestruturaparacontainers(https://linuxcontainers.org/)dokernel.LXCéoconjuntodeferramentasparamanipularcontainersdiretamente.
OCGroupsnãoéútilapenasparacontainers.Vocêpodecriargruposparalimitaroconsumodememóriadeaplicaçõesemsua
9.2CONTAINERSECGROUPS
122 9.2CONTAINERSECGROUPS
máquinavirtual.
Seaplicarmosumaregraparalimitaroconsumodememóriadeumgrupoa70%,todososprocessosdestegruposerãoavaliadosporestaregra.Quandoogrupoultrapassaolimitepreestabelecidodememória,okerneltentarecuperarmemórianãoalocadadosprocessos.Seaindaassimoconsumoestiveralto,eleusaoOOM-Killerparamataromaiorprocessodogrupo.
AarquiteturaedetalhesdoCGroupsédensaepodeserlidanadocumentaçãodokernel(https://www.kernel.org/doc/Documentation/cgroups/memory.txt).BastadizerqueelefazomesmocontroleparaI/O,redeeCPUequefoireescritonasúltimasversõesdokernel.Suaestruturaéabasedecontroledesistemasquecontrolamoutrosrecursosalémdoscontainers.
OscontainersseaproveitamdestaedeoutrascaracterísticasdecontroledokerneldoLinuxparaimplementaroisolamentoeinstanciaçãodeuserspacesdistintos.
Ocontainernãoéamáquinavirtualcompleta,eleéumrootfilesystem(imagemdeumfilesystem)queokernelusaparaisolarumusuário.
Asimagensqueocomandolxc-createutilizasãomínimas,contêmonecessárioparausarosistemaoperacionalsemumkernel.Aspossibilidadessãointeressantes,jáquevocêpodecriarumaimagemespecializadaeexecutaremumcontainer.Estaimagempodecontersuaaplicaçãoebibliotecasnecessáriasparaaexecução.
Existemdiferentesconfiguraçõesderedesqueumcontainerpodeusar.Vamosnoslimitaràconfiguraçãopadrão,queéumabridgeapresentadaaocontainerqueseligaàinterfaceprincipaldokernel.
9.2CONTAINERSECGROUPS 123
VamoscriarumcontainercomosistemaoperacionalUbuntuparavercomofuncionanaprática.Nodiretórioansible-docker-bootstrapdigitevagrantupeespereamáquinasubir.
Emseguida,executevagrantssh.Certifique-sedequeestánamáquinavirtualcomocomando*uname-aeifconfig-a.Depois,digiteoscomandosaseguir:
$sudo-s#apt-getinstalllxc#lxc-create--nameteste-tubuntu
Apósalgunsminutos,ocontainerestaráinstaladoeemexecução.Opróximocontainerdestetipousaráosarquivosforambaixadosnaprimeirainstalação.Podemosverificá-losemexecução:
#lxc-lsteste
Oúnicocontainerlistadofoiotestequecriamos.Vamosexecutá-lo:
#lxc-start--nameteste
Apósoboot,digiteenter.Vocêvaicairemumpromptpedindousuárioesenha.Useubuntu/ubuntueexploreocontainer.Verifiqueainterfacederedecomifconfig-aesaiadocomocomandosudohalt.Estecomandovaidesligarocontainer.Vamosexecutá-loagoraembackgroud:
#lxc-start--daemon--nameteste#lxc-console--nameteste
Vocêvaicairnovamentenopromptdeusuárioesenha.Parasairdocontainer,useacombinaçãodeteclasCONTROL-A-Q.Conectenovamentenocontainercomlxc-consoleeexecuteocomandoaseguir:
$vimoie
124 9.2CONTAINERSECGROUPS
SaiacomCONTROL-A-Qe,nohost,executeocomando:
#ps-ef|grepvim
--color=autovim
Asaídamostraocomandovimoiequefoiexecutadodentrodocontainer.OsPIDspodemmudar,masasaídaéamesma.Volteaocontainercomlxc-console.PodedigitarESC-:q,poisateladoVimpodenãovoltarcorretamente.
Digitetopevejaseconsegueveralgumprocessodohost.Esteéoprincipiodoisolamento.Dámáquinahostvocêconsegueverosprocessosdoscontainers,masdocontainerseentrecontainerssóconsegueveroqueoisolamentopermite.Vamospararocontainer:
#lxc-stop--nameteste
Existemuitomaisquepodeserfeitocomcontainerssemoutrasferramentas.Oconceitoépoderosoemaduro,comblocosbemdefinidos.SistemascomoHadoop,Mesos,GoogleKuberneteseDockerutilizamestesprincípiosparaconstruiraplicaçõesmodulares.VamosnosaprofundarnoDockereseuecossistemanorestodestecapítulo.
ODockeréumprojetodecódigoabertoquedefineumfluxodetrabalhoeintegraçãoparaosrecursosdecontainers,namespaces,gruposeredes.EstefluxoéapresentadoporumaAPIeumprogramadelinhadecomandoqueusaestaAPIparagerenciarociclodevidadecontainers.
Alémdisso,oprojetoforneceumalinguagemparadescreverocontainererepositóriosparaqueasimagenscriadassejamversionadas.Umavezcriadaaimagem,umoumaiscontainers
9.3DOCKER
9.3DOCKER 125
podemserexecutadoscomela,criandomúltiplasinstânciasnamesmamáquina.
VamosusarumexemplodeservidorHTTPemPythonparademonstraracriaçãodeumaimagemeaexecuçãoemumamáquinavirtual.
AmáquinavirtualquevamosutilizaréamesmaemquetestamosoLXC.Apósexecutá-lacomvagrantupeconectarcomvagrantssh,váaodiretório/vagrant/dockerapp.Dentrodele,temosdoisarquivos:Dockerfileehttp_server.py.
DockerfileéonomedoarquivoutilizadopeloDockerparaconstruirumaimagemnovadeumcontainer.AorganizaçãolembraumplaybookdeAnsible.VamosexaminaroDockerfiledonossotesteparaentenderumpoucomais:
FROMubuntu:14.04RUNapt-get-yinstallpythonADDhttp_server.py/http_server.pyCMD["python","/http_server.py"]
AdiretivaFROMindicaqualimagemseráutilizadacomobase.Podesertantoumadesistemaoperacionalquantoumajáconfiguradadealgumaaplicação.
UmadasconvençõespoderosasqueoDockerintroduziufoiaideiaderepositóriosdeimagenscomversionamento.AcadacomandonoDockerfile,umanovaversãolocaldaimagemécriada.
Estaversãoéumacamadaemcimadosistemadearquivosdestaimagem.Comooscontainers,asimagensdoDockersócontêmarquivos,elasnãotêmkerneledrivers─sãooquechamamosdeRootFilesystem.
Todosistemaoperacionalmontaumaimagemquevivenodisco
126 9.3DOCKER
quandoinicializa.Estaimagempodeestarescritadiretamentenosblocosdodiscoouemumarquivoquevivedentrodeoutrofilesystemnodisco.ODockertemferramentasquefacilitamacriaçãoincrementaleoversionamentodestesarquivos.
ApósescolherosistemaoperacionalUbuntu14.04useiadiretivaRUNparainstalaroPythoneADDparaadicionarumarquivolocalaumcaminhoespecificado.PorfimutilizeiCMDparaexecutaromeuprograma.
OutroconceitofundamentaldoDockeréquecadacontainerexecutaumprocessoapenas.Oprincípioderesponsabilidadeéimportante:containersnãosãomáquinasvirtuaiseaconvençãoutilizadapeloDockerédequeelesnãotêmnemacessoSSH.
Esteprincípioeafacilidadedecriareinstanciarcontainerspermitemacomposiçãoeagregaçãodecontainersemarquiteturascomplexas,quepodemserreaproveitadas.OnomeeminglêsdesteprincipioécomposabilitynadocumentaçãodoDocker.Adianteveremosumaferramentaparaorquestrarmaisdeumcontainereligá-losparacomporaarquiteturadeumaaplicaçãoweb.
Parautilizarumcontainer,temosquefazerobuild.Obuildfazdownloadsdaimagemedascamadasqueacompõemparaorepositóriolocal.
Duranteo,oDockervaiemitirváriosnúmerosprecedidosde--->,quesãoIDsdeoperaçõesdoDocker.Estesnúmerossãoareferênciaparaascamadaseparaaimagemfinal.Vamosusarocomandobuildparacriarnossaimagem,dentrododiretóriodockerapp:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerbuild.SendingbuildcontexttoDockerdaemon4.096kBSendingbuildcontexttoDockerdaemonStep0:FROMubuntu:14.0414.04:Pullingfromubuntu
9.3DOCKER 127
ubuntu:14.04:Theimageyouarepullinghasbeenverified.Important:imageverificationisatechpreviewfeatureandshouldnotbereliedontoprovidesecurity.
Status:Downloadednewerimageforubuntu:14.04
Step1:RUNapt-get-yinstallpython
Readingpackagelists...Buildingdependencytree...Readingstateinformation...Thefollowingextrapackageswillbeinstalled:libpython-stdliblibpython2.7-minimallibpython2.7-stdlibpython-minimalpython2.7python2.7-minimalSuggestedpackages:python-docpython-tkpython2.7-docbinutilsbinfmt-supportThefollowingNEWpackageswillbeinstalled:libpython-stdliblibpython2.7-minimallibpython2.7-stdlibpythonpython-minimalpython2.7python2.7-minimal0upgraded,7newlyinstalled,0toremoveand0notupgraded.Needtoget3734kBofarchives.
Apósaatualizaçãodosrepositórioseainstalaçãodospacotes:
Settinguppython-minimal(2.7.5-5ubuntu3)...Settinguppython(2.7.5-5ubuntu3)...
Step2:ADDhttp_server.py/http_server.py
Step3:CMDpython/http_server.py
Todosospassos(Step)foramexecutadoscomsucessoenossaimagemfoicriadalocalmentecomoID .ODocker
128 9.3DOCKER
provêabstraçõesparecidascomasdosistemaoperacionalparagerenciarinstânciasdecontainers.Umadelaséocomandops:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerpsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
Nãotemosnenhumcontainersendoexecutado.AscolunasindicamumIDdeexecução,oIDdaimagem,qualcomandoestecontainerestáexecutando,status,portasderedeexpostaseumnometemporário.AsoperaçõessobreestecontaineremexecuçãodevemserfeitasutilizandooCONTAINERIDouoNAMEdadoaele,nãooIDouNAMEdaimagemoriginal.
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerrun
^CTraceback(mostrecentcalllast):File"/http_server.py",line39,in<module>ReuseAddrTCPServer(("",PORT),ServerHandler).serve_forever()File"/usr/lib/python2.7/SocketServer.py",line236,inserve_foreverpoll_interval)File"/usr/lib/python2.7/SocketServer.py",line155,in_eintr_retryreturnfunc(*args)KeyboardInterrupt
Ocontainerpodeserexecutadoemforegroundouembackgroundoudetached.Nachamadaanterior,executeiemforegroundeoterminalficoupresoaele.UsandoCONTROL+Ceuaborteiaexecuçãoevoutentarnovamentecomachave-d(detach):
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerrun-d
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerpsCONTAINERIDIMAGECOMMANDPORTSNAMES
:latest"python/http_server
CREATEDSTATUSsecondselated_bohr
9.3DOCKER 129
Ocomandodockerpsmostraainstânciadaimagem2836de6b7707,versãolatest,sendoexecutada.Nenhumaportafoiexposta,portantonãoconseguimosacessaraaplicação.Vamosmatareexecutarestecontainerdaformacorreta.
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerkill
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerrun-d
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerpsCONTAINERIDIMAGECOMMANDPORTSNAMES
CREATED2secondsagoUp1seconds0.0.0.0:10000->10000/tcp
STATUStrusting_lovelace
Nestaexecução,useiaopção-dparaqueocontainerexecuteembackground,eaopção-p,equivalenteàdiretivaEXPOSEquepoderiaserinseridanoDockerfileparaindicarqualportadocontainerqueroexporequalportadohostéaequivalente.Nestecaso,http_server.pyéumprogramaqueabreaporta10000eeuopteipormanteramesmaportanohost.Aordemé-pporta_do_host:porta_do_container.
Faltaumteste,feitonohost:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#curl-vlocalhost:10000*RebuiltURLto:localhost:10000/*HostnamewasNOTfoundinDNScache*Trying127.0.0.1...*Connectedtolocalhost(127.0.0.1)port10000(#0)>GET/HTTP/1.1>User-Agent:curl/7.35.0>Host:localhost:10000>Accept:*/*>
130 9.3DOCKER
*Connection#0tohostlocalhostleftintact<html><body><formaction='/'method=POST><textareaname=msgrows='10'cols='100'></textarea><br><inputtype='submit'name='submit'></form></body></html>
Nomomentodobuild,poderíamosterusadoocomando:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerbuild-tpython_app.
Achave-tdáumnomearbitrárioaestebuildquepodeserusadonolugardoID.
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerrun-d-p5000:10000python_app
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerpsCONTAINERIDIMAGECOMMANDPORTSNAMES
python_app:latest"python/http_server
CREATEDSTATUS5secondsagoUp4seconds0.0.0.0:5000->5000/tcphigh_sammet
Podemosinspecionarocontainercomocomandoinspect,queretornaumJSONcomtodososdadossobreainstânciaoudadosespecíficos:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerinspecthigh_sammet[{"AppArmorProfile":"","Args":["/http_server.py"],"Config":{"AttachStderr":false,"AttachStdin":false,"AttachStdout":false,"Cmd":["python","/http_server.py"],
...
"Path":"python",
9.3DOCKER 131
"ProcessLabel":"","ResolvConfPath":"/var/lib/docker/containers/
resolv.conf","RestartCount":0,"State":{"Dead":false,"Error":"","ExitCode":0,"FinishedAt":"000 - - :00: ","OOMKilled":false,"Paused":false,"Pid":9 ,"Restarting":false,"Running":true,"StartedAt":"2015- - : : . "},"Volumes":{},"VolumesRW":{}}]
VamospegaroIPinterno,portaemapeamento:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerinspect-f'{{.NetworkSettings.IPAddress}}'high_sammet
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerporthigh_sammet10000/tcp->0.0.0.0:5000
Nocomandoinspect,passamosocaminhodoJSONdamesmaformaqueostemplatesJinja2doAnsible.Ocomandoportmostrouomapeamentocriadodeorigemedestino.
Nostrêsúltimoscomandos,useionomeatribuídopelodockeraestecontainer.Comestesdados,podemosconfigurarnossonginxlocalparaserviraaplicaçãoutilizandoatécnicadeproxyreverso.Destaforma,poderíamostermaisinstânciasdaaplicaçãorodandoemcontainerseonginxcuidandodacomunicaçãocomomundoexterior.
Paraficarcompleto,sóprecisamosdeumaformadeatualizara
132 9.3DOCKER
configuraçãodonginxtodavezquenovoscontainersexecutaremoufinalizarem.
Vamosusarumaconfiguraçãoestáticacomapenasumbackenddecontainer:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#cpapp.conf/etc/nginx/sites-available/root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#ln-s/etc/nginx/sites-available/app.conf/etc/nginx/sites-enabled/root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#/etc/init.d/nginxrestart*Restartingnginxnginx...done.
Abraobrowserdesuamáquinaemhttp://192.168.33.2euseaaplicação.Aconfiguraçãodonginxesperaumbackendouvindonaporta5000,queéumaportacomforwarddaporta10000docontainer.Nohost,inspecioneocontainer,osprocessoselogsgeradosporele.
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#dockerlogs
Onomedocontainerdevemudardeacordocomseusistemaoperacional.EleéselecionadoaleatoriamentepeloDocker.Sevocêolharologdonginxveráumaentradasemelhanteaesta:
root@vagrant-ubuntu-trusty-64:/vagrant/dockerapp#tail-f/var/log/nginx/app.access.log
9.3DOCKER 133
SevocêcriarumacontanoDockerHub(https://registry.hub.docker.com/),poderáusarocomandocommit,epushpodecolocarsuaimagemnoRegistrye,dessaforma,permitirqueoutrosusuáriosexecutemsuaaplicação.
ODockerHubéumrepositórioquefuncionadeformasemelhanteaoGit.Vocêpodeutilizá-loparaencontrarimagensdeaplicaçõescompletasecomelascomporsuasprópriasimagens.VocêpodeterumRegistryprivadotambém,instaladoemsuainfraestrutura,casosuasimagenscontenhamsoftwareproprietáriooudadossensíveis.
AdocumentaçãodoDockerécompletaecontémexemplosinteressantesjuntoaboaspráticasatualizadas.SugiroseguiroUserGuide(https://docs.docker.com/userguide/)paraentendermelhoromodeloderedes(Networking)edeassociação(Link)doscontainers.
Nasessãoanterior,euuseiumamáquinavirtualnoVagrantparatrabalharcomoDocker.Euprefiroestecaminhopoisomesmoplaybookqueuseiparacriarestamáquinavirtualserviráparacriareconfigurarmeusservidoresemprodução.
Masdependendodoseusetupvocêpodequererexecutaroscontainersforadoseusistemaoperacionaleterumaexperiênciaparecidacomexecutando-oslocalmente.
ODockerpermiteoacessodoclientedelinhadecomandoaAPIsremotas.BaseadonissofoicriadooprojetoBoot2Docker,quenadamaisédoqueumamáquinavirtualeumconjuntodeconfiguraçõesparaoVirtualBoxquepermiteenviarcomandosao
9.4BOOT2DOCKER
134 9.4BOOT2DOCKER
DockersemestaremumasessãoSSHdentrodamáquinavirtual.
OBoot2DockerésuportadopelaempresaDockereatualizadoconstantemente.PodeserumaboaopçãocasovocêestejaemumambientesemVagrantouqueiraseguirosexemplosdadocumentaçãodoDockersemsepreocuparemmontaraconfiguraçãodamáquinavirtual.
Asinstruçõesparainstalação(https://docs.docker.com/installation/mac/)detalhamesteconceitoelembramqueoBoot2Dockeréumambientededesenvolvimento─nãodeveserutilizadoemprodução.Éumaalternativaaométodoqueapresenteietemomesmocomportamento.EmvezdeexecutaroscomandosemumasessãoSSH,vocêpoderáexecutá-losnoterminaldoseuMACouLinux.
Alémdogerenciamentodecontainers,oDockertemferramentasparausodesuaAPIeprovisionamentodesistemas.VamosusaroDockerComposeparaprovisionarumWordPresscomofizemosanteriormente.
Provisionaraplicaçõesemcontainersrequermodificaçõesparaconvençõesqueseaproximemdopadrão12FactorApp(http://12factor.net/).
Éumaabordageminteressanteparaaarquiteturadeaplicaçõesequeuseiduranteolivroparaalgumasescolhas,porexemplo,proxyreversoecódigosquepodemreceberumaportaparaouvirtantoporconfiguraçãoquantoporvariáveisdeambiente.
Esteiteméchamadodeportbinding(http://12factor.net/port-binding)nadocumentaçãoeéaoquevamosnosatentarparacriar
9.5CRIANDONOSSOCONTAINERDEPHPENGINXEUSANDOODOCKERHUB
9.5CRIANDONOSSOCONTAINERDEPHPENGINXEUSANDOODOCKERHUB 135
umambientecomWordPressnoDocker.
AmaioriadasaplicaçõesaceitaumaportaparaouvirHTTPqueestádentrodocódigo(errado)ouemumarquivodeconfiguração(melhordoquehardcoded).Aespecificaçãosugerequeaplicaçõesnãodevemterportasfixaspoisnãohálocalidadefixaparaseremexecutadas.
Selevarmosissoparaocontextodecontainers,anteriormentetivemosquefalarparaosistemaoperacionalrelacionarumaportadohostcomumaportainternadocontainer.TodocontainertemumendereçoIPinválidoeacessaomundoexterioratravésderegraseinterfacesconfiguradasnohost.
Asaplicaçõesnestemodelosãocomponentesqueescalampelomodelodeprocessosecontainers,oumesmomáquinasvirtuais.Considerandoqueestessãorecursoscomputacionais,poderíamosexecutarumcomponenteondehouvessecapacidadecomputacionaldisponível.
Seaportaoualgumrecursoforfixooulimitadoporlocaisondeasregrasderedeexistamouloadbalancersqueutilizamsticky-bitsessions(edevemsaberexatamenteaondemandamcadacliente)estaflexibilidadedeprovisionamentoficaprejudicada.
ODockerComposeassumequeusaremosimagensqueestãonoDockerHub.VamoscriarumaimagemparaexecutarprogramasemPHP,criarumacontanoDockerHubemandá-laparalá.Posteriormente,usaremosestaimagemeaimagempadrãodeMySQLfornecidapeloDockerparaexecutaresteblog.
CrieumacontanoDockerRegistry(https://registry.hub.docker.com/),comsuascredenciais.
Norepositóriodestecapítulocrieiumdiretóriochamadophp5-fpm-nginxdentrodorepositóriodamáquinavirtualparaDocker.Lá
136 9.5CRIANDONOSSOCONTAINERDEPHPENGINXEUSANDOODOCKERHUB
existeumDockerfilequecriaumaimagemdenginxePHP5-FPM.Estaimagemrecebeumvolumeexterno(https://docs.docker.com/userguide/dockervolumes/)comaaplicaçãoemPHP,portantopodeserutilizadaparaserviroutrasaplicaçõesalémdoWordPress.
Vamosusaramáquinavirtualcriadaanteriormente.Conectecomvagrantssheváaodiretório/vagrantdamáquinavirtual.Entrenodiretóriophp5-fpm-nginxefaçaobuilddesuaimagem:
$sudodockerbuild-tphp5-fpm-nginx.
Apósalgumasmensagensdelog,aimagemestarácriadalocalmente:
$sudodockerbuild-tphp5-fpm-nginx.SendingbuildcontexttoDockerdaemon26.17MBSendingbuildcontexttoDockerdaemonStep0:FROMubuntu:14.04
Step1:RUNapt-getupdate&&apt-get-yinstallphp5-fpmphp-configphp5-mysqlnginx--->Usingcache
Step2:ADDdefault/etc/nginx/sites-available/default--->Usingcache
Step3:CMD/etc/init.d/nginxstart&&php5-fpm-F--->Usingcache
Paratestar,aindadentrodomesmodiretórioexecute:
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerpsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerrun-d-p80:80-v/vagrant/php5-fpm/simple:/appphp5-fpm-nginx
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerpsCONTAINERIDIMAGECOMMAND
9.5CRIANDONOSSOCONTAINERDEPHPENGINXEUSANDOODOCKERHUB 137
PORTSNAMES5 php5-fpm-nginx:latest"/bin/sh-c'/etc/in
CREATEDSTATUS2secondsagoUp1seconds0.0.0.0:80->80/tcpelated_kirch
Abraohttp://192.168.33.2/nobrowserevejaapáginadephpinfogeradaporestaaplicação.VamossubmeterestaimagemaorepositóriopúblicodoDocker.Oprimeiropassoéfazerseulogin,comosdadosdacontaquefoicriadaanteriormente:
#dockerloginUsername:gleiconPassword:Email:[email protected]:logincredentialssavedin/home/vagrant/.dockercfg.LoginSucceeded
ExistemalgumasmaneirasdecriarumaimagemnoDockerHub.Aquevamosusaréconstruirpartirdaexecuçãoumcontainerexistente.Outramaneiraqueveremoséoprocessodebuild,masquerodemonstraralgumasinteraçõescomodockerdaemon.
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#sudodockerrun-d-p80:80php5-fpm-nginx
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerpsCONTAINERIDIMAGECOMMAND
CREATEDSTATUS2secondsagoUp2seconds0.0.0.0:80->80/tcpserene_sammet
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#sudodockercommit-m"created/app"-a"GleiconMoraes"
1cgleicon/php5-fpm-nginx
OID1céoIDdocontainerquevamosusarparacriarnossaimagemnoDockerHub.Opróximopassoéadicionarestecontaineraumaimagem:
$sudodockercommit-m"created/app"-a"GleiconMoraes"
138 9.5CRIANDONOSSOCONTAINERDEPHPENGINXEUSANDOODOCKERHUB
PodemosverasimagenscriadaslocalmenteeaimagemquequeremosenviarparaoDockerHub:
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerimagesREPOSITORYTAGIMAGEID
CREATEDVIRTUALSIZE8secondsago256MB5minutesago256MB49minutesago256MB53minutesago256MB57minutesago256MB2daysago188.3MB
Vamostestarlocalmenteantesdefazeropush:
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#sudodockerrun-d-p80:80-v/vagrant/php5-fpm/simple:/app-t-igleicon/php5-fpm-nginx
Bindfor0.0.0.0:80failed:portisalreadyallocatedroot@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerpsCONTAINERIDIMAGECOMMANDPORTSNAMES
CREATEDSTATUSAboutaminuteagoUpAboutaminute0.0.0.0:80->80/tcpserene_sammet
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerkillserene_sammetserene_sammetroot@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#sudodockerrun-d-p80:80-v/vagrant/php5-fpm/simple:/app-t-igleicon/php5-fpm-nginx
9.5CRIANDONOSSOCONTAINERDEPHPENGINXEUSANDOODOCKERHUB 139
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#dockerpsCONTAINERIDIMAGEPORTSNAMES
COMMANDCREATED"/bin/sh-c'/etc/in2secondsago
STATUSUp1seconds0.0.0.0:80->80/tcpserene_archimedes
root@vagrant-ubuntu-trusty-64:/vagrant/php5-fpm-nginx#
Quandotentamosexecutaranossaimagem,ocorreuumerroporqueaportaestavaemuso.Esteéumdosproblemasdeterportasfixas.Comocomandokillmatamosocontainerqueestavaemexecuçãoetentamosnovamente.Naexecução,passamosovolumedaaplicaçãosimples.Seacessarhttp://192.168.33.2/pelobrowser,apáginadeveabrirnormalmente.
Comaimagemcriada,vamosenviaranossacontanoDockerHub.Substituaomeuloginpeloseu:
$sudodockerpushgleicon/php5-fpm-nginx
Apósalgumtempo,suaimagemestarápresenteemseurepositóriodeformasemelhanteaomeu:
140 9.5CRIANDONOSSOCONTAINERDEPHPENGINXEUSANDOODOCKERHUB
Figura9.2:DockerHub
Asaídadocomandopushdevesersemelhanteaesta:
$sudodockerpushgleicon/php5-fpm-nginxThepushreferstoarepository[gleicon/php5-fpm-nginx](len:1)
Sequiséssemoscriaraimagemnoprocessodebuild,usaríamos:
$dockerbuild-tgleicon/php5-fpm-nginx.$dockerpushgleicon/php5-fpm-nginx
9.6DOCKERCOMPOSE
9.6DOCKERCOMPOSE 141
Namesmamáquinavirtual,executeainstalaçãodoDockerComposedeacordocomasinstruçõesdositeparaseusistemaoperacional(https://docs.docker.com/compose/install/).
vagrant@vagrant-ubuntu-trusty-64:~$sudo-sroot@vagrant-ubuntu-trusty-64:~#curl-Lhttps://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname-s`-`uname-m`>/usr/local/bin/docker-compose
%Total%Received%XferdAverageSpeedTimeTimeDloadUploadTotalSpent
TimeCurrentLeftSpeed
--:--:-- k
root@vagrant-ubuntu-trusty-64:~#chmod+x/usr/local/bin/docker-composeroot@vagrant-ubuntu-trusty-64:~#docker-composehelpGethelponacommand.
Usage:helpCOMMANDroot@vagrant-ubuntu-trusty-64:~#
Sóuseestemododeinstalaçãoseconfiarabsolutamentenaorigemeemumambienteisolado.Executarumshellscriptdiretamentedainternetnãoéumaboaprática.
Comoexercício,vocêdevecriarumplaybookdoAnsiblequefaçadownloaddoscript,confiraomd5efaçaumainstalaçãodeformacontroladacomprivilégiosmenoresdoqueroot.
Paraefeitodidático,estouinstalandoemumamáquinavirtualisoladadomeuambientededesenvolvimentoedeproduçãoparaevitarproblemasdecomprometimento.
Emseguida,vamosfazerdownloaddaversãomaisrecentedoWordPress:
$mkdirwordpress-compose
142 9.6DOCKERCOMPOSE
$cdwordpress-compose/$curlhttps://wordpress.org/latest.tar.gz|tar-xvzf-$ls-lls-ltotal4drwxr-xr-x5nobodynogroup4096Apr2717:14wordpress
VamosusarnossocontainerdePHPeocontainerdeMySQLpadrãodoDocker.TemosquecriaraconfiguraçãodocomposeefazerumapequenaalteraçãonoWordPress.Paratanto,vamoscriarnestediretórioumarquivochamadodocker-compose.yml:
db:image:mysql:latestexpose:-" 6"ports:-" 7: 6"environment:MYSQL_DATABASE:wordpressMYSQL_USER:wordpressMYSQL_PASSWORD:wordpressMYSQL_ROOT_PASSWORD:aaa123web:image:gleicon/php5-fpm-nginxports:-"80:80"links:-dbvolumes:-./wordpress:/app
EstearquivousaomesmoformatoqueoAnsible,YAML,edescrevedoiscomponentesdanossaarquitetura:webedb.Ocomponentewebéanossaimagemdephp5-fpm-nginxcomoWordPress.OMySQLéumaimagemoficialmantidapelotimedoDocker.Existemimagensoficiaisparamuitosprogramas,valeapenaexploraroDockerHub.JuntoaosdadosdaimagemdoMySQLpasseiosdadosdeusuáriosesenha.
Naconfiguraçãodocomponenteweb,oitemchamadolinksavisaqueestecontainerdependedocontainerdb.Nãoéuma
9.6DOCKERCOMPOSE 143
dependênciadeordemdeexecuçãomasdeligação.
Osdadosdoscomponentesdaarquiteturaserãodisponibilizadosdentrodoambientedocontainer,emvariáveisdeambiente.Omesmotipoquecriamoscomocomandoexportdobash.AsaplicaçõesterãoIPsinválidoseestesdadossóestarãodisponíveisnomomentodeexecução.Éumamaneiradenãoterquegerararquivosdinâmicosdeconfiguraçãooutrocá-losatodomomento.
VamoseditarumarquivodoWordPressparaadequá-losaesteparadigma.Emumainstalaçãodeprodução,estepassodeveserautomatizadoeversionadoparapossibilitarupgradesepatchesdesegurança.
Dentrododiretóriowordpress,crieoarquivowp-config.phpcomoconteúdoaseguir:
<?php//**MySQLsettings-Youcangetthisinfofromyourwebhost**///**ThenameofthedatabaseforWordPress*/define('DB_NAME','wordpress');
/**MySQLdatabaseusername*/define('DB_USER','wordpress');
/**MySQLdatabasepassword*/define('DB_PASSWORD','wordpress');
/**MySQLhostname*/define('DB_HOST','db: 6');
/**DatabaseCharsettouseincreatingdatabasetables.*/define('DB_CHARSET','utf8');
/**TheDatabaseCollatetype.Don'tchangethisifindoubt.*/define('DB_COLLATE','');
/*MySQLdatabasetableprefix.*/$table_prefix='wp_';
144 9.6DOCKERCOMPOSE
/*AuthenticationUniqueKeysandSalts.*//*https://api.wordpress.org/secret-key/1.1/salt/*/define('AUTH_KEY','putyouruniquephrasehere');define('SECURE_AUTH_KEY','putyouruniquephrasehere');define('LOGGED_IN_KEY','putyouruniquephrasehere');define('NONCE_KEY','putyouruniquephrasehere');define('AUTH_SALT','putyouruniquephrasehere');define('SECURE_AUTH_SALT','putyouruniquephrasehere');define('LOGGED_IN_SALT','putyouruniquephrasehere');define('NONCE_SALT','putyouruniquephrasehere');
/*WordPressLocalizedLanguage.*/define('WPLANG','');
/*AbsolutepathtotheWordPressdirectory.*/if(!defined('ABSPATH'))define('ABSPATH',dirname(__FILE__).'/');
/*SetsupWordPressvarsandincludedfiles.*/require_once(ABSPATH.'wp-settings.php');
AvariávelDB_HOSTtemovalordb,queseráapresentadoaocontainerwebcomooIPdocontainerdeMySQL.Odocker-composecriaentradasparaevitarousodoIPdiretonaconfiguração.
Vamosexecutarodocker-compose:
$docker-composeup
Apósalgunsminutos,vocêdeveterumasaídaparecidacomesta,seguidadelogsdeaplicação:
root@vagrant-ubuntu-trusty-64:/vagrant/wordpress-compose#docker-composeupCreatingwordpresscompose_db_1...Pullingimagemysql:latest...latest:Pullingfrommysql
9.6DOCKERCOMPOSE 145
mysql:latest:Theimageyouarepullinghasbeenverified.Important:imageverificationisatechpreviewfeatureandshouldnotbereliedontoprovidesecurity.
Status:Downloadednewerimageformysql:latestCreatingwordpresscompose_web_1...Attachingtowordpresscompose_db_1,wordpresscompose_web_1
Noseubrowser,acessehttp://192.168.33.2:800/eainstalaçãobásicadoWordPressdeveaparecer.Oseuterminalficoucomoslogsdosdoiscontainerspoisnãoexecutamosodocker-composecomdetach.VamosaproveitarestavisãoparanavegarnoWordPresseveroslogsproduzidos.Parainterromperoscontainers,useCONTROL+C.
Apósaprimeiraexecução,vocêpodereiniciarcomocomando:
$sudodocker-composestartStartingwordpresscompose_db_1...Startingwordpresscompose_web_1...
Emoutroterminalconectadoàmáquinavirtualexecutevagrantssheoscomandosaseguir:
dockerpsCONTAINERIDIMAGEPORTSNAMES
COMMANDCREATED"/bin/sh-c'/etc/in3minutesago"/entrypoint.shmysq3minutesago
146 9.6DOCKERCOMPOSE
STATUSUpAboutaminute0.0.0.0:80->80/tcpwordpresscompose_web_1
Comosnomesdoscontainers,vamosinvestigarasvariáveisdeambienteemcadaumdeles.Elasforamcriadaspelodocker-compose.Paraexecutarcomandosdentrodeumcontaineremexecução,usamosdockerexec<nome-do-container>env.
root@vagrant-ubuntu-trusty-64:/vagrant/wordpress-compose#dockerexecwordpresscompose_web_1envPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WORDPRESSCOMPOSE_DB_1_PORT_3306_TCP_PROTO=tcpWORDPRESSCOMPOSE_DB_1_NAME=/wordpresscompose_web_1/wordpresscompose_db_1WORDPRESSCOMPOSE_DB_1_ENV_MYSQL_PASSWORD=wordpressWORDPRESSCOMPOSE_DB_1_ENV_MYSQL_ROOT_PASSWORD=aaa123WORDPRESSCOMPOSE_DB_1_ENV_MYSQL_USER=wordpress
9.6DOCKERCOMPOSE 147
WORDPRESSCOMPOSE_DB_1_ENV_MYSQL_DATABASE=wordpressWORDPRESSCOMPOSE_DB_1_ENV_MYSQL_MAJOR=5.6WORDPRESSCOMPOSE_DB_1_ENV_MYSQL_VERSION=5.6.24HOME=/root
root@vagrant-ubuntu-trusty-64:/vagrant/wordpress-compose#dockerexecwordpresscompose_db_1envPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYSQL_PASSWORD=wordpressMYSQL_ROOT_PASSWORD=aaa123MYSQL_USER=wordpressMYSQL_DATABASE=wordpressMYSQL_MAJOR=5.6MYSQL_VERSION=5.6.2HOME=/root
Usandoasvariáveisdeambienteexportadasnocontainer,poderíamoscriarumaaplicaçãocomzeroconfiguraçãoporarquivo.Todososdadosdosbancosedoambienteestãolá.
Nocontainerdobanco,temosasvariáveisquedeclaramosnodocker-compose.yml,MYSQL_DATABASE.Vamosinspecionarosprocessosdocontainerweb:
root@vagrant-ubuntu-trusty-64:/vagrant/wordpress-compose#dockerexecwordpresscompose_web_1ps-efUIDPIDPPIDCSTIMETTY
TIMECMD00:00:00/bin/sh-c/etc/init.d/nginxstart&&php5-fpm-F00:00:00nginx:masterprocess/usr/sbin/nginx00:00:00nginx:workerprocess00:00:00nginx:workerprocess00:00:00nginx:workerprocess
148 9.6DOCKERCOMPOSE
00:00:00nginx:workerprocess00:00:00php-fpm:masterprocess(/etc/php5/fpm/php-fpm.conf)00:00:00php-fpm:poolwww00:00:00php-fpm:poolwww00:00:00ps-ef
PodemosnosconectardamaquinavirtualaoMySQLdocontainer:
$sudoapt-getinstallmysql-clientroot@vagrant-ubuntu-trusty-64:/vagrant/wordpress-compose#mysql--protocol=TCP-uwordpress--host=localhost-P3 wordpress-pEnterpassword:ReadingtableinformationforcompletionoftableandcolumnnamesYoucanturnoffthisfeaturetogetaquickerstartupwith-A
WelcometotheMySQLmonitor.Commandsendwith;or\g.YourMySQLconnectionidis3Serverversion:5.6.24MySQLCommunityServer(GPL)
Copyright(c)2000,2015,Oracleand/oritsaffiliates.Allrightsreserved.
OracleisaregisteredtrademarkofOracleCorporationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners.
Type'help;'or'\h'forhelp.Type'\c'toclearthecurrentinputstatement.
mysql>showtables;+-----------------------+|Tables_in_wordpress|+-----------------------+|wp_commentmeta||wp_comments||wp_links||wp_options||wp_postmeta||wp_posts||wp_term_relationships||wp_term_taxonomy||wp_terms||wp_usermeta||wp_users|+-----------------------+
9.6DOCKERCOMPOSE 149
11rowsinset(0.00sec)
mysql>selectpost_titlefromwp_posts;+--------------+|post_title|+--------------+|Helloworld!||SamplePage||AutoDraft||elposto||elposto|+--------------+5rowsinset(0.00sec)
Parafinalizar,vamosusaroqueaprendemosnocapítuloanteriorparaprovocarumacarganonossoblogeexaminarcomoosprocessosaparecemnamáquinavirtualqueestárodandooDocker.Emumterminallocalforadamáquinavirtual,execute:
$whiletrue;doab-c20-n200http://192.168.33.2 /;sleep5;done
ObservequeosprocessosdePHP5-FPMeMySQLaparecemnotopdohost,masquandoexecutamosps-efnocontainerwebnãovimosprocessosdohostlá.
Figura9.3:topnohostdoDocker
150 9.6DOCKERCOMPOSE
Seexecutarmosocomandopsnovamente:
$sudodockerexecwordpresscompose_web_1ps-ef
Obufferdelogdokernelteráaseguintemensagem:
$sudodmesg-T....
apparmor="DENIED"operation="ptrace"profile="docker-default"pid=25136comm="ps"requested_mask="trace"denied_mask="trace"peer="docker-default"
Esteéumdosdispositivosparacontrolaroacessodeaplicaçõesecontainerssendoexecutadosemisolamentodenamespaces.
ApósoDocker,outrasferramentasdevirtualizaçãoeisolamentodeprocessossurgiramegrandesempresascomoAmazon,MicrosofteGoogleinvestiramtempoedinheiroparaproverserviçoseferramentascompatíveis.
OAnsiblepossuiumainterfacebásicacomoDockereemalgunsprovedoresdeserviçovocêpodeexecutarsuasimagensdiretamente,semterquecomprarumamáquinavirtual.
ContainerstambémsãoabasedeserviçoscomooHeroku,umaplataformaparaaplicaçõesweb.Éumaferramentaimportanteenãotãonovaqueestápassandoporumrenascimento.
Valeapenaentendercomooscontainerspodemajudarnaflexibilidadeeeficiênciadesuaaplicação.Nestetópico,conhecimentosdesistemaoperacional,performance,profilingearquiteturasemisturamenãopodemviversemautomaçãosoboriscodeprocedimentoscomplexosimpediremocrescimentoeoperaçãodosseussistemas.Lembre-sedequeacoletademétricastambémfacilitaousoeacriaçãodecontainerssobdemanda.
9.7CONCLUSÃO
9.7CONCLUSÃO 151
152 9.7CONCLUSÃO
CAPÍTULO10
Estecapítulotemalgumasconsideraçõessobreousodoqueaprendemosemprodução.Tudooquevimosduranteolivrofoipensadoecriadocombaseemexperiênciarealdeprodução,mascadaorganizaçãotemsuasregras.Oobjetivodasferramentasquevimoséaumentaraeficiênciadeformainteligente.
VamoscomeçarpeloqueoAnsiblechamadeinventoryfile,onossohosts.ini.Vocêpodeorganizarsuasmáquinasdemaneirasdiferentes,maseurecomendoqueoinventoryfilereflitaaarquiteturadoseusistemacomnomessignificativos,porexemplo:
[loadbalancer]10.0.0.1[web]10.0.0.210.0.0.3[db]10.0.0.410.0.0.5
NoscapítulosemquefizeramdeploynaAWSeDigitalOcean,vimosdynamicinventoriesnosquaisohosts.inierasubstituídoporscriptsoudadosemmemória.OAnsiblepossuiumaAPIquepodeseracessadacomalinguagemPythoneestesdadospodemserarmazenadosemdatastorescomoRediseMySQL.
RecomendotambémestudaroAnsibleTowereoutros
EMPRODUÇÃO
10.1DEPLOY
EMPRODUÇÃO 153
componentesdoecossistemaparagerenciarseusserviços.VocêpodeconstruirAPIsquegeremosinventoryfilesdinamicamenteecoletardadosdeusodasAPIsdeIaaSdisponíveisemseuprovedor.ValeapenaaprenderausaralinguagemPythonparaconstruirmódulosdoAnsible.
AlgunsprovedorescomoDigitalOcean,AzureeAmazonoferecemcódigosdedescontosecamadasdeserviçocompoucoounenhumcusto.Aproveiteestasofertasparatestarosplaybooksecriarseusprópriosplaybooksemumambientedeprodução.Lembredecriaramonitoraçãodosseussistemas.
BuildingBlockssãounidadesquepodemsercompostasparaconstruircomponentesmaiscomplexos.Éimportantereduzirousodebuildingblocksaelementoscomunscomomáquinasvirtuais,loadbalancers,volumesdestorageeimagens.Pensandoassim,nãoédifícilencontrarequivalênciaentreosprovedoresdeserviço,quegeralmentedãonomesemedidasdistintasaoseusprodutos.
Parademonstrarecobrirumprovedordeserviçosnovo,vamoscriarumconjuntodeduasmáquinasvirtuaiseumloadbalancernoAzure.Comacamadagrátisqueoferecem,épossívelexperimentarseusprodutos,masvamosnoslimitaraomaissimplesesemautomação,paraentenderainterfacedoprovedor:
Apóscriarsuaconta,entrenopaineleselecioneVirtualMachines.Crieduasmáquinascomoperfilmaissimples,sistemaoperacionalUbuntu14.04LTS.Podeusaroatalhocomumgrandesímbolode+nocantoinferioresquerdo:
10.2BUILDINGBLOCKSELOCK-IN
154 10.2BUILDINGBLOCKSELOCK-IN
Figura10.1:AzureVirtualMachines
Useprefixosquefaçamsentidoparavocê,nomeucasogsm-1egsm-2.Vamoscriarumloadbalancer,quenoAzureéchamadodeTrafficManager(ElasticLoadBalancerouELB,noAWS):
10.2BUILDINGBLOCKSELOCK-IN 155
Figura10.2:AzureTrafficManager
Escolhioprefixogsm-all.OTrafficManagerficadentrodeNetworkServices.Onossoficaemgsm-all.trafficmanager.net.NodashboarddoTrafficManager,podemosiremendpointseverqueostatusédegraded,oloadbalancernãoconsegueseconectar.
Precisamosinstalaronginxnasmáquinaseabriraporta80nofirewalldecadauma.
[email protected]$sudoapt-getupdate$sudoapt-getinstallnginx$sudo-s#echo"gsm-1">/usr/share/nginx/html/index.html
[email protected]$sudoapt-getupdate$sudoapt-getinstallnginx$sudo-s#echo"gsm-2">/usr/share/nginx/html/index.html
NainterfacedoAzureváatéVirtualMachineseselecionecadaumadasmáquinas.Nasessãoendpoints,cliqueem+ADDnorodapé
156 10.2BUILDINGBLOCKSELOCK-IN
dapágina.Preenchaaregracomoafiguraaseguir:
Figura10.3:AzureFWRuleCreation
Repitanasegundamáquina.Apósacriaçãodasregras,oTrafficManagerdevetersaídodoestadodegraded.Vamosexecutarumtestelocal:
$whiletrue;docurlgsm-all.trafficmanager.net;sleep5;done
Asaídadestetestedevealternaralgumasvezescomgsm-1egsm-2(ouasstringsquevocêcolocou).NãoédificilautomatizarestaconfiguraçãocomAnsibleouqualqueroutrosistemamasmeuobjetivofoinavegarporumprovedordeserviçodiferentedoqueusamosanteriormenteeidentificarosmesmosbuildingblocks.
Vocêpoderiatersuaaplicaçãoemambosemovercargadeproduçãocasotivesseproblemasouopreçoestivessemelhor.IssoajudaasepreveniroupelomenosaliviarosefeitosdoLock-in.
Lock-inéamedidaquedizqualadependênciadesuaaplicação
10.2BUILDINGBLOCKSELOCK-IN 157
enegócioaoprovedordeserviços.Umadasvariáveiséovolumededadosquevocêtememumprovedor,quepodesercomplexodereplicaroutransferirparaforadele.Pior,podesercaropoisalgunsserviçosnãocobrampelaingestãoetrafegolocaldedadosmascobrampelasaídadedadosoupelabandaconsumida.Outravariávelimportanteéoquantodecódigovocêteriaquefazerparasubstituirumserviçoutilizadocomoporexemplofilasoucaches.
Umdiagramadeblocossimplespodeajudaravisualizarestespontoseplanejaropiorcasopossível:buildingblockssimplescomomáquinasvirtuaiscomcapacidadelimitadaeloadbalancer.Ébomdesenvolverumplanocomestaslimitaçõesparaestimarseépossívelmigrarparaumaestruturainternaouparaoutroprovedor.MuitasempresasinvestememcriarseucloudprivadoporpreocupaçõescomsegurançaouconfidencialidadeeédifícilchegarpertodotrabalhoqueprovedorescomoAzure,GoogleeAWSoferecem.
Ensaieumprocessosimplesdedeployimaginandoquesuaestruturaestáfuncionandoetemclientesemprodução.Sugirocomeçarpeloblue/greendeployquenadamaiséqueduplicarsuaestruturaeutilizaroloadbalancercomopontodetrocadetráfego.LeiamaisnestepostdoMartinFowler(http://martinfowler.com/bliki/BlueGreenDeployment.html).
Estatécnicadeveseradaptadaàaplicaçãoeaoambiente.Emalgunscasos,gostodemanteromesmobancodedadosparaasduasinstânciasdosistemaseasmudançasforemincrementais,emoutrosémelhorpesquisarumamaneiradesincronizardadosparaterosambientescompletamenteseparados.
Emalgunscasos,precisamosempacotarasaplicaçõesparao
10.3BLUE/GREENDEPLOYEPACOTES
158 10.3BLUE/GREENDEPLOYEPACOTES
formatonativodosistemaoperacional.Issopodeserinteressantese,noseupipelinededeploy,suasaplicaçõesprecisamdookdeumtimecomoQAouSegurança.Pesquisesobreoempacotamentodeaplicaçõeseavaliesenãovaleapenacriararquivos.debourpmdesuasaplicaçõesjuntamentecomumrepositóriolocal.
Podeserqueparaalgunscomponentes,porexemploonginx,vocêprecisedeumaversãocustomizadaouqueiratrocarporequivalentescomooOpenResty(http://openresty.org/).ComoAnsible,vocêpodeautomatizaracriaçãodestespacotes.OFPM(https://github.com/jordansissel/fpm)éumaaplicaçãobemlegalparagerarpacotescompoucoatrito.Podeserumpassointermediáriosevocêoptouporcriarimagensparacadaversãodesuaaplicação.
EmprovedorescomoaAmazon,vocêpodeterumabibliotecadeimagenspersonalizadas.Podesermaissimplesterumasequênciaversionadadeimagensdasuaaplicaçãoparaaproveitarrecursoscomoauto-scalingemvezdereconstruiroambientetodavezqueprecisardemaiscapacidade.Avelocidadedealocaçãodecapacidadeeacomplexidadedaconstruçãodecadaelementodoambientedeveserlevadaemconta.
EmseupipelinepodeexistirumpontoemquevocêusaumservidordeintegraçãocomoJenkins(https://jenkins-ci.org/)ouTravis-CI(https://travis-ci.org)verificartestesunitáriosedeintegração.Sevocêaindanãousaesteserviço,pesquiseecomeceausar.ExistemmodalidadesSaaSeinstaladasemsuasmáquinaseelaspodemcontribuircommaisdoqueexecutartestes:podemserumpontoinicialparaimplementarautomaçõesdeentregaedeploy.Vocêsempreterátrêsambientes:desenvolvimento,homologaçãoeprodução.Elespodemseromesmoambientecumprindoestastrês
10.4TESTES
10.4TESTES 159
funções,oquenãoérecomendável,ousegregados.
Procuretestesemétricasquepossamseraplicadosemseuambientedeproduçãoparaqueodesenvolvimentoreflitaascondiçõesreaisdeprodução.Sugiroduasfontes:ChaosMonkeysreleasedintotheWild(http://techblog.netflix.com/2012/07/chaos-monkey-released-into-wild.html)eMetricsEverywhere(https://www.youtube.com/watch?v=czes-oa0yik).ChaosmonkeysfoiarespostadaNetflixàideiadeintroduzirmudançasemambientesdeproduçãoparadescobrirconexõesfrágeisentreoselementosdesuaarquitetura;métricaséarespostadedesenvolvedoresaoutrotipodemonitoraçãoquenãosejareativa,porexemplocontartempoderespostaarequestsHTTPemvezdeapenasmonitoraraporta80.
Benchmarksnormalmentesãoinconclusivosseoambienteeametodologiaaplicadanãodemonstramasdiferençasentrecenáriosoucomponentes(comparardoisframeworksHTTPnãodizmuitoalémdequeelessãodoisframeworksdiferentes).Poroutrolado,valeapenaexecutartestessimplesdecargaeperformanceemseusambientesdeproduçãoeatémesmoantesedepoisdeumamudançasignificativadecódigoemseuambientedehomologação.UmaferramentainteressanteéoAB(ApacheBenchmark).EleestáinstaladopordefaultnoMacOSXetempacotesparaamaioriadasdistribuiçõesLinux.
Afiguraaseguirmostraumaexecuçãoquefizdirecionandoaohttps://www.google.com/comosparâmetros-n100-c10.
160 10.4TESTES
Figura10.4:ApacheBenchnoGoogle
OApacheBenchmarkrepresentadeformasumarizadadadosqueserãoencontradosemoutrossistemasdetestedecargaebenchmark.Euinformeiquequeria100requests(-n100)com10clientessimultâneos(-c10).Oprimeiroblocoinformaversõesdesoftware,tiposdecódigosderetorno,requestsporsegundo,tempomédio(mediana)etransferência.Logoabaixo,umaquebradotempodeconexõesentreconexãoTCP/IP,processamentoeespera.
OúltimoblocoéchamadodePercentageoftherequestsservedwithinacertaintime(ms)etemainformaçãomaisimportantedaexecução,quesãoospercentuaisetemposorganizadosemfaixas.Acolunadaesquerdatemumpercentual,eadaesquerda,umtempo.Significaqueaquantidadeespecificada(50%,60%,70%etc.)dasconexõestevetempoabaixodovaloràdireita.Estainformaçãoémelhorqueamédiadetempodeconexõespoisnosaltospercentuais(90%,95%,99%e99.9%)podemseescondertemposderespostaquecausaminsatisfaçãoeaimpressãodemáqualidadeparaousuáriodesuaaplicação.
10.4TESTES 161
ExecuteoABcontrasuaaplicaçãoutilizandodiferentestamanhosdeinstânciasvirtuaisetambémlocalmentecomoVagrantparaavaliaroimpactodopoderdeprocessamentoeI/Odesuainfraestruturanoresultadofinaldesuaaplicação.
Comovimosanteriormente,usandooNewRelicparamonitorarasrespostaseoABparagerarcargasintéticaconseguimosentendercomooconjuntodeaplicaçãoebancodedadosfunciona.
Existemváriossistemasdetestedecargaetempoderesposta.Eurecomentoconhecerolocust.io(http://locust.io/).ÉumsistemafeitoemPythonquepodeserexecutadolocalouremotamente.
EuprepareiumprojetoparafacilitarseuusonaAWS(https://github.com/gleicon/locust-swarm)queorquestraecriaumsistemacommáquinasvirtuaisparaexecutarostestesdolocust.io.OsagentesdetestesãoprogramasemPythonquepodemserelaboradosesimularlogins,buscaseatividadesqueousuáriofariaemsuaaplicação.
AfiguraaseguiréateladeentradadoLocust,ondeinformamosonúmerodeusuáriosquedevemsersimuladoseataxadecriação(hatching)deles:
162 10.4TESTES
Figura10.5:NovotestenoLocust
Umtesteemexecução:
Figura10.6:NovotestenoLocust
Exploramosestasferramentasanteriormenteeodesafioépensaremcomoelaspoderiamserintegradosnasuarotinadebuild
10.4TESTES 163
etestes.Comoensaiarumperfildetráfegoprojetadoparasuaaplicaçãoeinterrompê-laempontosquesãoopacosaocódigo?Vimosexemplosdecomoreduzirabandaderededeumamáquinavirtualeinjetarumacargasintética.ComopoderíamosfazerissocomaCPUeI/O?
Estecapítuloéumapanhadodeconceitosquevimosduranteolivroealgunstemasquenãoconseguiabordar,masacheiquedeveriamserpelomenoscitados.
Tenteimostrarnestelivroumpoucomaisdoqueasferramentaseintroduzirumframeworkinicialdetrabalhoparaautomaçãodesistemas.Administraçãodesistemaséumaáreadivertidaetemmuitoemcomumcomdesenvolvimentodesistemas.
Otempodereaçãoaproblemasemproduçãoecomclienteséumadasdiferençasepodecriarsituaçõestensasmasaaplicaçãodeautomaçãoedenovasideiasnestecampotemtornadootrabalhobemmaiseficienteeseguro.Éumaoportunidadeúnicadeveroimpactodebugseotimizaçõesemprodução.
Asúltimasgeraçõesdesistemastêmficadocomplexas,senãopeloseuobjetivo,pelomenospelofatodequesãosistemasqueprecisamdemaisdeumamáquinaparaseremexecutados.
Nãotemcomoabordaratarefadeconstruiremanterestesambientesdeformamanualecomparadigmasqueusávamoshádezouvinteanos.Poroutrolado,asferramentasvãoalémdescriptsenigmáticosecombinaçãodescriptsperlcomferramentasdesistemas.
Boasorte!
10.5CONCLUSÃO
164 10.5CONCLUSÃO