opdatering, 17. November 2016: Vi tog denne blogindlægsserie, udvidede den og gjorde den til en bog kaldet Terraform: up& løb!
opdatering, 8. juli 2019: vi har opdateret denne blogindlægsserie til Terraform 0.12 og udgivet 2. udgave af Terraform: up & kører!
Dette er del 1 i den omfattende Guide til Terraform-serien. I introduktionen til serien diskuterede vi, hvorfor alle virksomheder skulle bruge infrastructure-as-code (IAC). I dette indlæg skal vi diskutere, hvorfor vi valgte Terraform som vores valgte IAC-værktøj.
Hvis du søger på internettet efter “infrastructure-as-code”, er det ret nemt at komme med en liste over de mest populære værktøjer:
- Chef
- Puppet
- Ansible
- CloudFormation
- Terraform
hvad der ikke er let er at finde ud af, hvilken af disse du skal bruge. Alle disse værktøjer kan bruges til at styre infrastruktur som kode. Alle af dem er open source, støttet af store samfund af bidragydere, og arbejder med mange forskellige cloud-udbydere (med den bemærkelsesværdige undtagelse af CloudFormation, som kun er lukket kilde). Alle tilbyder virksomhedssupport. Alle af dem er veldokumenterede, både med hensyn til officiel dokumentation og samfundsressourcer såsom blogindlæg og spørgsmål om Stackoverløb. Så hvordan beslutter du?
hvad der gør dette endnu sværere er, at de fleste af de sammenligninger, du finder online mellem disse værktøjer, gør lidt mere end at liste de generelle egenskaber for hvert værktøj og få det til at lyde som om du kunne være lige så vellykket med nogen af dem. Og selvom det er teknisk sandt, er det ikke nyttigt. Det er lidt som at fortælle en programmerende nybegynder, at du kunne være lige så vellykket at opbygge en hjemmeside med PHP, C eller Assembly — en erklæring, der er teknisk sandt, men en, der udelader en enorm mængde oplysninger, der ville være utroligt nyttige til at træffe en god beslutning.
i dette indlæg vil vi dykke ind i nogle meget specifikke grunde til, hvorfor vi valgte Terraform over de andre IAC-værktøjer. Som med alle teknologibeslutninger er det et spørgsmål om afvejninger og prioriteter, og selvom dine særlige prioriteter kan være anderledes end vores, håber vi, at deling af vores tankeproces vil hjælpe dig med at tage din egen beslutning. Her er de vigtigste afvejninger, vi overvejede:
- konfigurationsstyring vs Provisioning
- foranderlig infrastruktur vs uforanderlig infrastruktur
- proceduremæssig vs deklarativ
- Master vs Masterless
- Agent vs Agentless
- stort samfund vs lille samfund
- moden vs banebrydende
- brug af flere værktøjer sammen
kok, marionet, Ansible og SaltStack er alle konfigurationsstyring værktøjer, hvilket betyder, at de er designet til at installere og administrere programmer på eksisterende servere. CloudFormation og Terraform er klargøringsværktøjer, hvilket betyder, at de er designet til at levere serverne selv (såvel som resten af din infrastruktur, som belastningsbalancere, databaser, netværkskonfiguration osv.), hvilket efterlader jobbet med at konfigurere disse servere til andre værktøjer. Disse to kategorier udelukker ikke hinanden, da de fleste konfigurationsstyringsværktøjer kan udføre en vis grad af klargøring, og de fleste klargøringsværktøjer kan udføre en vis grad af konfigurationsstyring. Men fokus på konfigurationsstyring eller klargøring betyder, at nogle af værktøjerne passer bedre til bestemte typer opgaver.
Vi har især fundet ud af, at hvis du bruger Docker eller Packer, er langt størstedelen af dine konfigurationsstyringsbehov allerede taget hånd om. Med Docker og Packer kan du oprette billeder (såsom containere eller virtuelle maskinbilleder), der har alle de programmer, din server har brug for, allerede installeret og konfigureret. Når du har et sådant billede, er alt hvad du behøver en server til at køre det. Og hvis alt hvad du skal gøre er at levere en masse servere, så vil et provisioneringsværktøj som Terraform typisk være bedre egnet end et konfigurationsstyringsværktøj (her er et eksempel på, hvordan du bruger Terraform til at implementere Docker).
foranderlig infrastruktur vs uforanderlig infrastruktur
Konfigurationsstyringsværktøjer som Chef, Puppet, Ansible og SaltStack er typisk standard til et foranderligt infrastrukturparadigme. Hvis du f.eks. beder Chef om at installere en ny version af OpenSSL, kører den programopdateringen på dine eksisterende servere, og ændringerne vil ske på stedet. Efterhånden som du anvender flere og flere opdateringer, opbygger hver server en unik historie med ændringer. Dette fører ofte til et fænomen kendt som konfigurationsdrift, hvor hver server bliver lidt anderledes end alle de andre, hvilket fører til subtile konfigurationsfejl, der er vanskelige at diagnosticere og næsten umulige at gengive.
Hvis du bruger et klargøringsværktøj som Terraform til at implementere maskinbilleder oprettet af Docker eller Packer, er hver “ændring” faktisk en implementering af en ny server (ligesom enhver “ændring” til en variabel i funktionel programmering returnerer faktisk en ny variabel). Hvis du f.eks. vil implementere en ny version af OpenSSL, skal du oprette et nyt billede ved hjælp af Packer eller Docker med den nye version af OpenSSL, der allerede er installeret, implementere billedet på tværs af et sæt helt nye servere og derefter fjerne de gamle servere. Denne fremgangsmåde reducerer sandsynligheden for konfigurationsdriftfejl, gør det nemmere at vide præcis, hvilket program der kører på en server, og giver dig mulighed for trivielt at implementere enhver tidligere version af programmet til enhver tid. Selvfølgelig er det muligt at tvinge konfigurationsstyringsværktøjer til også at udføre uforanderlige implementeringer, men det er ikke den idiomatiske tilgang til disse værktøjer, mens det er en naturlig måde at bruge klargøringsværktøjer på.
proceduremæssig vs deklarativ
Chef og Ansible tilskynder til en procedurestil, hvor du skriver kode, der trin for trin angiver, hvordan man opnår en ønsket sluttilstand. Terraform, CloudFormation, SaltStack og Puppet tilskynder alle til en mere deklarativ stil, hvor du skriver kode, der angiver din ønskede sluttilstand, og selve IAC-værktøjet er ansvarlig for at finde ud af, hvordan du opnår denne tilstand.lad os f.eks. sige, at du ønskede at installere 10 servere (“EC2 Instances” i Lingo) for at køre v1 i en app. Her er et forenklet eksempel på en Ansibel skabelon, der gør dette med en proceduremæssig tilgang:
- ec2:
count: 10
image: ami-v1
instance_type: t2.micro
og her er et forenklet eksempel på en Terraform skabelon, der gør det samme ved hjælp af en deklarativ tilgang:
resource "aws_instance" "example" {
count = 10
ami = "ami-v1"
instance_type = "t2.micro"
}
nu på overfladen kan disse to tilgange se ens ud, og når du oprindeligt udfører dem med Ansible eller Terraform, de vil give lignende resultater. Det interessante er, hvad der sker, når du vil foretage en ændring.
forestil dig for eksempel, at trafikken er steget, og du vil øge antallet af servere til 15. Med Ansible er den procedurekode, du skrev tidligere, ikke længere nyttig; hvis du lige har opdateret antallet af servere til 15 og reran den kode, ville den implementere 15 nye servere, hvilket giver dig 25 i alt! Så i stedet skal du være opmærksom på, hvad der allerede er implementeret og skrive et helt nyt proceduremæssigt script for at tilføje de 5 nye servere:
- ec2:
count: 5
image: ami-v1
instance_type: t2.micro
med deklarativ kode, da alt hvad du gør er at erklære den ønskede sluttilstand, og Terraform finder ud af, hvordan du kommer til den sluttilstand, vil Terraform også være opmærksom på enhver tilstand, den oprettede i fortiden. For at implementere 5 flere servere er alt, hvad du skal gøre, at gå tilbage til den samme Terraform-skabelon og opdatere optællingen fra 10 til 15:
resource "aws_instance" "example" {
count = 15
ami = "ami-v1"
instance_type = "t2.micro"
}
Hvis du udførte denne skabelon, ville Terraform indse, at den allerede havde oprettet 10 servere, og at alt det skulle gøre var at oprette 5 nye servere. Faktisk, før du kører denne skabelon, kan du bruge Terraforms plan
kommando til at forhåndsvise, hvilke ændringer det ville gøre:
$ terraform plan+ aws_instance.example.11
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.12
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.13
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.14
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.15
ami: "ami-v1"
instance_type: "t2.micro"Plan: 5 to add, 0 to change, 0 to destroy.
Hvad sker der nu, når du vil implementere v2 tjenesten? Med den proceduremæssige tilgang er begge dine tidligere Ansible skabeloner igen ikke nyttige, så du skal skrive endnu en skabelon for at spore de 10 servere, du implementerede tidligere (eller var det 15 Nu?) og omhyggeligt opdatere hver enkelt til den nye version. Med Terraforms deklarative tilgang går du tilbage til den nøjagtige samme skabelon igen og ændrer simpelthen ami-versionsnummeret til v2:
resource "aws_instance" "example" {
count = 15
ami = "ami-v2"
instance_type = "t2.micro"
}
det er klart, at ovenstående eksempler forenkles. Ved hjælp afinstance_tags
ogcount_tag
parametre), men at skulle manuelt finde ud af denne slags logik for hver enkelt ressource, du administrerer med Ansible, baseret på hver ressources tidligere historie, kan være overraskende kompliceret (f. eks. finde eksisterende forekomster ikke kun efter tag, men også billedversion, tilgængelighedsområde osv.). Dette fremhæver to store problemer med proceduremæssige IAC-værktøjer:
- når man beskæftiger sig med procedurekode, er infrastrukturens tilstand ikke fuldt ud fanget i koden. At læse gennem de tre Ansible skabeloner, vi oprettede ovenfor, er ikke nok til at vide, hvad der er implementeret. Du skal også vide, i hvilken rækkefølge vi anvendte disse skabeloner. Havde vi anvendt dem i en anden rækkefølge, kan vi ende med en anden infrastruktur, og det er ikke noget, du kan se i selve kodebasen. Med andre ord, at ræsonnere om en Ansible eller kok kodebase, du er nødt til at kende den fulde historie om enhver ændring, der nogensinde er sket.
- genanvendeligheden af procedurekode er i sagens natur begrænset, fordi du manuelt skal tage hensyn til kodebasens aktuelle tilstand. Da denne tilstand konstant ændrer sig, kan kode, du brugte for en uge siden, muligvis ikke længere bruges, fordi den var designet til at ændre en tilstand af din infrastruktur, der ikke længere eksisterer. Som et resultat har procedurekodebaser en tendens til at vokse sig store og komplicerede over tid.
på den anden side repræsenterer koden altid den nyeste tilstand af din infrastruktur med den slags deklarative tilgang, der anvendes i Terraform. Et overblik, du kan fortælle, hvad der i øjeblikket er implementeret, og hvordan det er konfigureret, uden at skulle bekymre sig om historie eller timing. Dette gør det også nemt at oprette genanvendelig kode, da du ikke behøver manuelt at redegøre for verdens aktuelle tilstand. I stedet fokuserer du bare på at beskrive din ønskede tilstand, og Terraform finder ud af, hvordan du automatisk kommer fra den ene tilstand til den anden. Som et resultat har Terraform-kodebaser en tendens til at forblive små og lette at forstå.
selvfølgelig er der også ulemper ved deklarative sprog. Uden adgang til et fuldt programmeringssprog er din ekspressive kraft begrænset. For eksempel er nogle typer infrastrukturændringer, såsom en rullende implementering af nul nedetid, svære at udtrykke rent deklarative udtryk. Tilsvarende, uden evnen til at gøre “logik” (f.eks. if-udsagn, sløjfer), kan det være vanskeligt at oprette generisk, genanvendelig kode (især i CloudFormation). Heldigvis giver Terraform et antal kraftfulde primitiver, såsom inputvariabler, outputvariabler, moduler, create_before_destroy
og count
, der gør det muligt at oprette ren, konfigurerbar, modulær kode, selv på et deklarativt sprog. Vi diskuterer disse værktøjer mere i Del 4, Hvordan man opretter genanvendelig infrastruktur med Terraform-moduler og Del 5, Terraform-tip & tricks: sløjfer, if-udsagn og faldgruber.
Master Versus Masterless
som standard kræver Chef, Puppet og SaltStack, at du kører en master server til lagring af tilstanden af din infrastruktur og distribution af opdateringer. Hver gang du vil opdatere noget i din infrastruktur, bruger du en klient (f.eks. et kommandolinjeværktøj) til at udstede nye kommandoer til masterserveren, og masterserveren skubber enten opdateringerne ud til alle de andre servere, eller disse servere trækker de seneste opdateringer ned fra masterserveren regelmæssigt.
en master server tilbyder et par fordele. For det første er det et enkelt, centralt sted, hvor du kan se og styre status for din infrastruktur. Chef Console, Puppet Enterprise Console) til masterserveren for at gøre det lettere at se, hvad der foregår. For det andet kan nogle masterservere køre kontinuerligt i baggrunden og håndhæve din konfiguration. På den måde, hvis nogen foretager en manuel ændring på en server, kan masterserveren vende tilbage denne ændring for at forhindre konfigurationsdrift.
men at skulle køre en master server har nogle alvorlige ulemper:
- ekstra infrastruktur: du skal installere en ekstra server eller endda en klynge af ekstra servere (for høj tilgængelighed og skalerbarhed), bare for at køre master.
- Vedligeholdelse: du skal vedligeholde, opgradere, sikkerhedskopiere, overvåge og skalere masterserveren (- erne).
- sikkerhed: du skal give en måde for klienten at kommunikere til masterserveren(E) og en måde for masterserveren(e) at kommunikere med alle de andre servere, hvilket typisk betyder at åbne ekstra porte og konfigurere ekstra godkendelsessystemer, som alle øger dit overfladeareal til angribere.Chef, Puppet og SaltStack har forskellige niveauer af support til masterless-tilstande, hvor du bare kører deres agentprogram på hver af dine servere, typisk på en periodisk tidsplan (f.eks. Dette reducerer antallet af bevægelige dele betydeligt, men som diskuteret i næste afsnit efterlader dette stadig en række ubesvarede
spørgsmål, især om, hvordan man leverer serverne og installerer agentprogrammet på dem i første omgang.Ansible, CloudFormation, Heat og Terraform er alle masterless som standard. Eller for at være mere præcis kan nogle af dem stole på en MasterServer, men det er allerede en del af den infrastruktur, du bruger, og ikke et ekstra stykke, du skal administrere. For eksempel kommunikerer Terraform med skyudbydere ved hjælp af skyudbyderens API ‘ er, så API-serverne er på en eller anden måde masterservere, bortset fra at de ikke kræver nogen ekstra infrastruktur eller nogen ekstra godkendelsesmekanismer (dvs.bare brug dine API-nøgler). Ansible fungerer ved at oprette forbindelse direkte til hver server via SSH, så igen behøver du ikke køre nogen ekstra infrastruktur eller administrere ekstra godkendelsesmekanismer (dvs.bare brug dine SSH-nøgler).
Agent Versus Agentless
Chef, Puppet og SaltStack kræver alle, at du installerer agentprogram (f.eks. Agenten kører typisk i baggrunden på hver server og er ansvarlig for
installation af de nyeste konfigurationsstyringsopdateringer.dette har et par ulemper:
- Bootstrapping: Hvordan leverer du dine servere og installerer agentprogrammet på dem i første omgang? Nogle konfigurationsstyringsværktøjer sparker dåsen ned ad vejen, forudsat at en ekstern proces tager sig af dette for dem (f.eks. bruger du først Terraform til at implementere en masse servere med et VM-billede, der allerede har agenten installeret); andre konfigurationsstyringsværktøjer har en særlig bootstrapping-proces, hvor du kører engangskommandoer for at levere serverne ved hjælp af cloud provider API ‘ er og installere agentprogrammet på disse servere via SSH.
- vedligeholdelse: Du skal omhyggeligt Opdatere agentprogrammet regelmæssigt og være omhyggelig med at holde det synkroniseret med masterserveren, hvis der er en. Du skal også overvåge agentprogrammet og genstarte det, hvis det går ned.
- sikkerhed: hvis agentprogrammet trækker konfigurationen ned fra en MasterServer (eller en anden server, hvis du ikke bruger en master), skal du åbne udgående porte på hver server. Hvis masterserveren skubber konfigurationen til agenten, skal du åbne indgående porte på hver server. I begge tilfælde skal du finde ud af, hvordan du godkender agenten til den server, den taler med. Alt dette øger dit overfladeareal til angribere.
endnu en gang har Chef, Puppet og SaltStack forskellige niveauer af støtte til agentløse tilstande (f.eks. Det er derfor i naturen, standard-eller idiomatisk konfiguration for Kok, marionet, og SaltStack Inkluderer næsten altid en agent, og normalt også en mester.
alle disse ekstra bevægelige dele introducerer et stort antal nye fejltilstande i din infrastruktur. Hver gang du får en fejlrapport klokken 3, skal du finde ud af, om det er en fejl i din applikationskode eller din IAC-kode eller konfigurationsstyringsklienten eller masterserveren(E), eller den måde, klienten taler til masterserveren(E), eller den måde, andre servere taler til masterserveren(E), eller…
Ansible, CloudFormation, Heat og Terraform kræver ikke, at du installerer ekstra agenter. Eller for at være mere præcis kræver nogle af dem agenter, men disse er typisk allerede installeret som en del af den infrastruktur, du bruger. Google Cloud og alle andre cloud-udbydere sørger for at installere, administrere og godkende agentprogrammer på hver af deres fysiske servere. Som bruger af Terraform behøver du ikke bekymre dig om noget af det: du udsteder bare kommandoer, og skyudbyderens agenter udfører dem for dig på alle dine servere. Med Ansible skal dine servere køre SSH-dæmonen,som alligevel er almindelig at køre på de fleste servere.
stort samfund vs lille samfund
Når du vælger en teknologi, vælger du også et samfund. I mange tilfælde kan økosystemet omkring projektet have større indflydelse på din oplevelse end selve teknologiens iboende kvalitet. Fællesskabet bestemmer, hvor mange personer der bidrager til projektet, hvor mange plug-ins,
integrationer og udvidelser der er tilgængelige, hvor nemt det er at finde hjælp online (f.eks. blogindlæg, spørgsmål om Stackoverløb), og hvor nemt det er at ansætte nogen til at hjælpe dig (f. eks. en medarbejder, konsulent eller supportvirksomhed).det er svært at foretage en nøjagtig sammenligning mellem samfund, men du kan se nogle tendenser ved at søge online. Tabellen nedenfor viser en sammenligning af populære IAC-værktøjer med data, jeg indsamlede i løbet af maj 2019, herunder Om IAC-værktøjet er open source eller lukket kilde, hvilke skyudbydere det understøtter, det samlede antal bidragydere og stjerner på GitHub, hvor mange forpligtelser og aktive problemer der var over en måned fra midten af April til midten af maj, hvor mange open source-biblioteker der er tilgængelige for værktøjet, antallet af spørgsmål, der er anført for det værktøj i Stackoverløb, og antallet af job, der nævner værktøjet på Indeed.com.