Snadná správa více serverů

Posted 07. 06. 2015 / By Petr Soukup / Vývoj

Pokud máte více serverů, tak asi víte, kolik práce zabere je udržovat. Kopírovat konfiguráky, aktualizovat balíčky a tak dále. Jenže ono to jde dělat mnohem jednodušeji.

Tuhle vychytávku používáme už několik let a žil jsem v dojmu, že to tak dělá každý. Evidentně to ale nijak zvlášť rozšířené není a i firmy s desítkami serverů řeší jejich konfiguraci zbytečně komplikovaně. Jak to dělat lépe?

Typické problémy

puppet-logoPokud máte jeden server (nebo třeba jenom VPS) a potřebujete změnit konfiguraci webserveru, tak se prostě přihlásíte, přepíšete řádek v konfiguráku, restartujete službu a je hotovo. Když ale máte dva servery, tak to musíte dělat dvakrát. Pokud se navíc nějak liší, tak ještě musíte dávat pozor, abyste to na každém změnili správně.

Zkuste si na chvíli představit, že potřebujete nainstalovat nový server. Třeba protože chcete přidat druhý nebo třeba chcete přejít na novější distribuci. Jak dlouho by vám to zabralo? Můžete třeba zkopírovat konfiguráky, zkusit vše spustit a pak postupně opravovat problémy.

A nebo to jde dělat mnohem jednodušeji...

Puppet: naprostá nutnost pro správu serveru

Právě kvůli těmto problémům používáme Puppet. Ten umožňuje definovat konfiguraci serveru ve svém jazyce a následně zajistí aplikaci této konfigurace.

Je to přímo skriptovací jazyk, takže s ním jdou vymyslet opravdové šílenosti. My používáme jen asi 5% z toho, co všechno umí a tak vám tady také převedu jen úplné základy.

Konfigurace nginx

Jak se s puppetem pracuje vám předvedu na jednoduchém příkladu. Zkusíme si nastavit server pro hosting jedné domény.

Manifesty

Celá konfigurace puppetu je řízená manifesty. V těch se definují zdroje, jejich vlastnosti a třeba podmínky, za kterých se mají použít. Manifesty jdou také různě skládat do sebe. Můžete tak mít hromadu manifestů a na každém serveru pak jen nastavíte, který se má použít. Manifesty navíc můžou mít definované závislosti, takže pak jen definujete, že server XYZ má hostovat doménu souki.cz a už neřešíte, že k tomu potřebuje webserver - to bude definované v manifestu souki.cz

node default {
    yumrepo { "nginx":
        descr => 'nginx repo',
        baseurl  => 'http://nginx.org/packages/mainline/centos/$releasever/$basearch/',
        enabled  => 1,
        priority => 1,
    } ->
    package { 'nginx':
        ensure => installed,
    } -> 
    file { "/etc/nginx/nginx.conf":
        ensure  => present,
        content => template("nginx/nginx.erb"),
        notify  => Service['nginx'],
    } ->
    service { "nginx":
        ensure     => running,
        enable     => true,
        restart    => '/etc/init.d/nginx reload',
        hasrestart => true,
        hasstatus => true,
    }

}

V tomto manifestu se definují čtyři objekty. Mezi nimi jsou navíc šipečky, které definují závislost. Pokud se nepodaří nějakou akci v řetězu provést, tak se nic dalšího v řetězu neprovede (ale ostatní řetězy pokračují) a zahlásí se chyba.

yumrepo nginx

Nejprve se vytvoří Yum repozitář, který poskytuje oficiální nginx balíčky. Díky tomu bude nginx v aktuální verzi a ne v zastaralé, kterou nabízí linuxová distribuce.

package nginx

Puppet zajistí, že na serveru bude nainstalovaný balíček nginx. Lze případně říct, v jaké konkrétní verzi má být nainstalovaný nebo jakým způsobem se má nainstalovat.

file nginx.conf

Vytvoří se soubor /etc/nginx/nginx.conf dle šablony nginx.erb (viz níže). Pokud se tento soubor změní (nebo poprvé vytvoří), tak se provede restart služby nginx. Pokud by během jednoho běhu bylo více požadavků na restart, tak se provede jen jednou.

service nginx

Definice služby nginx. Puppet zajistí, že vždy poběží, bude se spouštět po startu systému a restart (třeba v důsledku změny konfigurace) se provede přes reload.

Šablony konfigurace

V puppetu můžete definovat, že na určité místo v systému má vložit soubor. Například u nginx to ale nestačí. V konfiguraci je totiž potřeba uvést počet procesů a to je odvozeno od počtu jader, takže je potřeba tuto informaci doplnit dynamicky. Puppet pro tento účel má šablony, ve kterých můžete používat Ruby pro ovlivnění výstupu. Navíc už rovnou obsahuje proměnné s typickými údaji, jako je například počet jader systému.

