ImplementingDevOpsonAWS
TableofContents
ImplementingDevOpsonAWSCreditsAbouttheAuthorAbouttheReviewerwww.PacktPub.com
Whysubscribe?CustomerFeedbackPreface
WhatthisbookcoversWhatyouneedforthisbookWhothisbookisforConventionsReaderfeedbackCustomersupport
DownloadingtheexamplecodeDownloadingthecolorimagesofthisbookErrataPiracyQuestions
1.WhatisDevOpsandShouldYouCare?WhatisDevOps?
AcommongoalSharedknowledge(nosilos)TrustandsharedresponsibilityRespectAutomationReproducibleinfrastructureMetricsandmonitoringContinuousIntegration,Delivery,andDeploymentEmbracingfailure
ShouldyoucareIsthistherighttime?Willitwork?Isitworthit?Doyouneedit?
Summary2.StartTreatingYourInfrastructureasCode
IaCusingTerraformConfigurationTemplatedesign
Resources
VariablesOutputs
OperationsValidationDry-runDeploymentUpdatesRemoval
IaCusingCloudFormationConfigurationTemplatedesign
ParametersResourcesOutputs
OperationsTemplatevalidationDeployingaStackUpdatingastackDeletingastack
Summary3.BringingYourInfrastructureUnderConfigurationManagement
IntroductiontoSaltStackPreparation
WritingConfigurationManagementcodeStatesPillarsGrainsTopfiles
BootstrappingnodesunderConfigurationManagement(end-to-endIaC)Summary
4.Build,Test,andReleaseFasterwithContinuousIntegrationPrepareIaC
TerraformtemplatesVariablesVariables(values)Resources
CreatetheVPCAddnetworkingcomponentsAddEC2nodeandrelatedresources
OutputsSaltStackcode
StatesPillarsMinionconfiguration
DeployIaCSetupCI
JenkinsinitializationWritingademoappDefiningthepipelineSettingupthepipeline
Summary5.Ever-ReadytoDeployUsingContinuousDelivery
PreparingTerraformtemplatesResourcesVariablesVariables(values)Outputs
PrepareingSaltcodeStates
top.slsjenkinsnginx
PillarsMinionconfiguration
PreparingJenkinscodePacker
demo-app.jsondemo-app_vars.jsondemo-app_userdata.sh
Serverspecspec/localhost/demo-app_spec.rb
demo-appdemo-app-cdelivery
PreparingCodeCommitrepositoriesDeployTerraformtemplatesInitializingJenkinsConfiguringJenkinsjobs
demo-apppipelinedemo-app-cdeliverypipeline
Summary6.ContinuousDeployment-AFullyAutomatedWorkflow
Terraformcode(resources.tf)outputs.tf
DeploymentJenkinspipelines
ContinuousDeploymentpipelinecdeployment.sh
Summary
7.Metrics,LogCollection,andMonitoringCentralizedlogging
IngestingandstoringlogswithLogstashandElasticsearchCollectinglogswithElasticsearchFilebeatVisualizinglogswithKibana
MetricsIngestingandstoringmetricswithPrometheusGatheringOSandapplicationmetricswithTelegrafVisualizingmetricswithGrafana
MonitoringAlertingwithPrometheusSelf-remediationwithPrometheusandJenkins
Summary8.OptimizeforScaleandCost
ArchitecturalconsiderationsTheVPC
CIDRSubnetsandAvailabilityZonesVPClimits
ThefrontendlayerThebackendlayerTheobjectstoragelayer
TheloadbalancinglayerCross-zoneloadbalancingELBpre-warmingTheCDNlayerSpotinstancesAWSCalculators
Summary9.SecureYourAWSEnvironment
ManagingaccessusingIAMSecuringtherootaccount
VPCsecuritySecurityGroupsNetworkACLsVPNgatewayVPCpeering
EC2securityIAMRolesSSHaccess
IndividualkeysEntrypoint
ELBseverywhereHTTPSbydefault
EncryptedstorageEBSvolumesS3objects
OSupdatesSecurityauditing
VPCFlowLogsCloudTrailTrustedAdvisorAWSConfigSelfpentesting
Summary10.AWSTipsandTricks
UsingVPCsKeeptheMainroutetableasafallbackStayingwithintheVPCCreatingIAMrolesinadvanceGroupsoverusersKnowingtheAWSservicelimitsPre-warmELBsifneededUsingterminationprotectionTaggingwhatyoucanDeployingacrossmultiplezonesEnhancingyourELBhealth-checksOffloadingSSLontotheELBEIPversuspublicIPMindthefull-hourbillingUsingRoute53ALIASrecordsTheS3bucketnamespaceisglobal-versus.intheS3bucketnameRandomizingS3filenamesInitializing(pre-warm)EBSvolumesSummary
ImplementingDevOpsonAWS
ImplementingDevOpsonAWSCopyright2017PacktPublishing
Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.
Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.
PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.
Firstpublished:January2017
Productionreference:1190117
PublishedbyPacktPublishingLtd.
LiveryPlace
35LiveryStreet
Birmingham
B32PB,UK.
ISBN978-1-78646-014-1
www.packtpub.com
http://www.packtpub.com
Credits
Author
VeselinKantsev
CopyEditor
SafisEditing
Reviewer
MadhuJoshi
ProjectCoordinator
JudieJose
CommissioningEditor
KartikeyPandey
Proofreader
SafisEditing
AcquisitionEditor
NamrataPatil
Indexer
PratikShirodkar
ContentDevelopmentEditor
AbhishekJadhav
Graphics
KirkD'Penha
TechnicalEditor
MohdRiyanKhan
ProductionCoordinator
NileshMohite
AbouttheAuthorVeselinKantsevisaDevOpsprofessionalandaLinuxenthusiastwholivesinLondon,UK.
HisintroductiontoLinuxwasasaSystemAdministratorbackin2006.HisfocusforthepastfewyearshasbeenmostlyoncloudtechnologiesandthetransitionofthecommunityfromanOpstoaDevOpsculture.
HehasworkedwithcompaniesinvarioussectorssuchasDesign,Media,andFinance,specializinginthemigrationofinfrastructureontoAWSandthepromotionofDevOpsprinciplesandpractices.
AbouttheReviewerMadhuJoshi,theVPofCloudServicesatTrillionTechnologySolutions,hasbuilthigh-profilewebsitesinAWSforDoD,Verato,NationalGeospatialAgency(NGA),DHSFEMA,ProQuestSearchSolutions,TheCocaColaCompany,FoodNetwork,Scripps,SpecialOlympics,HomeandGardenTV,andMonumentalSports.Hedesignedthesesitestohandlemillionsofvisitorspermonthandhasusedindustrybestpracticestoprovidepeakcapacityrequiredtoservetheglobalaudience.HealsohasexpertiseinmigratinglargeapplicationssuchastheKickAppssocialmediaplatformandfinancialservicesfromatraditionaldatacentertoAmazon'scloud.
IwouldliketothankPacktPublishingandJudieJoseforgivingmetheopportunitytoreviewthebook.Thishasturnedouttobeagreatbook,andIwanttocongratulatetheauthoronputtingonlotofhardworktomakethebookveryuseful.IamsurethatthereaderswillhaveasmuchfunasIhadreviewingit.
www.PacktPub.comForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.
DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusatservice@packtpub.comformoredetails.
Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.
https://www.packtpub.com/mapt
Getthemostin-demandsoftwareskillswithMapt.MaptgivesyoufullaccesstoallPacktbooksandvideocourses,aswellasindustry-leadingtoolstohelpyouplanyourpersonaldevelopmentandadvanceyourcareer.
http://www.PacktPub.comhttp://www.PacktPub.comhttp://www.PacktPub.comhttps://www.packtpub.com/mapt
Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser
CustomerFeedbackThankyouforpurchasingthisPacktbook.Wetakeourcommitmenttoimprovingourcontentandproductstomeetyourneedsseriouslythat'swhyyourfeedbackissovaluable.Whateveryourfeelingsaboutyourpurchase,pleaseconsiderleavingareviewonthisbook'sAmazonpage.Notonlywillthishelpus,moreimportantlyitwillalsohelpothersinthecommunitytomakeaninformeddecisionabouttheresourcesthattheyinvestintolearn.
Youcanalsoreviewforusonaregularbasisbyjoiningourreviewers'club.Ifyou'reinterestedinjoining,orwouldliketolearnmoreaboutthebenefitsweoffer,pleasecontactus:[email protected].
PrefaceDevOpsandAWSaretwokeysubjectsinthetechindustrythathavebeensteadilygrowinginpopularityinrecentyearsandforagoodreason.
DevOpsisgraduallybecomingthedefactomethodologyorframeworkandisadoptedbyorganizationsofallsizes.Ithasenabledtechnologyteamstoworkmoreefficientlyandmadetheirworkmorerewardingbytighteningthefeedbackloopbetweenthedeveloperandtheenduser.Teammembersenjoyamorepleasant,moreproductiveworkenvironmentthroughmuchincreasedcollaboration.
Inthisbook,wewillfirstexaminethephilosophybehindDevOps,thenproceedwithsomepracticalexamplesofitsmostpopularprinciples.
AWSisnowadayssynonymouswithCloudComputing,sittingatthetopoftheindustrychartswithits31%marketshare.Startingbackin2006,AmazonWebServiceshasevolvedintoalarge,independent,sophisticatedecosystemintheCloud.Itisandhasbeenlaunchingnewservicesatanastonishingrate.TheAWSproductcategoriesrangefromrawcomputeanddatabaseresourcestostorage,analytics,AI,gamedevelopment,andmobileservicestoIoTsolutions.
WewilluseAWSasaplatformtoapplyDevOpstechniqueson.Inthechapterstofollow,wewillseehowtheconvenienceandelasticityofAWSgreatlycomplementstheinnovativeapproachofDevOpstosystemadministrationandapplicationdevelopment.
WhatthisbookcoversChapter1,WhatIsDevOpsandShouldYouCare?,introducestheDevOpsphilosophy.
Chapter2,StartTreatingYourInfrastructureasCode,offersexamplesonhowtodeployinfrastructureascodeusingTerraformorCloudFormation.
Chapter3,BringYourInfrastructureunderConfigurationManagement,demonstrateshowtoconfigureEC2instancesusingSaltStack.
Chapter4,Build,Test,andReleaseFasterwithContinuousIntegration,describestheprocessofsettingupaCIworkflowusingaJenkinsCIserver.
Chapter5,Ever-ReadytoDeployUsingContinuousDelivery,showshowtoextendaCIpipelinetoproducedeployment-readyEC2AMIsusingPackerandServerspec.
Chapter6,ContinuousDeployment-AFullyAutomatedWorkflow,OffersafullyautomatedworkflowandcompletestheCI/CDeliverypipelinebyaddingthefunctionalityneededforAMIdeployment.
Chapter7,Metrics,LogCollection,andMonitoring,introducesPrometheus,Logstash,Elasticsearch,andrelatedDevOpstools.
Chapter8,OptimizeforScaleandCost,offersadviceonhowtoplananAWSdeploymentwithscalabilityandcostefficiencyinmind.
Chapter9,SecureYourAWSEnvironment,coversbestpracticesinordertoimprovethesecurityofanAWSdeployment.
Chapter10,AWSTipsandTricks,containsaselectionofusefultipsforabeginnertoanintermediateAWSusers.
WhatyouneedforthisbookThepracticalexamplesfoundinthisbookinvolvetheuseofAWSresources,thusanAWSaccountwillberequired.
Theclient-sidetoolsusedintheexamples,suchastheAWSCLIandTerraform,aresupportedonmostcommonoperatingsystems(Linux/Windows/MacOS).
WhothisbookisforThisbookisforsystemadministratorsanddeveloperswhomanageAWSinfrastructureandenvironmentsandareplanningtoimplementDevOpsintheirorganizations.ThoseaimingfortheAWSCertifiedDevOpsEngineercertificationwillalsofindthisbookuseful.PriorexperienceofoperatingandmanagingAWSenvironmentsisexpected.
ConventionsInthisbook,youwillfindanumberoftextstylesthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestylesandanexplanationoftheirmeaning.
Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:"WeneedtoSSHintothenodeandretrievetheadminpasswordstoredin/var/lib/jenkins/secrets/initialAdminPassword."
Ablockofcodeissetasfollows:
aws-region="us-east-1"vpc-cidr="10.0.0.0/16"vpc-name="Terraform"aws-availability-zones="us-east-1b,us-east-1c"
Whenwewishtodrawyourattentiontoaparticularpartofacodeblock,therelevantlinesoritemsaresetinbold:
aws-region="us-east-1"vpc-cidr="10.0.0.0/16"vpc-name="Terraform"aws-availability-zones="us-east-1b,us-east-1c"
Anycommand-lineinputoroutputiswrittenasfollows:
$terraformvalidate$terraformplanRefreshingTerraformstatepriortoplan......Plan:11toadd,0tochange,0todestroy.$terraformapplyaws_iam_role.jenkins:Creating......Applycomplete!Resources:11added,0changed,0destroyed.Outputs:JENKINSEIP=x.x.x.xVPCID=vpc-xxxxxx
Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,forexample,inmenusordialogboxes,appearinthetextlikethis:"WeselectPipelineasajobtypeandpickanameforit."
Note
Warningsorimportantnotesappearinaboxlikethis.
Tip
Tipsandtricksappearlikethis.
ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook-whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.
Tosendusgeneralfeedback,[email protected],andmentionthebook'stitleinthesubjectofyourmessage.
Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.
http://www.packtpub.com/authors
CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.
DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesforthisbookfromyouraccountathttp://www.packtpub.com.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
Youcandownloadthecodefilesbyfollowingthesesteps:
1. Loginorregistertoourwebsiteusingyoure-mailaddressandpassword.2. HoverthemousepointerontheSUPPORTtabatthetop.3. ClickonCodeDownloads&Errata.4. EnterthenameofthebookintheSearchbox.5. Selectthebookforwhichyou'relookingtodownloadthecodefiles.6. Choosefromthedrop-downmenuwhereyoupurchasedthisbookfrom.7. ClickonCodeDownload.
Oncethefileisdownloaded,pleasemakesurethatyouunziporextractthefolderusingthelatestversionof:
WinRAR/7-ZipforWindowsZipeg/iZip/UnRarXforMac7-Zip/PeaZipforLinux
ThecompletesetofcodecanalsobedownloadedfromthefollowingGitHubrepository:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS.
http://www.packtpub.comhttp://www.packtpub.com/supporthttps://github.com/PacktPublishing/Implementing-DevOps-on-AWS
DownloadingthecolorimagesofthisbookWealsoprovideyouwithaPDFfilethathascolorimagesofthescreenshots/diagramsusedinthisbook.Thecolorimageswillhelpyoubetterunderstandthechangesintheoutput.Youcandownloadthisfilefromhttps://www.packtpub.com/sites/default/files/downloads/ImplementingDevOpsonAWS_ColorImages.pdf
https://www.packtpub.com/sites/default/files/downloads/ImplementingDevOpsonAWS_ColorImages.pdf
ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks-maybeamistakeinthetextorthecode-wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.
Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.
http://www.packtpub.com/submit-erratahttps://www.packtpub.com/books/content/support
PiracyPiracyofcopyrightedmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.IfyoucomeacrossanyillegalcopiesofourworksinanyformontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
Pleasecontactusatcopyright@packtpub.comwithalinktothesuspectedpiratedmaterial.
Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.
QuestionsIfyouhaveaproblemwithanyaspectofthisbook,[email protected],andwewilldoourbesttoaddresstheproblem.
Chapter1.WhatisDevOpsandShouldYouCare?DevOpscanbeseenasanextensionofthesuccessfulandwellestablishedAgilemethodology.Bringingoperationsintothepicturehelpstheadvancefromcontinuous(Agile)developmenttointegrationtodeployment,butmoreimportantlyithelpsbuildabetterworkingenvironment,onewithstrongercross-teamrelationships.
IfIhadtodescribeDevOpsinoneword,itwouldbecollaboration.ThegenuinewillingnessofboththeDevandOpscampstoworktogetheristhefoundation,themostimportantaspectofthephilosophy.
DevOpsappearsasthemeetingpointinthefollowingdiagram:
Inthischapterwewillgothroughthefollowingtopics:
WhatisDevOps?Questionsyoushouldaskyourselfbeforeadoptingit
WhatisDevOps?So,letusexaminethevariousprinciplecharacteristicsofaDevOpsenvironment.
Whatfollowsisaseriesofgenerallyaccepteddefinitions,invariablymixedwithpersonalopinions-youhavebeenwarned.
AcommongoalThealignmentofefforttowardincreasingsystemperformanceandstability,reducingthetimeittakestodeployorimprovingtheoverallqualityoftheproduct,willresultinhappiercustomersandproudengineers.
Thegoalneedstoberepeated,clarified,andsimplifieduntilitisfullyunderstood,arguedagainst,andeventuallycommittedtobyeverybody.
DevOpsshiftsfocusawayfromself-interestandtowardthatgoal.Itdirectspraiseatgroupachievementsratherthanthoseoftheindividual;KPIsandEmployeeoftheMonthinitiativesperhapsnotsomuch.
Allowpeopletolookatthebiggerpicturepasttherealmoftheircubicle.Trustthem.
Sharedknowledge(nosilos)Thechancesareyouhavealreadyheardstoriesorreadbooksaboutthenotoriousorganizationalsilos.
Intheworstcase,itwouldbesomebodywhorefusestoletgoandoftenbecomesthemainbottleneckinadevelopmentlifecycle.Theycanbefiercelyterritorial,safe-guardingwhatexclusiveknowledgetheymighthaveinagivenfield,likely(Ispeculate)becausethisprovidesthemwithasenseofimportance,furthercateringtotheirego.
Ontheotherhand,therearealsoexamplesofpeoplewhofindthemselvesinasilopurelyduetounfortunatecircumstances.Myrespectgoesouttothemanyengineersstuckwithsupportinginheritedlegacysystemsallbythemselves.
Fortunately,DevOpsblurssuchbordersofexpertisewithconceptslikecross-functionalteamsandfull-stackengineers.Itisimportanttonoteherethatthisdoesnottranslateintoanopportunitytocutcostsbyexpectingpeopletobetechninjaexpertsateverysinglething(whichinreallifeequatestoprecedingaverage).But,asinoneofthoseVenndiagrams,itisthecross-overbetweenaDevandanOpssetofskills.
Silosareavoidedbyencouragingknowledgesharing.Peerreviews,demostand-ups,orshareddocumentationareafewwaystoensurethatnotaskorpieceofknow-howislimitedtoaspecificperson.YoucouldevenadoptPairProgramming.Itseemsabitheavy,butitevidentlyworks!
TrustandsharedresponsibilityShoulddevelopersbegivenproductionaccess?
Therearegoodreasonsformaintainingstrictrole-basedpermissions;oneofthemissecurityanotherisintegrity.Thisstandpointremainsvalidforaslongaswemaintainthestereotypeofthedeveloperwhoissousedtoworkingindevlocal;tothem,conceptssuchaspassphrase-protectedSSHkeysornotmanuallyeditingallofthefilestakeabackseat.
IntheeraofDevOps,thisisnolongerthecase.Sharedknowledgeandresponsibilitymeansoperationsengineerscanrelyontheirdevelopercolleaguestofollowthesamecodeofconductwhenworkingincritical,productionenvironments.
DevandOpsteamshaveaccesstothesamesetoftoolsandenvironments.DeploymentsarenolongeraspecialtaskreservedfortheOpsteamandscheduleddaysinadvance.
Inateamwithsuchknowledge-sharinghabits,I,asanoperationsengineer,canbeconfidentaboutmyDevcolleague'sabilitytoperformmytasks,andviceversa.
Developersparticipateintheon-callrota,supportingthesoftwaretheyproduce.
Thisisnottobeseenasanadditionalburden,butasasignoftrustandanopportunitytoincreasecollaboration.Nobodyisthrowingcodeoverthewallanymore.Responsibilityandasenseofautonomymotivatespeopletodomorethanisexpectedofthem.
RespectAswespendmoretimetalkingtoeachotheraboutthechallengeswefaceandtheproblemswearetryingtosolve,ourmutualrespectgrows.
ThismanifestsitselfindevelopersseekinginputfromtheOperationsteamfromtheearlystagesofthesoftwaredevelopmentprocessorinOpstoolsbeingbuilttomeetdevelopers'needs.
OpswhothinklikeDevs.DevswhothinklikeOps
--JohnAllspawandPaulHammond,Velocity
ADevOpsenvironmentisbuiltonsuchrespect.Itisaplacewhereeveryopinionmatters,wherepeoplecananddoopenlyquestiondecisionsintheinterestofthebestsolutiontoaproblem.Thisisapowerfulindicatorofone'scommitmenttowardthecommongoalImentionedearlier.
AutomationTodrawanoverlysimplifiedconclusionfromA.Maslow'sTheoryofMotivation,youarelesslikelytothinkaboutpoetrywhenhungry.Inotherwords,ateamwithbasicneedswillbesolvingbasicproblems.
Automatingroutineandmundanetasksallowsengineerstoconcentrateonthemorecomplex,higher-valueones.Also,peoplegetbored,cutcorners,andmakemistakescomputerstendnottodoso.
ReproducibleinfrastructureDescribinginfrastructureascodehasthefollowingadvantages:
ItcanbekeptunderversioncontrolItiseasilysharedwithotherstore-useorreproduceItservesasaveryusefuldiaryofwhatyoudidandhowexactlyyoudiditProvisioningcloudenvironmentsbecomestrivial(forexample,withTerraformorCloudFormation)ItmakesmodernConfigurationManagementpossible
Atanyrate,Isuspectanybodymanagingmorethan10serversisalreadycodifyinginfrastructureinsomewayoranother.
Metricsandmonitoring
MeasureAllTheThings!
--ActualDevOpsslogan
Storageischeap.Developthehabitofgatheringcopiousamountsofmeasurementsandmakingthoseeasilyaccessibleacrossyourorganization.Themorevisibilityengineershaveintotheperformanceoftheirinfrastructureandapplications,themoreadequatetheirdecisionswillbeincriticalsituations.
Graphscanconveyagreatdealofinformation,lookrathercoolonbigscreens,andthehumanmindhasbeenprovenexcellentatrecognizingpatterns.
Anotherimportantroleofmetricsdataisinperformanceoptimization.
Thetrickiestpartofspeedingupaprogramisnotdoingit,butdecidingwhetherit'sworthdoingatall...Partoftheproblemisthatoptimizationishardtodowell.It'sfrighteninglyeasytodevolveintosuperstitiousritualandrationalization.
--MatureOptimization,CarlosBueno
Toavoidfallingpreytoconfirmationbias,youneedanobjectivemethodofassessingyoursystemsbeforeandafterattemptinganyoptimization.Usethosemetrics;itishardtoarguewith(valid)data.
Onthesubjectofvalidity,pleasedocalibrateyourinstrumentsregularly,sanity-checkoutputandmakesurewhatyouthinkyouareshowingiswhatyourcolleaguesthinktheyareseeing(ref:https://mars.jpl.nasa.gov/msp98/news/mco990930.html).
https://mars.jpl.nasa.gov/msp98/news/mco990930.html
ContinuousIntegration,Delivery,andDeploymentTheObserve,Orient,Decide,andAct(OODA)loopisaconceptdevelopedbyCol.J.Boydthatshowsthevalueinone'sabilitytoadapttoever-changingcircumstances.
Facedwithunforgiving(andproductive)competition,organizationsshouldbeabletorapidlyreacttodynamicmarketconditions.
ThisisprobablybestillustratedwiththeoldKodakandNetflixtales.Theformerafterhavingbeenwildlysuccessfulissaidtohavefailedtoadapttothenewtrendsintheirsector,causingthebrandtograduallyfadeaway.Incontrast,Netflixkeepsonskillfullymoldingtheirproducttomatchthenewwaysinwhichweconsumedigitalcontent.Theycompletelytransformedtheirinfrastructure,sharedsomeclever,newandsomewhatcontroversialpracticesplusatonofgreatsoftware.BelikeNetflix.
ContinuousIntegrationandDeliveryisessentiallyOODAinpractice.Teamscontinuouslyintegraterelativelysmallcodechanges,deliveringreleasesmoreoften,thusgettingfeedbackfromtheirusersmuchquicker.Thetypeoffeedbackneededbyanorganizationtobeabletoadequatelyrespondtoaneverchangingmarket.
Noneoftheprecedingsuggestshoweverthatoneshouldaimtobecomeareleasehero,rushingthingsintoProduction,settingitonfiretwiceaweek.ACI/CDframeworkstillimpliestheusualstrictcodereviewandtestprocesses,despitehowoftenyoudeploy.Thoughcodereviewsandtestingrequiremuchlesstimeandeffortastypicallythemorefrequentthedeployments,thesmallerthecodechanges.
EmbracingfailureNaturally,moreexperimentationislikelytoincreasetheprobabilityoferror.
Idoubtthisfactcomesasasurprisetoanybody;whatmightsurpriseyou,however,istheadvicetoacceptanadditional,positiveangletofailure.
Recallthevideonerdsfromtheprevioussection.Well,theydidn'texactlybreezethroughallthatchangewithoutcasualties.IherebyspareyoutheEdisonquotes;however,trialanderrorisindeedavalidformofthescientificmethod,andtheDevOpsprocessesserveasagreatenablertothosewhowouldagree.
Inotherwords,anorganizationshouldencouragepeopletokeeponchallengingandimprovingthecurrentstateofaffairswhilealsoallowingthemtoopenlytalkaboutthetimeswhenthingswentwrong.
Butdealingwithexperimentationfailuresispossiblythemoreromanticsideofthestorycomparedtothecold,harshrealityofday-to-dayoperations.
Systemsfail.Iwouldliketothinkmostofushavecometoacceptthatfactalongwiththechainofthoughtitprovokes:
wedonotalwaysknowasmuchaswethinkwedo:
"Knowledgeoftheoutcomemakesitseemthateventsleadingtotheoutcomeshouldhaveappearedmoresalienttopractitionersatthetimethanwasactuallythecase...
Afteranaccident,practitioneractionsmayberegardedaserrorsorviolations,buttheseevaluationsareheavilybiasedbyhindsightandignoretheotherdrivingforces..."
--HowComplexSystemsFail,R.I.Cook
Excelsior!Orhow,inourlong-standingpursuitofsocialdominance,weseemtohavedevelopedtheconvenientbeliefthatfollowinganeventwenotonlyknowexactlywhatandhowithappenedbutalsowhy.ThispeculiarphenomenonhasalreadybeenexplainedratherwellbyD.KahnemaninThinkingFastandSlow;Iwilljustaddthatindeedoneoftenhearsofoverconfidentcharacterswhopointfingersattheircolleaguesbasedonwhatappearstothemasacoherentstoryline.
Thetruthofthematteristhis:wewerenotthere.Andkeepingthedetailswenowknowandthoseknownatthetimeseparatedisnotaneasytask.Blamingisofzerovalue:
Etsyandthelikesinourcommunityhavesharedenoughobservationstosuggestthatnegativereinforcementasastrategyforreducinghumanerrorislessthanoptimal.
WiththeadoptionofDevOps,weacceptthatpeoplegenerallycometoworkeverydaywiththeintentiontoperformtothebestoftheirabilitiesandintheinterestoftheorganization.Afteranoutage,webeginouranalysiswiththeassumptionthattheoperatorhasactedinthebestpossiblewaygiventhecircumstancesandinformationavailabletothematthetime.Wefocusonwhatcouldhaveledtothemmakingthegivendecisions,theirthoughtprocess,theflowofevents,andwhetheranyofthesecanbeimproved.Resiliencecanbeaccumulated:
"Whatdoesnotkillus..."mithridatismorNassimTaleb'sconceptofantifragilityareallexpressiveoftheideathatwegetbetteratdealingwithnegativeexperiencesasweencounterthem,andwhat'smore,weshouldlookforthemeverynowandagain.
Wecantrainourselvesandoursystemstorecoverfromerrorsfasterorevenbettertocontinueoperatingdespitethem.Onewaytoachievethisiswithcontrolled(andwithpractice,lesscontrolled)outages.
Withtherightmonitoringandauditingtoolsinplace,everyabnormalactivityoffersusamoreintimateviewofourapplicationsandinfrastructure.
NowthatIhavebestoweduponyou,mydearreader,thesecrettoabetterlifethroughDevOps,letusconcernourselveswiththelatterpartofthetitleofthischapter.
ShouldyoucareIfailtoseeareasonwhyoneshouldnot.SomesevenorsoyearshavepassedsincetheinceptionoftheideaofDevOps,andtheamountofevidenceofitseffectivenesshasbeengrowingsteadily.HavingtherespectedAgileframeworkatitsbasefurtheraddstoitscredibilityandperhapshelpsexplainagoodpartofitssuccess.
Thatisnottosaytherearenotconsiderationstobetakenintoaccounthowever.Thecriticalthinkerwithinyou,wouldwanttoaskaquestionortwopriortoembarkingonsuchaculturalcoupd'tat.
Isthistherighttime?DidyoujustfinishadoptingLeanorAgileDevelopment?Whatelsehasbeengoingonintheteam?Isnowthebesttimeforyetanothercryforchange?
Alteringourhabitsmakesusuneasy;ittakessometimetoadjust.Yourperseveranceislaudable,andpursuingDevOpsasthenextlevelofteamcollaborationisoftentherightchoice.
Thereisnoneedtogiveitupaltogether;perhapsputitonholdforamoment.
Willitwork?Lookaroundyou.Thosefaces,thosedifferentpersonalities,canyoupicturethemalltogethersingingKumbaya?Maybeyes,maybeno,ornotyet.
Pleasedonote-mailananonymousstaffsurvey.Geteverybodyinaroom,layyourDevOpspropagandaout,andgaugetheirreactions.
Youwillneedeveryonetofullyunderstandtheconcepts,acknowledgethechallenges,andacceptthesacrificesforthistowork.Therecanneitherbeexceptionsnorambiguity.
Allofthisrequiresagreatdegreeofculturalchange,whichateamshouldbepreparedfor.
Isitworthit?Whatwouldittaketochangethecurrentmentality?Howmuchofadisturbanceyouwouldneedtocause?Whatdegreeofbacklashdoyouexpect?
WhileIamnotsuggestingthisasanexcusetoputupwiththestatusquo,Ibegyoumaintainapragmaticviewofthesituation.
Yourtypeoforganizationmightbebettersuitedforaprocessofevolutionratherthanarevolution.
Doyouneedit?Howwouldyouscoreyourcurrentprocesses?Wouldyousayyourcross-teamcommunicationissatisfactory?Youregularlymeetbusinessexpectations?Youhavealreadyautomatedmostofyourworkflow?
Itsoundslikeyouaredoingfineasitis;youmightalreadyhavesomeDevOpsinyourteamwithoutrealizingit.Thepointisthatitcouldbeabetteruseofresourcesifyouweretoconcentrateonoptimizingelsewhere,solvingother,morepressingproblemsatthistime.
NowthatyouhavebeenthroughayetanotherinterpretationoftheideasbehindDevOps,ifyoufeelthosematchyourwayofthinkingandthefinalfewquestionsdidnotraiseanyconcerns,thenwecansafelytransitiontothemoretechnicaltopicswhereweputprinciplesintopractice.
SummaryFirst,weexploredthemainideascontainedintheDevOpsphilosophy,followedbyafewquestionsaimedathelpingyouconstructamoreobjectiveperspectivewhenitcomestoadoptingDevOpswithinyourorganization.
WehaveseenthatDevOpsisaneffectivecombinationofsomeolder,provenAgileconceptsandothermorerecentlydevelopedones,andthatitteachesushowtobuildbetterteamswhowritebettersoftware,getresultsfaster,andcollaborateeffortlesslyinanenvironmentthatencouragesexperimentationwithoutcompromisingstability.
Nowthatwehavecoveredthetheory,thenextchaptertakesusintothepracticalapplicationofDevOps.Wearegoingtobeginwithexamplesofdeployinginfrastructureascodeinthecloud.
Chapter2.StartTreatingYourInfrastructureasCodeLadiesandgentlemen,putyourhandsintheair,forProgrammableInfrastructureishere!
PerhapsInfrastructure-as-Code(IaC)isnotanentirelynewconceptconsideringhowlongConfigurationManagementhasbeenaround.Codifyingserver,storage,andnetworkinginfrastructureandtheirrelationships,however,isarelativelyrecenttendencybroughtaboutbytheriseofcloudcomputing.ButletusleaveConfigurationManagementforlaterandfocusourattentiononthatsecondaspectofIaC.
Youshouldrecallfromthepreviouschaptersomeofthebenefitsofstoringallthethingsascode:
CodecanbekeptunderversioncontrolCodecanbeshared/collaboratedoneasilyCodedoublesasdocumentationCodeisreproducible
Thatlastpointwasabigwinformepersonally.Automatedprovisioninghelpedreducethetimeittooktodeployafull-featuredcloudenvironmentfromfourhoursdowntoone,andtheoccurrencesofhumanerrortoalmostzero(oneshallnotbetrustedwithaninputfield).
Beingabletorapidlyprovisionresourcesbecomesasignificantadvantagewhenateamstartsusingmultipleenvironmentsinparallelandneedsthosebroughtupordownon-demand.Inthischapter,weexamineindetailhowtodescribe(incode)anddeployonesuchenvironmentonAWSwithminimalmanualinteraction.
ToimplementIaCinthecloud,wewilllookattwotoolsorservices:TerraformandCloudFormation.
Wewillgothroughexamplesofthefollowing:
ConfiguringthetoolWritinganIaCtemplateDeployingatemplateDeployingsubsequentchangestothetemplateDeletingatemplateandremovingtheprovisionedinfrastructure
Forthepurposeoftheseexamples,letusassumeourapplicationrequiresaVirtualPrivateCloud(VPC)thathostsaRelationalDatabaseServices(RDS)backendandacoupleofElasticComputeCloud(EC2)instancesbehindanElasticLoadBalancer(ELB).WewillkeepmostcomponentsbehindNetworkAddressTranslation(NAT),allowingonlytheloadbalancertobeaccessedexternally.
IaCusingTerraformOneofthetoolsthatcanhelpdeployinfrastructureonAWSisHashiCorp'sTerraform(https://www.terraform.io).HashiCorpisthatgeniusbunchthatgaveusVagrant,Packer,andConsul.Iwouldrecommendyoulookuptheirwebsiteifyouhavenotalready.
UsingTerraform(TF),wewillbeabletowriteatemplatedescribinganenvironment,performadryruntoseewhatisabouttohappenandwhetheritisexpected,deploythetemplate,andmakeanylateadjustmentswherenecessary-allofthiswithoutleavingtheshellprompt.
https://www.terraform.io
ConfigurationFirstly,youwillneedtohaveacopyofTF(https://www.terraform.io/downloads.html)onyourmachineandavailableontheCLI.Youshouldbeabletoquerythecurrentlyinstalledversion,whichinmycaseis0.6.15:
$terraform--versionTerraformv0.6.15
SinceTFmakesuseoftheAWSAPIs,itrequiresasetofauthenticationkeysandsomelevelofaccesstoyourAWSaccount.InordertodeploytheexamplesinthischapteryoucouldcreateanewIdentityandAccessManagement(IAM)userwiththefollowingpermissions:
"autoscaling:CreateAutoScalingGroup","autoscaling:CreateLaunchConfiguration","autoscaling:DeleteLaunchConfiguration","autoscaling:Describe*","autoscaling:UpdateAutoScalingGroup","ec2:AllocateAddress","ec2:AssociateAddress","ec2:AssociateRouteTable","ec2:AttachInternetGateway","ec2:AuthorizeSecurityGroupEgress","ec2:AuthorizeSecurityGroupIngress","ec2:CreateInternetGateway","ec2:CreateNatGateway","ec2:CreateRoute","ec2:CreateRouteTable","ec2:CreateSecurityGroup","ec2:CreateSubnet","ec2:CreateTags","ec2:CreateVpc","ec2:Describe*","ec2:ModifySubnetAttribute","ec2:RevokeSecurityGroupEgress","elasticloadbalancing:AddTags","elasticloadbalancing:ApplySecurityGroupsToLoadBalancer","elasticloadbalancing:AttachLoadBalancerToSubnets","elasticloadbalancing:CreateLoadBalancer","elasticloadbalancing:CreateLoadBalancerListeners","elasticloadbalancing:Describe*","elasticloadbalancing:ModifyLoadBalancerAttributes","rds:CreateDBInstance","rds:CreateDBSubnetGroup","rds:Describe*"
Note
Pleaserefertothisfileformoreinformation:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/iam_user_policy.json.
OnewaytomakethecredentialsoftheIAMuseravailabletoTFisbyexportingthefollowingenvironmentvariables:
https://www.terraform.io/downloads.htmlhttps://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/iam_user_policy.json
$exportAWS_ACCESS_KEY_ID='user_access_key'$exportAWS_SECRET_ACCESS_KEY='user_secret_access_key'
Thisshouldbesufficienttogetusstarted.
Note
Downloadingtheexamplecode
DetailedstepstodownloadthecodebundlearementionedinthePrefaceofthisbook.
ThecodebundleforthebookisalsohostedonGitHubat:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS.Wealsohaveothercodebundlesfromourrichcatalogofbooksandvideosavailableat:https://github.com/PacktPublishing/.Checkthemout!
https://github.com/PacktPublishing/Implementing-DevOps-on-AWShttps://github.com/PacktPublishing/
TemplatedesignBeforewegettocoding,herearesomeoftherules:
YoucouldchoosetowriteaTFtemplateasasinglelargefileoracombinationofsmalleronesTemplatescanbewritteninpureJSONorTF'sownformatTFwilllookforfileswith.tfor.tf.jsonextensionsinagivenfolderandloadtheminalphabeticalorderTFtemplatesaredeclarative,hencetheorderinwhichresourcesappearinthemdoesnotaffecttheflowofexecution
ATFtemplategenerallyconsistsofthreesections:resources,variables,andoutputs.Asmentionedintheprecedingsection,itisamatterofpersonalpreferencehowyouarrangethese;however,forbetterreadabilityIsuggestwemakeuseoftheTFformatandwriteeachsectiontoaseparatefile.Also,whilethefileextensionsareofimportance,thefilenamesareuptoyou.
Resources
Inaway,thisfileholdsthemainpartofatemplate,astheresourcesrepresenttheactualcomponentsthatendupbeingprovisioned.Forexample,wewillbeusingtheVPCTerraformresource,RDS,ELBandafewotherstoprovisionwhatroughlylookslikethis:
Sincetemplateelementscanbewritteninanyorder,TFdeterminestheflowofexecutionbyexamininganyreferencesthatitfinds(forexample,aVPCshouldexistbeforeanELBthatissaidtobelongtoitiscreated).Alternatively,explicitflowcontrolattributessuchasdepends_onareused,aswewillobserveshortly.
Tofindoutmore,letusgothroughthecontentsoftheresources.tffile.
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/resources.tf.
First,wetellTerraformwhatprovidertouseforourinfrastructure:
#SetaProvider
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/resources.tf
provider"aws"{region="${var.aws-region}"}
Youwillnoticethatnocredentialsarespecified,sincewesetthemasenvironmentvariablesearlier.
NowwecanaddtheVPCanditsnetworkingcomponents:
#CreateaVPCresource"aws_vpc""terraform-vpc"{cidr_block="${var.vpc-cidr}"tags{Name="${var.vpc-name}"}}#CreateanInternetGatewayresource"aws_internet_gateway""terraform-igw"{vpc_id="${aws_vpc.terraform-vpc.id}"}#CreateNATresource"aws_eip""nat-eip"{vpc=true}
Sofar,wehavedeclaredtheVPC,itsInternetandNATgateways,plusasetofpublicandprivatesubnetswithmatchingroutingtables.
Itwillhelpclarifythesyntaxifweexaminedsomeofthoseresourceblocks,linebyline:
resource"aws_subnet""public-1"{
Thefirstargumentisthetypeoftheresourcefollowedbyanarbitraryname:
vpc_id="${aws_vpc.terraform-vpc.id}"
Theaws_subnetresourcenamedpublic-1hasavpc_idproperty,whichreferstotheidattributeofadifferentaws_vpcresourcenamedterraform-vpc.Suchreferencestootherresourcesimplicitlydefinetheexecutionflow,thatistosay,theVPCneedstoexistbeforethesubnetcanbecreated:
cidr_block="${cidrsubnet(var.vpc-cidr,8,1)}"
Wewilltalkmoreaboutvariablesinamoment,buttheformatisvar.var_nameasshown
here.
Here,weusethecidrsubnetfunctionwiththevpc-cidrvariable,whichreturnsacidr_blocktobeassignedtothepublic-1subnet.PleaserefertotheTFdocumentationforthisandotherusefulfunctions.
Next,weaddaRDStotheVPC:
resource"aws_db_instance""terraform"{identifier="${var.rds-identifier}"allocated_storage="${var.rds-storage-size}"storage_type="${var.rds-storage-type}"engine="${var.rds-engine}"engine_version="${var.rds-engine-version}"instance_class="${var.rds-instance-class}"username="${var.rds-username}"password="${var.rds-password}"port="${var.rds-port}"vpc_security_group_ids=["${aws_security_group.terraform-rds.id}"]db_subnet_group_name="${aws_db_subnet_group.rds.id}"}
Here,wemostlyseereferencestovariableswithafewcallstootherresources.
FollowingtheRDSisanELB:
resource"aws_elb""terraform-elb"{name="terraform-elb"security_groups=["${aws_security_group.terraform-elb.id}"]subnets=["${aws_subnet.public-1.id}","${aws_subnet.public-2.id}"]listener{instance_port=80instance_protocol="http"lb_port=80lb_protocol="http"}tags{Name="terraform-elb"}}
Lastly,wedefinetheEC2AutoScalingGroupandrelatedresourcessuchastheLaunchConfiguration.
FortheLaunchConfigurationwedefinetheAMIandtypeofinstancetobeused,thenameoftheSSHkeypair,EC2securitygroup(s)andtheUserDatatobeusedtobootstraptheinstances:
resource"aws_launch_configuration""terraform-lcfg"{image_id="${var.autoscaling-group-image-id}"instance_type="${var.autoscaling-group-instance-type}"key_name="${var.autoscaling-group-key-name}"security_groups=["${aws_security_group.terraform-ec2.id}"]user_data="#!/bin/bash\nset-euf-opipefail\nexec1>>(logger-s-t$(basename$0))2>&1\nyum-yinstallnginx;chkconfignginxon;servicenginxstart"lifecycle{create_before_destroy=true}
TheAutoScalingGrouptakestheIDoftheLaunchConfiguration,alistofVPCsubnets,themin/maxnumberofinstancesandthenameoftheELBtoattachprovisionedinstancesto:
}resource"aws_autoscaling_group""terraform-asg"{name="terraform"launch_configuration="${aws_launch_configuration.terraform-lcfg.id}"vpc_zone_identifier=["${aws_subnet.private-1.id}","${aws_subnet.private-2.id}"]min_size="${var.autoscaling-group-minsize}"max_size="${var.autoscaling-group-maxsize}"load_balancers=["${aws_elb.terraform-elb.name}"]depends_on=["aws_db_instance.terraform"]tag{key="Name"value="terraform"propagate_at_launch=true}}
Theprecedinguser_datashellscriptwillinstallandstartNGINXontotheEC2node(s).
Variables
Wehavemadegreatuseofvariablestodefineourresources,makingthetemplateasre-usableaspossible.Letusnowlookinsidevariables.tftostudythesefurther.
Similarlytotheresourceslist,westartwiththeVPC:
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/variables.tf.
variable"aws-region"{type="string"description="AWSregion"}variable"aws-availability-zones"{type="string"description="AWSzones"
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/variables.tf
}variable"vpc-cidr"{type="string"description="VPCCIDR"}variable"vpc-name"{type="string"description="VPCname"}
Thesyntaxisasfollows:
variable"variable_name"{variableproperties}
variable_nameisarbitrary,butneedstomatchrelevantvar.var_namereferencesmadeinotherpartsofthetemplate.Forexample,theaws-regionvariablewillsatisfythe${var.aws-region}referencewemadeearlierwhendescribingtheregionoftheproviderawsresource.
Wewillmostlyusestringvariables,butthereisanotherusefultypecalledmapthatcanholdlookuptables.Mapsarequeriedinasimilarwaytolookingupvaluesinahash/dict(Pleasesee:https://www.terraform.io/docs/configuration/variables.html).
NextcomesRDS:
variable"rds-identifier"{type="string"description="RDSinstanceidentifier"}variable"rds-storage-size"{type="string"description="StoragesizeinGB"}variable"rds-storage-type"{type="string"description="Storagetype"}variable"rds-engine"{type="string"description="RDStype"}variable"rds-engine-version"{type="string"description="RDSversion"}variable"rds-instance-class"{type="string"description="RDSinstanceclass"}variable"rds-username"{type="string"description="RDSusername"}
https://www.terraform.io/docs/configuration/variables.html
variable"rds-password"{type="string"description="RDSpassword"}variable"rds-port"{type="string"description="RDSportnumber"}
Lastly,weaddourEC2relatedvariables:
variable"autoscaling-group-minsize"{type="string"description="MinsizeoftheASG"}variable"autoscaling-group-maxsize"{type="string"description="MaxsizeoftheASG"}variable"autoscaling-group-image-id"{type="string"description="EC2AMIidentifier"}variable"autoscaling-group-instance-type"{type="string"description="EC2instancetype"}variable"autoscaling-group-key-name"{type="string"description="EC2sshkeyname"}
Wenowhavethetypeanddescriptionofallourvariablesdefinedinvariables.tf,butnovalueshavebeenassignedtothemyet.
TFisquiteflexiblewithhowthiscanbedone.Wecoulddoitanyofthefollowingways:
Assign(default)valuesdirectlyinvariables.tf:variable"aws-region"{type="string"description="AWSregion"default='us-east-1'}Notassignavaluetoavariable,inwhichcaseTFwillpromptforitatruntime*Passa-var'key=value'argumentdirectlytotheTFcommand,likeso:
-var'aws-region=us-east-1'
Storekey=valuepairsinafileUseenvironmentvariablesprefixedwithTF_VAR,asinTF_VAR_aws-region
Usingakey=valuepairsfileprovestobequiteconvenientwithinteams,aseachengineercanhaveaprivatecopy(excludedfromrevisioncontrol).Ifthefileisnamedterraform.tfvarsitwillbereadautomaticallybyTF;alternatively,-var-filecanbeusedonthecommandlinetospecifyadifferentsource.
Hereisthecontentofoursampleterraform.tfvarsfile:
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/terraform.tfvars.
autoscaling-group-image-id="ami-08111162"autoscaling-group-instance-type="t2.nano"autoscaling-group-key-name="terraform"autoscaling-group-maxsize="1"autoscaling-group-minsize="1"aws-availability-zones="us-east-1b,us-east-1c"aws-region="us-east-1"rds-engine="postgres"rds-engine-version="9.5.2"rds-identifier="terraform-rds"rds-instance-class="db.t2.micro"rds-port="5432"rds-storage-size="5"rds-storage-type="gp2"rds-username="dbroot"rds-password="donotusethispassword"vpc-cidr="10.0.0.0/16"vpc-name="Terraform"
Apointofinterestisaws-availability-zones,asitholdsmultiplevaluesthatweinteractwithusingtheelementandsplitfunctions,asseeninresources.tf.
Outputs
Thethird,mostlyinformationalpartofourtemplatecontainstheTFOutputs.Theseallowselectedvaluestobereturnedtotheuserwhentesting,deployingorafteratemplatehasbeendeployed.Theconceptissimilartohowechostatementsarecommonlyusedinshellscriptstodisplayusefulinformationduringexecution.
Letusaddoutputstoourtemplatebycreatinganoutputs.tffile:
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/outputs.tf.
output"VPCID"{value="${aws_vpc.terraform-vpc.id}"}output"NATEIP"{value="${aws_nat_gateway.terraform-nat.public_ip}"}output"ELBURI"{value="${aws_elb.terraform-elb.dns_name}"
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/terraform.tfvarshttps://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/Terraform/outputs.tf
}output"RDSEndpoint"{value="${aws_db_instance.terraform.endpoint}"}
Toconfigureanoutput,yousimplyreferenceagivenresourceanditsattribute.Asshowninprecedingcode,wehavechosentheIDoftheVPC,theElasticIPaddressoftheNATgateway,theDNSnameoftheELBandtheendpointaddressoftheRDSinstance.
Thissectioncompletesthetemplateinthisexample.Youshouldnowhavefourfilesinyourtemplatefolder:resources.tf,variables.tf,terraform.tfvars,andoutputs.tf.
OperationsWeshallexaminefivemainTFoperations:
ValidatingatemplateTesting(dry-run)InitialdeploymentUpdatingadeploymentRemovalofadeployment
Note
Inthefollowingcommandlineexamples,Terraformisrunwithinthefolderthatcontainsthetemplatefiles.
Validation
Beforegoinganyfurther,abasicsyntaxcheckshouldbedonewiththeterraformvalidatecommand.Afterrenamingoneofthevariablesinresources.tf,validatereturnsanunknownvariableerror:
$terraformvalidateErrorvalidating:1error(s)occurred:*providerconfig'aws':unknownvariablereferenced:'aws-region-1'.defineitwith'variable'blocks
Oncethevariablenamehasbeencorrected,re-runningvalidatereturnsnooutput,meaningvalidationhaspassed.
Dry-run
Thenextstepistoperformatest/dry-runexecutionwithterraformplan,whichdisplayswhatwouldhappenduringanactualdeployment.Thecommandreturnsacolor-codedlistofresourcesandtheirpropertiesormoreprecisely,asfollows:
$terraformplanResourcesareshowninalphabeticalorderforquickscanning.Greenresourceswillbecreated(ordestroyedandthencreatedifanexistingresourceexists),yellowresourcesarebeingchangedin-place,andredresourceswillbedestroyed.
Toliterallygetthepictureofwhattheto-be-deployedinfrastructurelookslike,youcoulduseterraformgraph:
$terraformgraph>my_graph.dot
DOTfilescanbemanipulatedwiththeGraphvizopensourcesoftware(Pleaseseehttp://www.graphviz.org)ormanyonlinereaders/converters.Thefollowingdiagramisaportionofalargergraphrepresentingthetemplatewedesignedearlier:
http://www.graphviz.org
Terraformgraph
Deployment
Ifyouarehappywiththeplanandgraph,thetemplatecannowbedeployedusingterraformapply:
$terraformapplyaws_eip.nat-eip:Creating...allocation_id:""=>""association_id:""=>""domain:""=>""instance:""=>""network_interface:""=>""private_ip:""=>""public_ip:""=>""vpc:""=>"1"aws_vpc.terraform-vpc:Creating...cidr_block:""=>"10.0.0.0/16"default_network_acl_id:""=>""default_security_group_id:""=>""dhcp_options_id:""=>""enable_classiclink:""=>""enable_dns_hostnames:""=>""Applycomplete!Resources:22added,0changed,0destroyed.
Thestateofyourinfrastructurehasbeensavedtothefollowingpath.Thisstateisrequiredtomodifyanddestroyyourinfrastructure,sokeepitsafe.Toinspectthecompletestate,usetheterraformshowcommand.
Statepath:terraform.tfstateOutputs:ELBURI=terraform-elb-xxxxxx.us-east-1.elb.amazonaws.comNATEIP=x.x.x.xRDSEndpoint=terraform-rds.xxxxxx.us-east-1.rds.amazonaws.com:5432VPCID=vpc-xxxxxx
Attheendofasuccessfuldeployment,youwillnoticetheOutputsweconfiguredearlierandamessageaboutanotherimportantpartofTF-thestatefile(pleasereferto
https://www.terraform.io/docs/state/):
TFstoresthestateofyourmanagedinfrastructurefromthelasttimeTFwasrun.Bydefault,thisstateisstoredinalocalfilenamedterraform.tfstate,butitcanalsobestoredremotely,whichworksbetterinateamenvironment.
TFusesthislocalstatetocreateplansandmakechangestoyourinfrastructure.Priortoanyoperation,TFdoesarefreshtoupdatethestatewiththerealinfrastructure.
Inasense,thestatefilecontainsasnapshotofyourinfrastructureandisusedtocalculateanychangeswhenatemplatehasbeenmodified.Normally,youwouldkeeptheterraform.tfstatefileunderversioncontrolalongsideyourtemplates.Inateamenvironmenthowever,ifyouencountertoomanymergeconflictsyoucanswitchtostoringthestatefile(s)inanalternativelocationsuchasS3(pleasesee:https://www.terraform.io/docs/state/remote/index.html).
AllowafewminutesfortheEC2nodetofullyinitialize,thentryloadingtheELBURIfromtheprecedingOutputsinyourbrowser.Youshouldbegreetedbynginx,asshowninthefollowingscreenshot:
Updates
AsperMurphy'sLaw,assoonaswedeployatemplate,achangetoitwillbecomenecessary.Fortunately,allthatisneededforthisistoupdateandre-deploythegiventemplate.
Let'ssayweneedtoaddanewruletotheELBsecuritygroup(showninbold):
1. Updatethe"aws_security_group""terraform-elb"resourceblockinresources.tf:
resource"aws_security_group""terraform-elb"{name="terraform-elb"description="ELBsecuritygroup"vpc_id="${aws_vpc.terraform-vpc.id}"
https://www.terraform.io/docs/state/https://www.terraform.io/docs/state/remote/index.html
ingress{from_port="80"to_port="80"protocol="tcp"cidr_blocks=["0.0.0.0/0"]}ingress{from_port="443"to_port="443"protocol="tcp"cidr_blocks=["0.0.0.0/0"]}egress{from_port=0to_port=0protocol="-1"cidr_blocks=["0.0.0.0/0"]}}
2. Verifywhatisabouttochange:
$terraformplan...~aws_security_group.terraform-elbingress.#:"1"=>"2"ingress.2214680975.cidr_blocks.#:"1"=>"1"ingress.2214680975.cidr_blocks.0:"0.0.0.0/0"=>"0.0.0.0/0"ingress.2214680975.from_port:"80"=>"80"ingress.2214680975.protocol:"tcp"=>"tcp"ingress.2214680975.security_groups.#:"0"=>"0"ingress.2214680975.self:"0"=>"0"ingress.2214680975.to_port:"80"=>"80"ingress.2617001939.cidr_blocks.#:"0"=>"1"ingress.2617001939.cidr_blocks.0:""=>"0.0.0.0/0"ingress.2617001939.from_port:""=>"443"ingress.2617001939.protocol:""=>"tcp"ingress.2617001939.security_groups.#:"0"=>"0"ingress.2617001939.self:""=>"0"ingress.2617001939.to_port:""=>"443"Plan:0toadd,1tochange,0todestroy.
3. Deploythechange:
$terraformapply...aws_security_group.terraform-elb:Modifying...ingress.#:"1"=>"2"ingress.2214680975.cidr_blocks.#:"1"=>"1"ingress.2214680975.cidr_blocks.0:"0.0.0.0/0"=>"0.0.0.0/0"ingress.2214680975.from_port:"80"=>"80"ingress.2214680975.protocol:"tcp"=>"tcp"ingress.2214680975.security_groups.#:"0"=>"0"
ingress.2214680975.self:"0"=>"0"ingress.2214680975.to_port:"80"=>"80"ingress.2617001939.cidr_blocks.#:"0"=>"1"ingress.2617001939.cidr_blocks.0:""=>"0.0.0.0/0"ingress.2617001939.from_port:""=>"443"ingress.2617001939.protocol:""=>"tcp"ingress.2617001939.security_groups.#:"0"=>"0"ingress.2617001939.self:""=>"0"ingress.2617001939.to_port:""=>"443"aws_security_group.terraform-elb:Modificationscomplete...Applycomplete!Resources:0added,1changed,0destroyed.
Note
Someupdateoperationscanbedestructive(pleaserefertohttp://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html).YoushouldalwayschecktheCloudFormationdocumentationontheresourceyouareplanningtomodifytoseewhetherachangeisgoingtocauseaninterruption.TFprovidessomeprotectionviatheprevent_destroylifecycleproperty(pleaserefertohttps://www.terraform.io/docs/configuration/resources.html#prevent_destroy).
Removal
ThisisafriendlyremindertoalwaysremoveAWSresourcesafteryouaredoneexperimentingwiththemtoavoidanyunexpectedcharges.
Beforeperforminganydeleteoperations,wewillneedtograntsuchprivilegestothe(terraform)IAMuserwecreatedinthebeginningofthischapter.Asashortcut,youcouldtemporarilyattachtheAdministratorAccessmanagedpolicytotheuserviatheAWSConsole,asshowninthefollowingfigure:
ToremovetheVPCandallassociatedresourcesthatwecreatedaspartofthisexample,wewilluseterraformdestroy:
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.htmlhttps://www.terraform.io/docs/configuration/resources.html#prevent_destroy
$terraformdestroyDoyoureallywanttodestroy?Terraformwilldeleteallyourmanagedinfrastructure.Thereisnoundo.Only'yes'willbeacceptedtoconfirm.Enteravalue:yes
Terraformasksforaconfirmationthenproceedstodestroyresources,endingwiththefollowing:
Applycomplete!Resources:0added,0changed,22destroyed.
Next,weremovethetemporaryadminaccesswegrantedtotheIAMuserbydetachingtheAdministratorAccessmanagedpolicy,asshowninthefollowingscreenshot:
Then,verifythattheVPCisnolongervisibleintheAWSConsole.
IaCusingCloudFormationCloudFormationisanAWSservicefordeployinginfrastructureascode.Asbefore,wearegoingtodescribeourinfrastructureviatemplatescontainingparameters(variables),resources,andoutputs.
CloudFormationcallseachdeployedtemplateaStack.Creating,listing,updating,anddeletingstacksispossibleviatheAWSConsole,CLI,orAPI.Inasmallsetup,youwouldprobablydeployeachofyourstacksindividually,butasyourarchitecturebecomesmorecomplex,youcanstartnestingstacks.Youwouldhaveatop-leveloraparentstack(template)thatinvokesanumberofsub-stacks.Nestedstacksallowyoutopassvariablesbetweenthemand,ofcourse,saveyouthetimeofhavingtodeployeachoneindividually.
ConfigurationCloudFormationprovidesaGUIviatheAWSConsole;wehowever,aregoingtofocusontheAWSCLIsinceitismostsuitableforautomatingtasksinthefuture.
DependingontheOSyourun,youcoulddownloadaninstallerfromhttps://aws.amazon.com/cli/orusePythonPIP:
$pipinstallawscli$aws--versionaws-cli/1.10.34...
WewillneedasetofAPIkeys,solet'screateanewIAMusercalledcloudformationwiththefollowingprivileges:
"cloudformation:CancelUpdateStack","cloudformation:ContinueUpdateRollback","cloudformation:Create*","cloudformation:Describe*","cloudformation:EstimateTemplateCost","cloudformation:ExecuteChangeSet","cloudformation:Get*","cloudformation:List*","cloudformation:PreviewStackUpdate","cloudformation:SetStackPolicy","cloudformation:SignalResource","cloudformation:UpdateStack","cloudformation:ValidateTemplate","autoscaling:CreateAutoScalingGroup","autoscaling:CreateLaunchConfiguration","autoscaling:DeleteLaunchConfiguration","autoscaling:Describe*","autoscaling:UpdateAutoScalingGroup","ec2:AllocateAddress","ec2:AssociateAddress","ec2:AssociateRouteTable","ec2:AttachInternetGateway","ec2:AuthorizeSecurityGroupEgress","ec2:AuthorizeSecurityGroupIngress","ec2:CreateInternetGateway","ec2:CreateNatGateway","ec2:CreateRoute","ec2:CreateRouteTable","ec2:CreateSecurityGroup","ec2:CreateSubnet","ec2:CreateTags","ec2:CreateVpc","ec2:Describe*","ec2:Modify*","ec2:RevokeSecurityGroupEgress","elasticloadbalancing:CreateLoadBalancer","elasticloadbalancing:CreateLoadBalancerListeners","elasticloadbalancing:Describe*","elasticloadbalancing:ModifyLoadBalancerAttributes",
https://aws.amazon.com/cli/
"elasticloadbalancing:SetLoadBalancerPoliciesOfListener","rds:CreateDBInstance","rds:CreateDBSubnetGroup","rds:Describe*"
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/iam_user_policy.json.
Youhavethechoiceofusingawsconfigure,whichwillpromptyoufortheAPIcredentials,orifyouprefernottostorethempermanently,youcoulduseanenvironmentvariable:
$exportAWS_ACCESS_KEY_ID='user_access_key'$exportAWS_SECRET_ACCESS_KEY='user_secret_access_key'
CloudFormationtemplatesdonotstoreanyAWSregioninformation,sotoavoidspecifyingitonthecommandlineeachtime.Itcanbeexportedaswell:
$exportAWS_DEFAULT_REGION='us-east-1'
Withthoseenvironmentvariablesinplace,awsclishouldbereadyforuse.
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/iam_user_policy.json
TemplatedesignCloudFormationtemplatesarewritteninJSONandusuallycontainatleastthreesections(inanyorder):parameters,resourcesandoutputs.
Unfortunatelyitisnotpossibletostoretheseintoseparatefiles(withtheexceptionofparametervalues),sointhisexamplewewillworkwithasingletemplatefilenamedmain.json.
Templatescanbeusedlocallyorimportedfromaremotelocation(anS3bucketisacommonchoice).
Parameters
ParametersaddflexibilityandportabilitytoourStackbylettinguspassvariablestoitsuchasinstancetypes,AMIids,SSHkeypairnamesandsimilarvalueswhichitisbestnottohard-code.
Eachparametertakesanarbitrarylogicalname(alphanumeric,uniquewithinthetemplate),description,type,andanoptionaldefaultvalue.TheavailabletypesareString,Number,CommaDelimitedList,andthemorespecialAWS-specifictype,suchasAWS::EC2::KeyPair::KeyName,asseenintheprecedingcode.
Thelatterisusefulforvalidation,asCloudFormationwillcheckwhetherakeypairwiththegivennameactuallyexistsinyourAWSaccount.
ParameterscanalsohavepropertiessuchasAllowedValues,Min/MaxLength,Min/MaxValue,NoEchoandother(pleaseseehttp://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html).
Thereisalimitof60parameterspertemplate.
Letusexaminetheparametersfoundatthetopofourtemplate:
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/main.json.
"Parameters":{"vpcCidr":{"Description":"VPCCIDR","Type":"String"},"vpcName":{"Description":"VPCname","Type":"String"},"awsAvailabilityZones":{
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.htmlhttps://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/main.json
"Description":"ListofAZs","Type":"CommaDelimitedList"},"publicCidr":{"Description":"ListofpublicsubnetCIDRs","Type":"CommaDelimitedList"},..."rdsInstanceClass":{"Description":"RDSinstanceclass","Type":"String","AllowedValues":["db.t2.micro","db.t2.small","db.t2.medium"]},"rdsUsername":{"Description":"RDSusername","Type":"String"},"rdsPassword":{"Description":"RDSpassword","Type":"String","NoEcho":"true"},..."autoscalingGroupKeyname":{"Description":"EC2sshkeyname","Type":"AWS::EC2::KeyPair::KeyName"},"autoscalingGroupImageId":{"Description":"EC2AMIID","Type":"AWS::EC2::Image::Id"}}
Wehaveusedthefollowing:
CommaDelimitedList,whichwewillconvenientlyquerylaterwithaspecialfunctionAllowedValuesandMinValuetoenforceconstraintsNoEchoforpasswordsorothersensitivedataSomeAWS-specifictypestohaveCloudFormationfurthervalidateinput
Youwillnoticethattherearenovaluesassignedtoanyoftheprecedingparameters.
Tomaintainareusabletemplate,wewillstorevaluesinaseparatefile(parameters.json):
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/parameters.json.
[{"ParameterKey":"vpcCidr","ParameterValue":"10.0.0.0/16"},{
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/parameters.json
"ParameterKey":"vpcName","ParameterValue":"CloudFormation"},{"ParameterKey":"awsAvailabilityZones","ParameterValue":"us-east-1b,us-east-1c"},{"ParameterKey":"publicCidr","ParameterValue":"10.0.1.0/24,10.0.3.0/24"},{"ParameterKey":"privateCidr","ParameterValue":"10.0.2.0/24,10.0.4.0/24"},{"ParameterKey":"rdsIdentifier","ParameterValue":"cloudformation"},{"ParameterKey":"rdsStorageSize","ParameterValue":"5"},{"ParameterKey":"rdsStorageType","ParameterValue":"gp2"},{"ParameterKey":"rdsEngine","ParameterValue":"postgres"},...
Resources
Youarealreadyfamiliarwiththeconceptofresourcesandhowtheyareusedtodescribedifferentpiecesofinfrastructure.
Regardlessofhowresourcesappearinatemplate,CloudFormationwillfollowitsinternallogictodecidetheorderinwhichthesegetprovisioned.
Thesyntaxfordeclaringaresourceisasfollows:
"LogicalID":{"Type":"","Properties":{}}
IDsneedtobealphanumericanduniquewithinthetemplate.
ThelistofCloudFormationresourcetypesandtheirpropertiescanbefoundhere:http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html
Themaxnumberofresourcesatemplatecanhaveis200.Reachingthatlimit,youwillneedtosplitatemplateintosmalleronesandpossiblylookintonestedstacks.
Backtoourexample,aspertraditionwestartbycreatingaVPCanditssupportingelementssuchassubnets,InternetgatewayandNATgateway:
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/main.json.
"Resources":{"vpc":{"Type":"AWS::EC2::VPC","Properties":{"CidrBlock":{"Ref":"vpcCidr"},"EnableDnsSupport":"true","EnableDnsHostnames":"true","Tags":[{"Key":"Name","Value":{"Ref":"vpcName"}}]}},"publicSubnet1":{"Type":"AWS::EC2::Subnet","Properties":{"AvailabilityZone":{"Fn::Select":["0",{"Ref":"awsAvailabilityZones"}]},"CidrBlock":{"Fn::Select":["0",{"Ref":"publicCidr"}]},"MapPublicIpOnLaunch":"true","Tags":[{"Key":"Name","Value":"Public"}],"VpcId":{"Ref":"vpc"}}},..."internetGateway":{"Type":"AWS::EC2::InternetGateway","Properties":{"Tags":[{"Key":"Name","Value":{"Fn::Join":["-",[{"Ref":"vpcName"},"IGW"]]}}]}},"internetGatewayAttachment":{"Type":"AWS::EC2::VPCGatewayAttachment","Properties":{"InternetGatewayId":{"Ref":"internetGateway"},"VpcId":{"Ref":"vpc"}}},"natEip":{"Type":"AWS::EC2::EIP","Properties":{"Domain":"vpc"}},"natGateway":{"Type":"AWS::EC2::NatGateway",
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/main.json
"Properties":{"AllocationId":{"Fn::GetAtt":["natEip","AllocationId"]},"SubnetId":{"Ref":"publicSubnet1"}},"DependsOn":"internetGatewayAttachment"},
NotesomeoftheCloudFormationfunctionsusedintheprecedingcode:
"Fn::Select"in"CidrBlock":{"Fn::Select":["0",{"Ref":"publicCidr"}]},whichallowsustoquerytheCommaDelimitedListtypeparameterswesetearlier"Fn::Join",forconcatenatingstrings"Fn::GetAtt",forretrievingresourceattributes
Also,theDependsOnpropertyofthenatGatewayresourceallowsustosetexplicitconditionsontheorderofexecution.Inthiscase,wearesayingthattheInternetGatewayresourceneedstobeready(attachedtotheVPC)beforetheNATGatewayisprovisioned.
AftertheVPC,let'saddRDS:
"rdsInstance":{"Type":"AWS::RDS::DBInstance","Properties":{"DBInstanceIdentifier":{"Ref":"rdsIdentifier"},"DBInstanceClass":{"Ref":"rdsInstanceClass"},"DBSubnetGroupName":{"Ref":"rdsSubnetGroup"},"Engine":{"Ref":"rdsEngine"},"EngineVersion":{"Ref":"rdsEngineVersion"},"MasterUserPassword":{"Ref":"rdsPassword"},"MasterUsername":{"Ref":"rdsUsername"},"StorageType":{"Ref":"rdsStorageType"},"AllocatedStorage":{"Ref":"rdsStorageSize"},"VPCSecurityGroups":[{"Ref":"rdsSecurityGroup"}],"Tags":[{"Key":"Name","Value":{"Ref":"rdsIdentifier"}}]}}
ThenaddtheELB:
..."elbInstance":{"Type":"AWS::ElasticLoadBalancing::LoadBalancer","Properties":{"LoadBalancerName":"cloudformation-elb","Listeners":[{"InstancePort":"80","InstanceProtocol":"HTTP","LoadBalancerPort":"80","Protocol":"HTTP"}],"SecurityGroups":[{"Ref":"elbSecurityGroup"}],"Subnets":[{"Ref":"publicSubnet1"},{"Ref":"publicSubnet2"}],"Tags":[{"Key":"Name","Value":"cloudformation-elb"}]}}
AndaddtheEC2resources:
..."launchConfiguration":{"Type":"AWS::AutoScaling::LaunchConfiguration","Properties":{"ImageId":{"Ref":"autoscalingGroupImageId"},"InstanceType":{"Ref":"autoscalingGroupInstanceType"},"KeyName":{"Ref":"autoscalingGroupKeyname"},"SecurityGroups":[{"Ref":"ec2SecurityGroup"}]
WestilluseaUserDatashellscripttoinstalltheNGINXpackage;however,thepresentationisslightlydifferentthistime.CloudFormationisgoingtoconcatenatethelinesusinganewlinecharacterasadelimiterthenencodetheresultinBase64:
"UserData":{"Fn::Base64":{"Fn::Join":["\n",["#!/bin/bash","set-euf-opipefail","exec1>>(logger-s-t$(basename$0))2>&1","yum-yinstallnginx;chkconfignginxon;servicenginxstart"]]}}}}
WeuseDependsOntoensuretheRDSinstancegoesinbeforeautoScalingGroup:
"autoScalingGroup":{"Type":"AWS::AutoScaling::AutoScalingGroup","Properties":{"LaunchConfigurationName":{"Ref":"launchConfiguration"},"DesiredCapacity":"1","MinSize":"1","MaxSize":"1","LoadBalancerNames":[{"Ref":"elbInstance"}],"VPCZoneIdentifier":[{"Ref":"privateSubnet1"},{"Ref":"privateSubnet2"}],"Tags":[{"Key":"Name","Value":"cloudformation-asg","PropagateAtLaunch":"true"}]},"DependsOn":"rdsInstance"}
Outputs
Again,wewillusethesetohighlightsomeresourceattributesfollowingasuccessfuldeployment.AnotherimportantfeatureofOutputs,however,isthattheycanbeusedasinputparametersforothertemplates(stacks).Thisbecomesveryusefulwithnestedstacks.
Note
Oncedeclared,Outputscannotbesubsequentlyupdatedontheirown.YouwillneedtomodifyatleastoneresourceinordertotriggeranOutputupdate.
WeaddtheVPCID,NATIPaddressandELBDNSnameasOutputs:
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/main.json.
"Outputs":{"vpcId":{"Description":"VPCID","Value":{"Ref":"vpc"}},"natEip":{"Description":"NATIPaddress","Value":{"Ref":"natEip"}},"elbDns":{"Description":"ELBDNS","Value":{"Fn::GetAtt":["elbInstance","DNSName"]}}}
Currently,atemplatecanhavenomorethan60Outputs.
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/blob/master/5585_02_CodeFiles/CloudFormation/main.json
OperationsIfyouhavebeenfollowingalong,youshouldnowhaveamain.jsonandaparameters.jsoninyourcurrentfolder.Itistimetoputthemtouse,sohereareafewoperationswearegoingtoperform:
ValidateatemplateDeployastackUpdateastackDeleteastack
Templatevalidation
Firstthingsfirst,abasiccheckofourJSONtemplatewithvalidate-template:
$awscloudformationvalidate-template--template-bodyfile://main.json{"Description":"ProvisionsEC2,ELB,ASGandRDSresources","Parameters":[{"NoEcho":false,"Description":"EC2AMIID","ParameterKey":"autoscalingGroupImageId"}
Ifthere'snoerrors,theCLIreturnstheparsedtemplate.Notethatwecouldhavejustaseasilypointedtoaremotelocationusing--template-urlinsteadof-template-body.
DeployingaStack
Todeployourtemplate(stack),wewillusecreate-stack.Ittakesanarbitraryname,thelocationofthetemplate,andthefilecontainingparametervalues:
$awscloudformationcreate-stack--stack-namecfn-test--template-bodyfile://main.json--parametersfile://parameters.json{"StackId":"arn:aws:cloudformation:us-east-1:xxxxxx:stack/cfn-test/xxxxxx"}
CloudFormationstartscreatingthestackandnofurtheroutputisreturned.TogetprogressinformationontheCLI,usedescribe-stacks:
$awscloudformationdescribe-stacks--stack-namecfn-test{"Stacks":[{"StackId":"arn:aws:cloudformation:us-east-xxxxxx:stack/cfn-test/xxxxxx"..."CreationTime":"2016-05-29T20:07:17.813Z","StackName":"cfn-test","NotificationARNs":[],"StackStatus":"CREATE_IN_PROGRESS",
"DisableRollback":false}]}
Andforevenmoredetails,usedescribe-stack-events.
Afterafewminutes(basedonoursmalltemplate)StackStatuschangesfromCREATE_IN_PROGRESStoCREATE_COMPLETEandweareprovidedtherequestedOutputs:
$awscloudformationdescribe-stacks--stack-namecfn-test"Outputs":[{"Description":"VPCID","OutputKey":"vpcId","OutputValue":"vpc-xxxxxx"},{"Description":"NATIPaddress","OutputKey":"natEip","OutputValue":"x.x.x.x"},{"Description":"ELBDNS","OutputKey":"elbDns","OutputValue":"cloudformation-elb-xxxxxx.us-east-1.elb.amazonaws.com"}],"CreationTime":"2016-05-29T20:07:17.813Z","StackName":"cfn-test","NotificationARNs":[],"StackStatus":"CREATE_COMPLETE","DisableRollback":false
Atthispoint,theelbDNSURLshouldreturnthenginxwelcomepage,asshownhere:
Ifnot,youmightneedtoallowsomemoretimefortheEC2nodetofullyinitialize.
Updatingastack
CloudFormationofferstwowaysofupdatingadeployedstack.
Note
Someupdateoperationscanbedestructive(pleaserefertohttp://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html).YoushouldalwayschecktheCloudFormationdocumentationontheresourceyouareplanningtomodifytoseewhetherachangeisgoingtocauseanyinterruption.
Ifyouwouldliketoquicklydeployaminorchange,thenallyouneedtodoismodifythetemplatefileanddeployitdirectlywithupdate-stack:
$awscloudformationupdate-stack--stack-namecfn-test--template-bodyfile://main.json--parametersfile://parameters.json
Otherwise,agoodpracticewouldbetouseChangeSetstopreviewstackchangesbeforedeployingthem.Forexample,letusupdatetherulesintheELBsecuritygroupaswedidbefore:
1. Modifythemain.jsontemplate(addanotherruletoelbSecurityGroup):
"elbSecurityGroup":{"Type":"AWS::EC2::SecurityGroup","Properties":{"SecurityGroupIngress":[{"ToPort":"80","FromPort":"80","IpProtocol":"tcp","CidrIp":"0.0.0.0/0"},{"ToPort":"443","FromPort":"443","IpProtocol":"tcp","CidrIp":"0.0.0.0/0"}]
2. CreateaChangeSet:
$awscloudformationcreate-change-set--change-set-nameupdatingElbSecGroup--stack-namecfn-test--template-bodyfile://main.json--parametersfile://parameters.json
3. PreviewtheChangeSet:
$awscloudformationdescribe-change-set--change-set-nameupdatingSecGroup--stack-namecfn-test
4. ExecutetheChangeSet:
$awscloudformationexecute-change-set--change-set-nameupdatingSecGroup--stack-namecfn-test
Tip
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html
WhetherviaaChangeSetorupdatingdirectly,ifyouaresimplymodifyingparametervalues(parameters.json)youcanskipre-uploadingthetemplate(main.json)with--use-previous-template.
Deletingastack
Inordertotidyupafterourexperiments,wewillneedtogranttemporaryAdminprivilegestotheCloudFormationIAMuser(thesameprocedureasintheearlierTFsection);rundelete-stack:
$awscloudformationdelete-stack--stack-namecfn-test
ThenrevoketheAdminprivileges.
SummaryInthischapter,welookedattheimportanceandusefulnessofInfrastructureasCodeandwaystoimplementitusingTerraformorAWSCloudFormation.
WeexaminedthestructureandindividualcomponentsofbothaTFandaCFtemplatethenpracticeddeployingthoseontoAWSusingtheCLI.Itrustthattheexampleswewentthroughhavedemonstratedthebenefitsandimmediategainsfromthepracticeofdeployinginfrastructureascode.
Sofar,however,wehaveonlydonehalfthejob.Withtheprovisioningstagecompleted,youwillnaturallywanttostartconfiguringyourinfrastructure,andthatiswhatwearegoingtodointhenextchapteronConfigurationManagement.
Chapter3.BringingYourInfrastructureUnderConfigurationManagementAshintedattheendofthepreviouschapter,thereissomemoreworktobedonebeforewecanclaimtohavefullyimplementedIaC.
Thefirststepwastodescribethehardwaresideofourinfrastructureincode;nowitistimetolookatthesoftwareorconfigurationaspectofit.
LetussaywehaveprovisionedafewEC2nodesandwouldliketohavecertainpackagesinstalledonthem,andrelevantconfigurationfilesupdated.PriortoConfigurationManagement(CM)toolsgainingpopularity,suchtaskswouldhavebeenperformedmanuallybyanengineereitherfollowingachecklist,runningacollectionofshellscripts,orboth.Asyoucanimagine,suchmethodsdonotscalewellastheygenerallyimplyoneengineersettinguponeserveratatime.
Inaddition,checklistsorscripts:
ArehardtowritewhenitcomestoconfiguringahostplusafullapplicationstackrunningonitAreusuallytargetedatagivenhostorapplicationandarenotveryportableGetprogressivelyhardertocomprehendthefurtheryougetfromthepersonwhooriginallywrotethemBuildscriptstendtogetexecutedonlyonce,usuallyatthetimeahostisprovisioned,thusconfigurationstartstodriftfromthatmomenton
Fortunately,notmanypeopleusethesenowadays,asConfigurationManagementhasbecomeacommonpractice.Letusexaminesomeofthebenefits:
CMallowsustodeclarethedesiredstateofamachineonceandthenreproducethatstateasoftenasnecessaryPowerfulabstractiontakescareofspecificssuchasenvironment,hardware,andOStype,allowingustowritereusableCMcodeThedeclaredmachinestatecodeiseasytoread,comprehend,andcollaborateon.ACMdeploymentcanbeperformedontens,hundreds,orthousandsofmachinessimultaneously
InthisageofDevOps,thereareavarietyofCMtoolstochoosefrom.YoumighthavealreadyheardofPuppet,Chef,Ansible,OpsWorks,ortheonewearegoingtouse-SaltStack(theSaltOpenproject).
Allofthesearewelldeveloped,sophisticatedCMsolutionswithactivecommunitiesbehindthem.Ifindithardtojustifyanyreportedclaimsofonebeingbetterthantherestastheyalldothejobprettywell,eachwithitsownsetofstrengthsandweaknesses.Sowhichoneyouuse,asis
oftenthecase,isuptopersonalpreference.
Regardlessofthetoolyouendupusing,Iwouldliketostresstheimportanceoftwopoints:namingconventionsandcodereusability.
Followingnamingconventionswhenwritingcodeisanobviouswinasitguaranteesotherpeoplewillbeabletounderstandyourworkwithlesseffort.Inadditiontowritingcodehowever,CMinvolvesexecutingitagainstyournodesandthisiswherenamingalsobecomesimportant.Imagineyouhadfourservers:leonardo,donatello,michelangelo,andraphael.Twoofthoseareyourfrontendlayerandtwothebackend,soyousitdownandwriteyourConfigurationManagementmanifestsrespectively:webserver-nodeanddatabase-node.Sofar,sogood,giventhenumberofhostsyoucanlaunchyourCMtoolandeasilytellittoruntherelevantmanifestagainsteachofthem.
Nowimagine50,then100hosts,withinasimilarflat-namingschema,andyoustarttoseetheproblem.Asthesizeandcomplexityofyourinfrastructuregrows,youwillneedahost-namingconventionthatnaturallyformsahierarchy.Hostnamessuchaswebserver-{0..10},db-{0..5}andcache-{0..5}canbefurthergroupedintofrontendandbackendandthenrepresentedinastructured,hierarchicalway.SuchawayofgroupingnodesbasedonroleorotherpropertiesisextremelyusefulwhenapplyingConfigurationManagement.
CodereusabilityshouldalreadybeonyourmindwhenyoustartwritingCMcode(manifests).Youwillfindthattherearegenerallytwowaysofapproachingthistask.Youcouldwritealarge,say,webserverpiecewhichcontainsinstructionsonhowtosetupthefirewall,someCLItools,NGINX,andPHPonanode,oryoucouldbreakitdownintosmallerpartslikeiptables,utils,NGINX,PHP,andsoon.
Inmyopinion,thelatterdesignaddssomeoverheadwhenwritingthemanifests,butthebenefitofreusabilityissubstantial.Insteadofwritinglargesetsofdeclarationsdedicatedtoeachservertype,youmaintainacollectionofgeneric,smallonesandcherry-pickfromthemtosuitthemachineinquestion.
Toillustrate:
manifests:everything_a_websrv_needs,everything_for_a_db,cache_mainnodes:web01,db01,cache01CM_execution:web01=(everything_a_websrv_needs),db01=(everything_for_a_db),cache01=(cache_main)
Orbetter:
manifests:iptables,utils,nginx,postgresql,redis,phpnodes:web01,db01,cache01CM_execution:web01=(iptables,utils,nginx,php),db01=(iptables,utils,postgresql),cache01=(iptables,utils,redis)
IntroductiontoSaltStackSaltStack(seehttps://saltstack.com/),firstreleasedin2011,isanautomationsuitewhichoffersConfigurationManagementplusstandardand/orevent-drivenorchestration.Itiscommonlyusedinamaster-minionsetup,whereamasternodeprovidescentralizedcontrolacrossacomputeestate.Itisknownforitsspeedandscalabilitythankstothefastandlightweightmessagebus(ZeroMQ)usedforcommunicationbetweenthesalt-masterandminions.Itcanalsobeusedinanagentlessfashion,wheretheminionsarecontrolledoverSSH,similarlytohowAnsibleoperates.
SaltStackiswritteninPythonandiseasilyextensible.Youcanwriteyourownmodulesforit,attachlong-runningprocessestoitseventbus,andinjectrawPythoncodeinunusualplaces.
Themaster-minionmodelisquitepowerful,offersalotofflexibility,andistherecommendedapproachifyouarelookingafteranythingmorethanafewdevnodesandwanttotakeadvantageofallthefeaturesSaltStackhastooffer.
Note
Moreonhowtogetasalt-masterupandrunningcanbefoundhere:https://docs.saltstack.com/en/latest/topics/configuration/index.html
Inourcase,wearegoingtoexplorethepowerofConfigurationManagementusingSaltStackinastandaloneormasterlessmode.WewillreusepartsoftheTerraformtemplatefromthepreviouschaptertolaunchasetofEC2resources,bootstrapaSaltStackminionandhaveitconfigureitselftoserveawebapplication.
Providedallgoeswell,weshouldendupwithafullyconfiguredwebserver(EC2node)behindaload-balancer(EC2ELB).
Hereisourtask-list:
1. PrepareourSaltStackdevelopmentenvironment.2. WritetheconfigurationthatwewouldlikeSaltStacktoapplytoournode(s).3. ComposetheTerraformtemplatedescribingourinfrastructure.4. DeploytheinfrastructureviaTerraformandletSaltStackconfigureit.
https://saltstack.com/https://docs.saltstack.com/en/latest/topics/configuration/index.html
PreparationSaltStackConfigurationManagementisperformedusingthefollowingmaincomponents:
Statesarethefileswhichdescribethedesiredstateofamachine.Herewewriteinstructionsforinstallingpackages,modifyingfiles,updatingpermissions,andsoon.PillarsarethefilesinwhichwedefinevariablestohelpmakeStatesmoreportableandflexible.Grainsarepiecesofinformationgatheredontheminionhostitself.TheseincludedetailsabouttheOS,environment,thehardwareplatform,andothers.TheSaltFileServerstoresanyfiles,scripts,orotherartifactswhichmaybereferencedintheStates.TheSaltTopfile(s)areusedtomapStatesand/orPillarstominions.
Inamaster-minionsetup,allofthesecomponentsexcepttheGrainswouldbehostedonandmadeavailabletotheminionsbythesalt-master(otherbackendsarealsosupported).
WeareplanningtorunSaltinmasterlessmodehowever,meaningthatwewillneedawaytotransferanyStates,Pillars,andrelatedfilesfromourlocalenvironmenttotheminion.Git?Goodidea.WewillwriteallSaltcodelocally,pushittoaGitrepository,andthenhaveitcheckedoutontoeachminionatboottime.
AsforchoosingaGithostingsolution,GithuborBitbucketareexcellentservices,butgivingourminionEC2nodesaccesstothesewillinvolvesomekeyhandling.Incomparison,CodeCommit(theAWSGitsolution)offersamuchsmootherintegrationwithEC2instancesviaIAMRoles.
LetusstartbycreatinganewIAMuserandaCodeCommitGitrepository.Wewillbeusingtheuser'saccesskeystocreatetherepositoryandaSSHkeytocloneandworkwithit:
1. IntheAWSConsole,createanIAMuser(writedownthegeneratedaccesskeys)andattachtheAWSCodeCommitFullAccessbuilt-in/ManagedIAMpolicytoitasshowninthefollowingscreenshot:
2. Onthesamepage,switchtotheSecurityCredentialstabandclickontheUploadSSH
publickeyasshowninthefollowingscreenshot:
3. Configureawscli:
$exportAWS_ACCESS_KEY_ID='AKIAHNPFB9EXAMPLEKEY'$exportAWS_SECRET_ACCESS_KEY='rLdrfHJvfJUHY/B7GRFTY/VYSRwezaEXAMPLEKEY'$exportAWS_DEFAULT_REGION='us-east-1'
4. Createarepository:
$awscodecommitcreate-repository--repository-namesalt--repository-description"SaltStackrepo"{"repositoryMetadata":{"repositoryName":"salt","cloneUrlSsh":"ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/salt","lastModifiedDate":1465728037.589,"repositoryDescription":"SaltStackrepo","cloneUrlHttp":"https://git-codecommit.us-east-1.amazonaws.com/v1/repos/salt","creationDate":1465728037.589,"repositoryId":"d0628373-d9a8-44ab-942a-xxxxxx","Arn":"arn:aws:codecommit:us-east-1:xxxxxx:salt","accountId":"xxxxxx"}}
5. Clonethenewrepositorylocally:
$gitclonessh://[email protected]/v1/repos/saltCloninginto'salt'...warning:Youappeartohaveclonedanemptyrepository.
Checkingconnectivity...done.
Here,SSH_KEY_IDistheonewesawafteruploadingapublickeyinstep2.
Note
FormoreoptionsonconnectingtoCodeCommitseehttp://docs.aws.amazon.com/codecommit/latest/userguide/setting-up.html
Wearereadytostartpopulatingourempty,newSaltrepository.
http://docs.aws.amazon.com/codecommit/latest/userguide/setting-up.html
WritingConfigurationManagementcodeForSaltStacktohelpusconfigureournodeasawebserver,weneedtotellitwhatoneofthoseshouldlooklike.InConfigurationManagementterms,weneedtodescribethedesiredstateofthemachine.
Inourexample,wewillbeusingacombinationofSaltStackStates,Pillars,Grains,andTopfilestodescribetheprocessesof:
CreatingLinuxuseraccountsInstallingservices(NGINXandPHP-FPM)Configuringandrunningtheinstalledservices
StatesAStatecontainsasetofinstructionswhichwewouldliketobeappliedtoourEC2minion(s).Wewilluse/srv/salt/statesontheminionastherootoftheSaltStatetree.Statescanbestoredinthereintheformofasinglefile,forexample/srv/salt/states/mystate.sls,ororganizedintofolderslikeso/srv/salt/states/mystate/init.sls.Lateron,whenwerequestthatmystateisexecuted,Saltwilllookforeitherastate_name.slsorastate_name/init.slsintherootoftheStateTree.Ifindthesecondapproachtidierasitallowsforotherstate-relatedfilestobekeptintherelevantfolder.
WebegintheConfigurationManagementofourwebservernodewithastateformanagingLinuxuseraccounts.InsideourSaltGitrepository,wecreatestates/users/init.sls:
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/users.
veselin:user.present:-fullname:VeselinKantsev-uid:{{salt['pillar.get']('users:veselin:uid')}}-password:{{salt['pillar.get']('users:veselin:password')}}-groups:-wheelssh_auth.present:-user:veselin-source:salt://users/files/veselin.pub-require:-user:veselinsudoers:file.managed:-name:/etc/sudoers.d/wheel-contents:'%wheelALL=(ALL)ALL'
WewilluseYAMLtowritemostSaltconfiguration.Youwillnoticethreedifferentstatemodulesusedintheprecedingsection:
user.present:Thismoduleensuresthatagivenuseraccountexistsonthesystemorcreatesoneifnecessaryssh_auth.present:AmoduleformanagingtheSSHauthorized_keysfileofauserfile.managed:Amoduleforcreating/modifyingfiles
Note
SaltStack'sstatemodulesofferrichfunctionality.Forfulldetailsofeachmoduleseehttps://docs.saltstack.com/en/latest/ref/states/all/
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/usershttps://docs.saltstack.com/en/latest/ref/states/all/
Toavoidhardcodingcertainvaluesunderuser.present,wemakeuseoftheSaltStackPillarssystem.Wewillexamineapillarfileshortly,butfornowjustnotethesyntaxofreferencingpillarvaluesinsideourstate.
Twootherpointsofinterestherearethesourceofourkeyfileandtherequireproperty.Inthisexample,asalt://formattedsourceaddressreferstotheSaltFileServerwhichbydefaultservesfilesfromtheStateTree(forsupportedbackends,pleaseseehttps://docs.saltstack.com/en/latest/ref/file_server/).Therequirestatementenforcesanorderofexecution,ensuringthattheuseraccountispresentbeforetryingtocreateanauthorized_keysfileforit.
Note
SaltStackfollowsanimperativeexecutionmodeluntilsuchcustomorderingisenforced,invokingadeclarativemode(seehttps://docs.saltstack.com/en/latest/ref/states/ordering.html).
ThankstothereadabilityofYAML,onecaneasilytellwhatisgoingonhere:
1. WecreateanewLinuxuser.2. Weapplydesiredattributes(uid,password,group,andsoon).3. WedeployanSSHauthorized_keysfileforit.4. Weenablesudoforthewheelgroupofwhichtheuserisamember.
Perhapsyoucouldtryeditthisstateandaddauserforyourself?Itwillbeusefullaterafterwedeploy.
WewillnowmoveontoanNGINXinstallationviastates/nginx/init.sls.
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/nginx.
WeinstallNGINXusingthepkg.installedmodule:
pkg.installed:[]
Settheservicetostartonboot(enable:True),enablereloadinginsteadofrestartingwhenpossible(reload:True),ensuretheNGINXpkghasbeeninstalled(require:)beforerunningtheservice(service.running:)
nginx:service.running:-enable:True-reload:True-require:-pkg:nginx
https://docs.saltstack.com/en/latest/ref/file_server/https://docs.saltstack.com/en/latest/ref/states/ordering.htmlhttps://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/nginx
Thenputaconfigfileinplace(file.managed:),ensuringtheservicewaitsforthistohappen(require_in:)andalsoreloadseachtimethefileisupdated(watch_in:):
/etc/nginx/conf.d/default.conf:file.managed:-source:salt://nginx/files/default.conf-require:-pkg:nginx-require_in:-service:nginx-watch_in:-service:nginx
Notetherequire/require_in,watch/watch_inpairs.Thedifferencebetweeneachoftheserequisitesandits_incounterpartliesinthedirectioninwhichtheyact.
Forexample:
nginx:service.running:-watch:-file:nginx_confignginx_config:file.managed:-name:/etc/nginx/nginx.conf-source:salt://...
Hasthesameeffectas:
nginx:service.running:[]nginx_config:file.managed:-name:/etc/nginx/nginx.conf-source:salt://...-watch_in:-service:nginx
Inbothcases,theNGINXservicerestartsonconfigfilechanges;however,youcanseehowthesecondformatcanbepotentiallyquiteusefulthefurtheryougetfromtheserviceblock-sayinadifferentfile,aswewillseeinthenextstate.
AddinsomePHP(states/php-fpm/init.sls):
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/php-fpm.
include:-nginxphp-fpm:
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/php-fpm
pkg.installed:-name:php-fpm-require:-pkg:nginxservice.running:-name:php-fpm-enable:True-reload:True-require_in:-service:nginx...
Hereyoucanbetterseetheusefulnessofan_inrequisite.Afterweincludethenginxstateatthetop,ourrequire_inmakessurethatnginxdoesnotstartbeforephp-fpmdoes.
WithNGINXandPHP-FPMnowconfigured,letusaddaquicktestpage(states/phptest/init.sls).
Note
Pleasereferto:https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/phptest.
WesetafewvariablespulledfromGrains(moreonthoseshortly):
{%setpublqic_ipv4=salt['cmd.shell']('ec2-metadata--public-ipv4|awk'{print$2}'')%}{%setgrains_ipv4=salt['grains.get']('ipv4:0')%}{%setgrains_os=salt['grains.get']('os')%}{%setgrains_osmajorrelease=salt['grains.get']('osmajorrelease')%}{%setgrains_num_cpus=salt['grains.get']('num_cpus')%}{%setgrains_cpu_model=salt['grains.get']('cpu_model')%}{%setgrains_mem_total=salt['grains.get']('mem_total')%}
Thenwedeploythetestpageandaddcontentstoitdirectly:
phptest:file.managed:-name:/var/www/html/index.php-makedirs:True-contents:|
Wewillusethispagepost-deploymenttocheckwhetherbothNGINXandPHP-FPMareoperational.
https://github.com/PacktPublishing/Implementing-DevOps-on-AWS/tree/master/5585_03_CodeFiles/CodeCommit/salt/states/phptest
PillarsNowletuslookatthemainmechanismforstoringvariablesinSalt-thePillars.Theseare:
YAMLtree-likedatastructuresDefined/renderedonthesalt-master,unlessrunningmasterlessinwhichcasetheyliveontheminionUsefulforstoringvariablesinacentralplacetobesharedbytheminions(unlesstheyaremasterless)HelpfulforkeepingStatesportableAppropriateforsensitivedata(theycanalsobeGPGencrypted;seehttps://docs.saltstack.com/en/latest/ref/renderers/all/salt.renderers.gpg.html)
Wewillbeusing/srv/salt/pillarsastherootofourPillartreeontheminion.Letusgobacktotheusersstateandexaminethefollowinglines:
-uid:{{salt['pillar.get']('users:veselin:uid')}}-password:{{salt['pillar.get']('users:veselin:password')}}
Theuidandpasswordattributesaresettobesourcedfromapillarnamedusers.AndifwecheckourPillarTree,wefinda/srv/salt/pillars/users.slsfilecontaining:
users:veselin:uid:5001password:'$1$wZ0gQOOo$HEN/gDGS85dEZM7QZVlFz/'
Itisnoweasytoseehowtheusers:veselin:passwordreferenceinsidethestatefilematchesagainstthispillar'sstructure.
Note
Formoredetailsandexamplesonpillarusage,see:https://docs.saltstack.com/en/latest/topics/tutorials/pillar.html
https://docs.saltstack.com/en/latest/ref/renderers/all/salt.renderers.gpg.htmlhttps://docs.saltstack.com/en/latest/topics/tutorials/pillar.html
GrainsUnlikePillars,Grainsareconsideredstaticdata:
Theygetgeneratedminion-sideandarenotsharedbetweendifferentminionsTheycontainfactsabouttheminionitselfTypicalexamplesareCPU,OS,networkinterfaces,memory,andkernelsItispossibletoaddcustomGrainstoaminion
WehavealreadymadegooduseofGrainswithinourprecedingtestpage(s