user  nginx;
worker_processes <%= @processorcount %> ;

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    charset utf-8;
    include /etc/nginx/conf.d/*.conf;
}

Téměř všechno v tomto souboru je klasická syntax nginx konfigurace a s puppetem nemá nic společného. Jediné co se změnilo je <%= @processorcount %>, které se při zpracování nahradí dle aktuální hodnoty.

Moduly

Pro puppet je připravená spousta modulů, vytvářených komunitou. Například nginx pak můžete definovat přes modul obecně, místo abyste definovali konkrétní soubory, jako jsem tu dělal výše. Velmi praktické to je hlavně pokud máte třeba různé linuxové distribuce - nemusíte pak řešit, že na Centosu se instaluje z Yum a na Ubuntu z ... něčeho jiného.

Sám ale moduly nepoužívám. Přijde mi to příliš magické a pokud máme jen jeden systém, tak není tolik práce definovat konfiguraci přímo. Aspoň přesně vím, co je jak definováno a nejsem závislý na cizím modulu.

Zdroj konfigurace

Puppet pro svoji funkci potřebuje jen zmíněné textové soubory a je na vás, kam si je uložíte. Sám puppet nabízí puppet-server, který zajišťuje distribuci změn. Problém je, že při jeho použití jste závislí na funkčnosti serveru s konfigurací. Doporučil bych proto spíš vyhnout se tomuto způsobu.

Konfiguraci ukládáme raději do gitu, takže není problém se podívat do historie, kdy proběhla nějaká změna. Z gitu se pak exportuje celý balík do AWS S3. Na každém serveru je nastavený cron s tímto příkazem:

aws s3 sync --delete s3://simpliapuppet/ /etc/puppet/ && puppet apply /etc/puppet/site.pp &>> /var/log/puppet.log

Stáhne se aktuální konfigurace a spustí se puppet. Zásadní výhodou AWS S3 je, že lze snadno nastavit, který server má přístup ke kterým souborům a nebo třeba ještě šifrovat různé části konfigurace různými klíči. Konfigurace celé infrastruktury tak může být přehledně na jednom místě a přesto se každý server dostane jen k tomu relevantnímu.

Aplikování konfigurace

Když puppet spustíte, tak vygeneruje požadovanou konfiguraci a porovná ji se skutečnou. Například u příkladu výše při prvním spuštění zjistí, že nginx není nainstalovaný, tak ho nainstaluje. Při druhém spuštění už je ale vše v pořádku, takže neprovede nic.

V našem případě proběhnutí takové kontroly trvá 1-2 sekundy a máme nastavený cron na opakování každých 10 minut.

Instalace nového serveru

Pokud máte veškerou konfiguraci v puppetu, tak je nainstalování nového serveru otázkou chvilky. Jen nainstalujete puppet, stáhnete konfiguraci a spustíte. Chvilku to poběží a tradááá, server je nainstalovaný.

Zásadní výhodou oproti kopírování konfiguráků z běžícího serveru je, že zcela přesně víte, co na serveru máte. Pokud by vám třeba někdo vložil na server něco, co tam nepatří, tak si to budete kopírovat pořád do kola. S puppetem ale můžete začít s minimální instalací a nainstalovat skutečně jen to, co je nezbytně nutné.

Použití v cloudu

Původně jsme na tento postup přešli, protože dalo neúměrně moc práce zprovoznit nový server. Po přechodu do cloudu jsem za to byl opravdu vděčný, protože tam si to bez puppetu nedovedu představit. V cloudu totiž máte spoustu malých serverů, kde každý dělá něco jiného. Díky puppetu to ale jen definujete, určíte skupiny serverů a každý bude nakonfigurovaný dle konkrétního účelu.

Zásadní výhodou pak je vytváření image. Máme nastavený cron, který provede následující:

  1. nastartuje instanci s čistou instalací linuxu
  2. spustí puppet a provede instalaci dle konfigurace
  3. provede warm-up cache eshopů (například se zkompilují šablony atd)
  4. vytvoří image
  5. zahodí instanci
Tento cron proběhne třeba jednou denně a instance, které se spouští přes autoscaling pak používají takto vytvořenou image. Díky tomu mají vždy čistou instalaci - při spuštění instance se už nic neinstaluje a rovnou běží. Navíc mají připravenou cache, takže první minuty běhu se netráví jejím generováním.

Update: Nestačí vám články? Nově nabízím i konzultace AWS cloudu :)



O blogu
Blog o provozování eshopů a technologickém zázemí.
Aktuálně řeším hlavně cloud, bezpečnost a optimalizaci rychlosti.

Rozjíždím službu pro propojení eshopů s dodavateli.