Efektivní práce s Image

Jak vypadají vaše image (nebo chcete-li šablony) ve vaší klasické virtualizaci? Jedna z nejčastějších otázek v diskusích kolem OpenStack s KVM jako hypervisorem je, jak mám konvertovat svoje VMware obrazy. Odpovědi na to sice existují, ale že je užitečnější zamyslet se nad celou koncepcí. Nasazení IaaS jako je OpenStack a potenciální snížení závislosti na jediném hypervisoru (docela dobré a typické nasazení je v produkci KVM a vSphere a v dev/test KVM a VirtualBox s Vagrantem) je dobrou příležitostí přemýšlet o vaší strategii kolem tvorby a používání diskových obrazů.

Přemýšlení o obrazech vašich VM začneme v tomto labu, ale pokročilé postupy rozeberem až v jeho druhé části. Dnes se zaměříme na to, jak to udělat, aby v šabloně nebyla uložena hesla. Tedy aby přístupové údaje nebyly vlastnost samotné image, ale dosadili se až v okamžiku vytvoření instance. Dále si vyzkoušíme jednoduché spouštění iniciačního skriptu – jednoduché dokonfigurování VM po vytvoření instance.

Jak můžeme přistupovat k tvorbě a používání diskových obrazů či chcete-li šablon?

  • Image vznikají tak, že něco ve VM ručně kutáme a výsledek uložíme jako nový obraz

    • Výhoda: Nemusíme se nic učit, takhle se to dělalo i v prehistorii

    • Nevýhoda: Každý image je unikát, vše trvá dlouho, vzniká velké množství chyb, opakovatelnost je velmi problematická, dokumentace prakticky neexistuje nebo je špatně, závislost (více či méně) na hypervisor platformě (a s tím spojená špatná přenositelnost a problém nekonzistencí mezi vývojem, QA a produkcí)

  • Máme základní diskový obraz a konfigurační nástroje, které ho dostanou do stavu požadovaného aplikací

    • Výhoda: Vše je automatizované a dopadne vždy stejně, výborná a živá dokumentace, nezávislost na hypervisor platformě a přenositelnost

    • Nevýhoda: Příprava služby (aplikace) trvá dlouho, troubleshooting vyžaduje znalosti

  • Používáme immutable servery, tedy image je read only a pro každou verzi aplikace vždy vzniká nový fixní obraz

    • Výhoda: Rychlý start, vysoká bezpečnost (lze třeba i vypnout SSH přístup apod.), pro provoz jednoduché nasazení, při použití vhodných nástrojů lze jedním postupem vygenerovat funkčně identické obrazy pro různé hypervisory a platformy (přenositelnost)

    • Nevýhoda: Nutnost změnit development strategii a naučit se používat nové nástroje předávání údajů aplikacím místo tradičních konfiguračních souborů

Tato témata jsou pokročilejší a v dnešním labu se jich dotkneme jen okrajové. V druhé pokročilé části si ukážeme nástroje jako Server Automation, Ansible, Chef nebo Packer.

Šablony s key pair místo hesel

V automatizovaném prostředí samozřejmě můžete mít image virtuálních strojů se zabudovanými přihlašovacími hesly, ale není to ideální situace. Pokud jde o snapshot nějaké hotové aplikace, tak proč ne, ale jde-li o operační systém připravený pro další použití, znamenalo by to bezpečnostní riziko. Image upravený pro cloudové prostředí by měl být schopen se přizpůsobit situaci (v případě Linux to spočívá především v implementaci cloud-init balíčku při startu). Nechme stranou konkrétní mechanismus – místo hesla můžeme v Helion OpenStack vygenerovat SSH klíče (což je podstatně pohodlnější a bezpečnější) a ty použijeme místo hesel. Při startu instance zajistí OpenStack „vsunutí“ správného klíče do vašeho image, klíče, který patří konkrétnímu projektu, ne univerzální heslo.

Vygenerujeme si nové klíče (můžeme jich v projektu používat hned několik a také můžete naimportovat své existující). Jděte do záložky Compute - Access & Security.

V záložce Key Pairs klikněte na CREATE KEY PAIR

Zadejte název mujKlic a klikněte na vytvořit.

Klíč si stáhněte k sobě (to co získáváte je jeden klíč z páru, ten druhý se vsune do instance – vysvětlení detailů fungování PKI jsou nad rámec dnešního labu).

Otevřete soubor a zkopírujte jeho obsah do schránky.

Připojte se na labServer. Nejprve si tento privátní klíček uložíme do souboru. Napište příkaz cat přesměrovaný do souboru a vložte zkopírovaný obsah klíče (u většiny klientů ho vložíte pravým nebo prostředním tlačítkem). Nakonec zmáčněte CTRL+D.

    tomas@labserver:~$ cat > mujKlic.pem

    -----BEGIN RSA PRIVATE KEY-----

    MIIEqAIBAAKCAQEAr+1ZJ5HgKB02ZNRE4iQ6ZWgnS7G+4JCGJ+NzAr1UdmEDEoKL

    19PV0+DUmTuHrEOjVXnPAte1LCvuan+d7YOB0kJxRLv6hV5wbnhHgbhxn8etaG93

    …

    Bw73i871+cysew6zLaVNv2Z99yHq86wlF37yBFIBOiF+rk3gbW2ytzLF4hz36CVq

    uhHbCVH4iWIqKTOL7aPSUGRsNl/SR0/8XfshcS4rAF299leCtYMWz1qriH8=

    -----END RSA PRIVATE KEY-----

    tomas@labserver:~$

Aby bylo možné soubor používat, musíme nastavit správná práva.

    tomas@labserver:~$ chmod 600 mujKlic.pem

To máme připravené. Spustíme teď instanci Ubuntu. Jde o tzv. cloud image, tedy hotový Ubuntu obraz, který je připravený pro cloudové nasazení. To se pozná především tak, že obsahuje utilitku cloud-init, která se spouští hned po startu a dokáže komunikovat s OpenStack. Tímto způsobem se do VM po startu dostanou potřebná nastavení, v našem případě SSH klíč pro výchozího uživatele (tím je user „ubuntu“).

Vytvořte Security Group povolující SSH přístup zvenku.

Pokud jste v předchozích částech labu nastavili perimetrový firewall, zrušte ho - už nebudeme potřebovat. Jděte do Project, Network, Firewalls

A zrušte firewall

Jsme připraveni vytvořit si novou instanci Ubuntu 14.04. Spusťte průvodce spuštěním instance (už víte jak - Project, Compute, Instances a zmáčknout tlačítko).

Jako image zvolte Ubuntu 14.04

Vyberte si Flavor web.tiny (má větší disk, což pro tento image potřebujeme).

Alokujte síť, ale průvodce ještě neukončujte.

Přidejte Security Group povolující SSH přístup, ale průvodce ještě neukončujte.

A teď to nejdůležitější – přiřaďte váš bezpečnostní klíč a instanci spusťte.

Abychom mohli zkoušet přístup zvenku, přiřaďte k isntanci Floating IP.

Jděte do labServeru a pokuste se připojit bez vašeho klíčku.

    tomas@labserver:~$ ssh ubuntu@10.201.0.13

    Warning: Permanently added '10.201.0.13' (ECDSA) to the list of known hosts.

    Permission denied (publickey).

Neúspěch a ani nejste dotázáni na heslo (je to v cloud image ve výchozím stavu zakázané, navíc pro účet ubuntu žádné neexistuje). Zkuste to znovu s využitím vašeho klíčku.

    tomas@labserver:~$ ssh ubuntu@10.201.0.13 -i mujKlic.pem

    Warning: Permanently added '10.201.0.13' (ECDSA) to the list of known hosts.

    Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-86-generic x86_64)

    ...

    ubuntu@mojeubuntu:~$

Jsme tam! Šetřete zdroje v labu a tuto VM zase odstraňte.

Iniciační skripty

Pokud používáte image se zabudovaným cloud-init (tedy něco, co se obvykle označuje jako cloud-ready image), můžete při startu instance spustit vámi definovaný skript. Buď jednoduchý tak, jak to v rámci labu uděláme my (do 16KB kódu), nebo i komplexnější ve formě konfiguračního disku. To vám umožní váš image dokonfigurovat. Jedna z možností také je, že přímo v image je připravený váš vlastní autokonfigurační skript, který v rámci iniciace spustíte s nějakými parametry.

Založte novou instanci stejně, jako v předchozí kapitolce, ale dojděte až na záložku Configuration. Do okénka Customization Script napište následující skript. Ten vytvoří nového uživatele fantomas s heslem fantomas.

    #!/bin/bash

    echo "Nastavuji noveho uzivatele..."

    useradd fantomas

    echo "fantomas:fantomas" | chpasswd

    echo "Byl jsem tu ... fantomas"

Spusťte instanci a po té co naběhne se podívejte do logu. Klikněte na View Log

Zjistili jste přítomnost Fantomase?

Připojte se do konzole a přihlaste se tímto účtem.

Jsme tam! Samozřejmě ještě to není dokonalé - skript by měl vytvořit domovský adresář a modifikovat soubor /etc/passwd tak, aby po přihlášení automaticky spustil /bin/bash. To už ale na funkci Configuration Script v HPE Helion OpenStack nic nemění, tu jsme si ukázali.

Gratuluji – právě jste se naučili upravit výsledný OS přímo při vytváření instance. Tímto způsobem můžete například nastavit potřebné parametry pro to, aby se do OS dostala nějaká další služba či nástroj pro složitější kroky, jako je HPE Server Automation, Chef, Puppet apod. Můžete také třeba nastavit http proxy, nainstalovat nějaký balíček apod.

Používanou VM prosím zase smažte.

Dotahování VM aneb immutable image

Základem této strategie je úvaha, že je riskantní nacházet se v nějakém mezistavu. Možná to znáte z některých svých činností – někdy je rychlejší a jednodušší začít od začátku, než se pokoušet napravit něco, co se vám nebo někomu jinému zrovna nepovedlo. Někdy to třeba rychlejší a jednodušší není, ale je tu jedna jistota. Pokud vyjdete ze stejných startovních podmínek a budete opakovat identický postup, dojdete ke stejnému výsledku. Aby byla zajištěna přesnost v postupu, bude ho dělat robot (ve formě vhodného nástroje). Pokud tedy potřebujete obraz s nainstalovanými komponentami jako je web server, aplikační server, knihovny a tak podobně, začnete ze základního obrazu s operačním systémem a pak si stáhnete všechny potřebné aktualizace a komponenty dle předpisu. Mohl by to vlastně být nějaký skript, ale to je strašně špatně udržitelné a museli byste pokaždé vymýšlet všechno znova. Sáhněte tedy raději po vhodném nástroji, který to udělá přehledně, předvídatelně, spoustu věcí vyřeší za vás, existují k němu rozsáhlé knihovny hotových modulů a příkladů a ideálně dokonce podporuje metodu desired state (tedy definujete cílový stav a na pořadí operací nezáleží).

Co použít? Nejstarší CFEngine bych dnes už doporučoval nechat odpočívat, ale můžete vyzkoušet jednoho ze dvou soupeřících dospěláků – Puppet a Chef. První je napsaný v Ruby, zaměřuje se na desired state princip (tedy deklarativní přístup), na serverech používá agenta a je velmi oblíbený. Ten druhý je také v Ruby (a část v Erlang), má řadu zajímavých vychytávek, je spíše řešen imperativně (více se podobá programování) a kromě konfigurace serverů exceluje i v dalších zajímavostech (testování softwaru nebo compliance check). Možná vás ale zaujmou i mladí, kteří na to jdou bez agentů a pro většinu lidí jsou jednodušší na seznámení. Tím jsou Ansible a SaltStack, oba napsaní v Python, oba hojně využívající nádherně čitelné předpisy (YAML a Jinja šablony). Já osobně pro začátek doporučuji Ansible, ale pak není špatné zkusit třeba Chef, který je velmi rozšířený (ale všechno je otázkou osobního vkusu a potřeb – v této čtyřce neuděláte chybu). Pokud hledáte něco, co si poradí se vším včetně třeba UNIX systémů a má velmi bohatou knihovnu, nabízí GUI, compliance a je zavedené a prověřené v enterprise, zkuste komerční HPE Server Automation.

Co tedy potřebujete? Používáte pouze základní image – Okna 2012 R2, Ubuntu 14.04, CentOS 7 a to je třeba všechno. Pak máte ale připravené role (recepty, scénáře, …) pro jednotlivé typy serverů. Potřebujete novou verzi knihovny, jiné sestavení vaší aplikace nebo změnu nastavení? Rozhodně ji neprovedete ručně, ale zadáte ji do předpisu vámi vybraného nástroje. Většina z nich vám umožní stejnou sestavu spustit na vašem už běžícím serveru (na to existuje krásné slovo – nástroj je idempotentní), protože co už tam je se pouze ověří, že je v požadovaném stavu, a co tam chybí nebo nesedí se opraví. Stejně tak ale můžete vzít původní image a vybudovat všechno znovu (pokud jde o rychlý security patch, může být fajn to udělat na existujícím VM, ale ve většině případů bych volil cestu vybudovat si vše znova – ostatně takto stávající VM vůbec nemusíte vypínat a omezovat její dostupnost pro uživatele, až bude druhá nahoře funkční, můžete uživatele překlopit nějakým mechanismem – pro jednoduchost zatím řekněme DNS, ale na cloudsvet si povíme podstatně lepší metody).

Ansible pro automatizaci VM

Ansible je open source nástroj spadající do kategorie Configuration Management. Jeho velkou výhodou je, že je bezagentový - nepotřebuje tedy ve spravovaném zařízení instalovat žádného svého agenta, stačí SSH přístup a Python ve spravovaném zařízení, což je u Linux OS zcela běžné (Ansible podporuje i Windows, kde to funguje trošku jinak, ale velmi podobně). Tento nástroj můžete použít na řadu věcí. Tak například instalátor HPE Helion OpenStack je postaven právě na Ansible. V poslední době se hodně rozšířila i automatizace nastavení síťové infrastruktury přes Ansible. Tento nástoj ve finále dokáže i sahat do OpenStacku samotného a například automaticky vytvářet instance (o tom v jiné části lab guide). My se zaměříme na to, co bylo hlavním důvodem vzniku tohoto nástroje - „dotahování VM“, tedy konfigurace obsahu, balíčků a držení požadovaného stavu (desired state).

Připravte si dvě VM velikosti l1.small s názvem Ansible-web, s image Ubuntu 14.04, dejte jim Floating IP, povolte Security Group s přístupem na SSH a web (80) a nezapomeňte přiřadit váš SSH klíč.

(pozn.: nepoužívejte Ubuntu 16.04, protože tam už nativně není nainstalován Python2, ale Python3 a Ansible v době psaní tohoto návodu ještě plně Python3 nepodporuje. Museli byste tak nejprve do image dostat Python3 třeba konfigurační skriptem nebo vytvořením vašeho vlastního image. Příští verze Ansible už plánuje plnou podporu Python3).

Připojte se na labServer, skočte do adresáře ansible

    cd ansible

Použijte nějaký textový editor (nano, vi, ...) a připravte si soubor „hosts“. Jde v zásadě o seznam operačních systémů (IP adres nebo doménových jmen), které budeme chtít ovládat. V hranatých závorkách můžeme dělat skupiny – nám zatím bude stačit jen jedna.

    [mujlab]

    10.201.0.13

    10.201.0.14

Ansible komunikuje čistě přes protocol SSH – otestujme spojení. Potřebujete mít svůj SSH klíč (viz předchozí část labu – pokud budete mít potíže, zkuste nejprve ssh ubuntu@FloatingIP, musí procházet).

    tomas@labserver:~/ansible$ ansible mujlab -m ping -i hosts -u ubuntu --private-key=~/mujKlic.pem

    10.201.0.13 | SUCCESS => {

        "changed": false,

        "ping": "pong"

    }

    10.201.0.14 | SUCCESS => {

        "changed": false,

        "ping": "pong"

    }

Používání adhoc modulů, tak jak jsme si ukázali modul ping, není něco, co budete dělat často. Prakticky vždy budete pro Ansible připravovat komplexnější předpis zvaný Playbook. Nejprve si vyzkoušíme instalaci statického webového serveru. Playbook pro něco takového najdete už hotový na labServer, prohlédněme si ho.

    tomas@labserver:~/ansible$ cat web1.yml

    ---

    - hosts: mujlab

      become: yes

      remote_user: ubuntu

      environment:

        http_proxy: http://web-proxy.corp.hp.com:8088

      tasks:

        - name: Nainstaluj NGINX webovy server

          apt: pkg=nginx state=installed update_cache=true

          notify:

            - start nginx

        - name: Nakopiruj index.html na server

          copy: src=index.html dest=/usr/share/nginx/html/ mode=0644

      handlers:

        - name: start nginx

          service: name=nginx state=started

Co tedy říkáme? Specifikujeme skupinu serveru, pro které chceme nastavení provést (mujlab ve vašem hosts souboru). Dále říkáme, že chceme operaci provadět se zvýšenými právy (become). Na začátku playbooku také definujeme environmentální proměnné, v našem případě proxy server. Pak už jedeme jednotlivé úkoly. Tím prvním je nainstalovat balíček nginx a vzít index.html s labServer a nakopírovat do cílových VM skupiny mujlab. Po instalaci serveru navíc chceme zajistit, že jeho služba je nahoře.

Spusťte tento playbook a sledujte, jak Ansible postupuje (web server NGINX se stahuje z webu, tak to bude chvilku trvat, počkejte si).

    tomas@labserver:~/ansible$ ansible-playbook web1.yml -i hosts --private-key ~/mujKlic.pem

    PLAY [mujlab] ******************************************************************

    TASK [setup] *******************************************************************

    ok: [10.201.0.13]

    ok: [10.201.0.14]

    TASK [Nainstaluj NGINX webovy server] ******************************************

    changed: [10.201.0.13]

    changed: [10.201.0.14]

    TASK [Nakopiruj index.html na server] ******************************************

    changed: [10.201.0.13]

    changed: [10.201.0.14]

    RUNNING HANDLER [start nginx] **************************************************

    ok: [10.201.0.13]

    ok: [10.201.0.14]

    PLAY RECAP *********************************************************************

    10.201.0.13                : ok=4    changed=2    unreachable=0    failed=0

    10.201.0.14                : ok=4    changed=2    unreachable=0    failed=0

    tomas@labserver:~/ansible$

U tasků máte napsáno changed nebo ok, k tomu se za chvilku vrátíme.

Vyzkoušejte funkčnost webových serverů s využitím „textového prohlížeče“ curl.

    tomas@labserver:~/ansible$ curl 10.201.0.13

    Tohle je muj web

    tomas@labserver:~/ansible$ curl 10.201.0.14

    Tohle je muj web

Spusťme teď playbook ještě jednou a sledujme, co se bude dít.

    tomas@labserver:~/ansible$ ansible-playbook web1.yml -i hosts --private-key ~/mujKlic.pem

    PLAY [mujlab] ******************************************************************

    TASK [setup] *******************************************************************

    ok: [10.201.0.13]

    ok: [10.201.0.14]

    TASK [Nainstaluj NGINX webovy server] ******************************************

    ok: [10.201.0.14]

    ok: [10.201.0.13]

    TASK [Nakopiruj index.html na server] ******************************************

    ok: [10.201.0.14]

    ok: [10.201.0.13]

    PLAY RECAP *********************************************************************

    10.201.0.13                : ok=3    changed=0    unreachable=0    failed=0

    10.201.0.14                : ok=3    changed=0    unreachable=0    failed=0

Žádná havárie, vše funguje i nadále. Právě jste byli svědky vlastnosti, které se obvykle říká idempotence, tedy to, že můžete vše opakovat kolikrát chcete a vždy to dopadne stejně. V tomto běhu máte u všech tasků napsáno ok. V popisu jsem použil výraz „nainstaluj“, ale to je zavádějící – správně bych měl mít poznámku ve znění „Ujisti se, že NSGIX web server je nainstalován“. To je totiž přesně to, co Ansible udělá – uvede systém do požadovaného stavu. Je krok už splněn? Fajn, odškrtnuto (ok). Není? Udělejme to (changed).

Zkusme si to ještě jednou - na jednom z web serverů se odchylte od požadovaného stavu tím, že smažeme index.html.

    tomas@labserver:~/ansible$ ssh -i ~/mujKlic.pem ubuntu@10.201.0.13 "sudo rm /usr/share/nginx/html/index.html"

Jeden z web serverů je teď rozbitý.

    tomas@labserver:~/ansible$ curl 10.201.0.13

    <html>

    <head><title>403 Forbidden</title></head>

    <body bgcolor="white">

    <center><h1>403 Forbidden</h1></center>

    <hr><center>nginx/1.4.6 (Ubuntu)</center>

    </body>

    </html>

    tomas@labserver:~/ansible$ curl 10.201.0.14

    Tohle je muj web

Spusťme Playbook znovu a všimněme si, že odchylka u jednoho ze serverů byla napravena.

    tomas@labserver:~/ansible$ ansible-playbook web1.yml -i hosts --private-key ~/mujKlic.pem

    PLAY [mujlab] ******************************************************************

    TASK [setup] *******************************************************************

    ok: [10.201.0.14]

    ok: [10.201.0.13]

    TASK [Nainstaluj NGINX webovy server] ******************************************

    ok: [10.201.0.13]

    ok: [10.201.0.14]

    TASK [Nakopiruj index.html na server] ******************************************

    changed: [10.201.0.13]

    ok: [10.201.0.14]

    PLAY RECAP *********************************************************************

    10.201.0.13                : ok=3    changed=1    unreachable=0    failed=0

    10.201.0.14                : ok=3    changed=0    unreachable=0    failed=0

Zkusme si teď něco jiného. Naše image má login ubuntu a přihlášení je povolenou pouze SSH klíčem. V následujícím playbooku vytvoříme nové uživatelské účty a povolíme login heslem. Soubor user1.yml najdete na labServer, ale pojďme okomentovat, co se v něm děje.

    tomas@labserver:~/ansible$ cat users1.yml

    ---

    - hosts: mujlab

      become: yes

      remote_user: ubuntu

      environment:

        http_proxy: http://web-proxy.corp.hp.com:8088

      vars:

        users:

          - pavel

          - marek

          - tonda

          - lojza

      tasks:

        - name: Pridej uzivatele

          user:

            name: "{{ item }}"

            shell: /bin/bash

            createhome: yes

            password: $6$rounds=656000$BnsdFwwr8iTaJIIP$UfWt9SFUU5nxZP2xkF3cmGsYD92nnhfJ86x3uAT5FQxyGgkWRxv81wz4zubkhygT/Sdk2ltMxeKZ03h5K067G.

          with_items:

            "{{ users }}"

        - name: Povol prihlaseni heslem

          replace: dest=/etc/ssh/sshd_config regexp='PasswordAuthentication no' replace='PasswordAuthentication yes'

          notify:

            - restart_ssh

      handlers:

        - name: restart_ssh

          service: name=ssh state=restarted

Popišme jen to, co je jiné oproti předchozí situaci. Je tady nový objekt vars, tedy proměnné a v něm users, které obsahuje výčet uživatelů. Task Pridej uzivatele zakládá účet s jménem, které je obsaženo v objektu users (tedy operace se provádí pro každého uživatele). Specifikujeme jaký základní shell má uživatel mít, že chceme vytvořit i domovský adresář a také uvádíme heslo „helion“ (to musí být v hash formátu, existují online generátory na Internetu). V druhém kroku povolíme přihlášení heslem – na to je potřeba modifikovat soubor sshd_config na cílovém serveru. Provedeme operaci replace, kde najdeme jeden řetězec a nahradíme ho jiným. Na závěr SSH restartujeme, ale jen, pokud bylo nutné soubor měnit (tedy pokud už soubor nebyl modifikovaný z předchozího běhu).

    tomas@labserver:~/ansible$ ansible-playbook users1.yml -i hosts --private-key ~/mujKlic.pem

    PLAY [mujlab] ******************************************************************

    TASK [setup] *******************************************************************

    ok: [10.201.0.13]

    ok: [10.201.0.14]

    TASK [Pridej uzivatele] ********************************************************

    changed: [10.201.0.14] => (item=pavel)

    changed: [10.201.0.13] => (item=pavel)

    changed: [10.201.0.14] => (item=marek)

    changed: [10.201.0.13] => (item=marek)

    changed: [10.201.0.14] => (item=tonda)

    changed: [10.201.0.13] => (item=tonda)

    changed: [10.201.0.14] => (item=lojza)

    changed: [10.201.0.13] => (item=lojza)

    TASK [Povol prihlaseni heslem] *************************************************

    changed: [10.201.0.14]

    changed: [10.201.0.13]

    RUNNING HANDLER [restart_ssh] **************************************************

    changed: [10.201.0.14]

    changed: [10.201.0.13]

    PLAY RECAP *********************************************************************

    10.201.0.13                : ok=4    changed=3    unreachable=0    failed=0

    10.201.0.14                : ok=4    changed=3    unreachable=0    failed=0

Zkuste se přihlásit jako jeden z uživatelů na jeden z vašich serverů (připomínám, že heslo je helion).

    tomas@labserver:~/ansible$ ssh tonda@10.201.0.13

    Warning: Permanently added '10.201.0.13' (ECDSA) to the list of known hosts.

    tonda@10.201.0.13's password:

    Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-86-generic x86_64)

    ...

    tonda@ansible-web-1:~$

Jednou z typických operací v rámci instalace služeb do VM je modifikace konfiguračního souboru či jiná úprava nějaké výchozí šablony. Vyzkoušejme si teď obohatit náš playbook pro instalaci a konfiguraci web serveru o šablonu pro index.html. Jak samotný playbook (web2.yml) tak šablonu (index.html.j2) najdete na labServer.

Tato vypadá naše šablona:

    tomas@labserver:~/ansible$ cat index.html.j2

    {{ item.osloveni }} ctenari

    Dnesnim vyhercem je {{ item.vyherce }}

    Gratulujeme!

Políčka osloveni a vyherce budeme dosazovat až v playbooku:

    tomas@labserver:~/ansible$ cat web2.yml

    ---

    - hosts: mujlab

      become: yes

      remote_user: ubuntu

      environment:

        http_proxy: http://web-proxy.corp.hp.com:8088

      vars:

        webovky:

          - osloveni: Nazdarek

            vyherce: Standa Hlozek

      tasks:

        - name: Nainstaluj NGINX webovy server

          apt: pkg=nginx state=installed update_cache=true

          notify:

            - start nginx

        - name: Nakopiruj ze sablony a modifikuj index.html

          template: src=index.html.j2 dest=/usr/share/nginx/html/index.html mode=0644

          with_items:

            "{{ webovky }}"

      handlers:

        - name: start nginx

          service: name=nginx state=started

V části vars jsme si definovali objekt webovky a v něm proměnné osloveni a vyherce. Tyto dosadíme na příslušná místa šablony a umístíme ji do cílové VM. Spusťte playbook.

    tomas@labserver:~/ansible$ ansible-playbook web2.yml -i hosts --private-key ~/mujKlic.pem

    PLAY [mujlab] ******************************************************************

    TASK [setup] *******************************************************************

    ok: [10.201.0.14]

    ok: [10.201.0.13]

    TASK [Nainstaluj NGINX webovy server] ******************************************

    ok: [10.201.0.14]

    ok: [10.201.0.13]

    TASK [Nakopiruj ze sablony a modifikuj index.html] *****************************

    changed: [10.201.0.13] => (item={u'vyherce': u'Standa Hlozek', u'osloveni': u'Nazdarek'})

    changed: [10.201.0.14] => (item={u'vyherce': u'Standa Hlozek', u'osloveni': u'Nazdarek'})

    PLAY RECAP *********************************************************************

    10.201.0.13                : ok=3    changed=1    unreachable=0    failed=0

    10.201.0.14                : ok=3    changed=1    unreachable=0    failed=0

Vyzkoušejte výsledek.

    tomas@labserver:~/ansible$ curl 10.201.0.13

    Nazdarek ctenari

    Dnesnim vyhercem je Standa Hlozek

    Gratulujeme!

Blížíme se do finiše.

Některé konfigurační úkony se mohou často opakovat a Ansible nabízí institut role. Jde o kompletní seznam úloh řešící nějakou konkrétní oblast. Takovou rolí třeba bude SQL server, webový server, aplikační server apod. Takové role si můžete vytvořit sami, ale také je možné si je stáhnout z veřejného repozitáře (Ansible Galaxy). Vyzkoušejme si to.

Přidejte novou VM s Ubuntu 14.04 a přiřaďte ji Floating IP.

Vytvořte si podadresář pro role a stáhněte si roli ANXS.mysql

    tomas@labserver:~/ansible$ mkdir roles

    tomas@labserver:~/ansible$ source ~/proxy

    tomas@labserver:~/ansible$ ansible-galaxy install ANXS.mysql -p roles/

    - downloading role 'mysql', owned by ANXS

    - downloading role from https://github.com/ANXS/mysql/archive/v1.1.0.tar.gz

    - extracting ANXS.mysql to roles/ANXS.mysql

    - ANXS.mysql was installed successfully

Upravte vás hosts soubor a přidejte do něj novou skupinu mysql s příslušnou adresou.

    [mujlab]

    10.201.0.13

    10.201.0.14

    [mysql]

    10.201.0.15

Role mysql se postará nejen o instalaci MySQL databázového serveru, ale může vám například vytvořit databázi či uživatele (víc najdete v dokumentaci role na Ansible Galaxy). Playbook mysql.yml najdete take na labServer a je jednoduchý:

    tomas@labserver:~/ansible$ cat mysql.yml

    - hosts: mysql

      vars:

        mysql_users:

          - name: mujuser

            pass: mojeheslo

      become: yes

      environment:

        http_proxy: http://web-proxy.corp.hp.com:8088

        https_proxy: http://web-proxy.corp.hp.com:8088

      remote_user: ubuntu

      roles:

        - { role: ANXS.mysql }

Spusťte playbook (použitý Playbook používá zastaralý formát definice proměnné, takže dostanete jistá varování. V Ansible 2.1, který je v labu, ovšem stále funguje, ale do budoucna si najděte novější Playbook na Galaxy).

    tomas@labserver:~/ansible$ ansible-playbook mysql.yml -i hosts --private-key ~/mujKlic.pem

     [WARNING]: While constructing a mapping from

    /home/tomas/ansible/roles/ANXS.mysql/defaults/main.yml, line 4, column 1, found a duplicate dict key

    (mysql_innodb_file_per_table).  Using last defined value only.

    PLAY [mysql] *******************************************************************

    TASK [setup] *******************************************************************

    ok: [10.201.0.15]

    TASK [ANXS.mysql : include] ****************************************************

    included: /home/tomas/ansible/roles/ANXS.mysql/tasks/install.yml for 10.201.0.15

    TASK [ANXS.mysql : MySQL | Add APT repository] *********************************

    skipping: [10.201.0.15]

    TASK [ANXS.mysql : MySQL | Make sure the MySQL packages are installed] *********

    [DEPRECATION WARNING]: Using bare variables is deprecated. Update your playbooks so that the

    environment value uses the full variable syntax ('{{mysql_packages}}').

    This feature will be removed

     in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in

    ansible.cfg.

    changed: [10.201.0.15] => (item=[u'mysql-server', u'mysql-client', u'python-mysqldb'])

    TASK [ANXS.mysql : MySQL | Ensure MySQL is running] ****************************

    ok: [10.201.0.15]

    TASK [ANXS.mysql : include] ****************************************************

    included: /home/tomas/ansible/roles/ANXS.mysql/tasks/configure.yml for 10.201.0.15

    TASK [ANXS.mysql : MySQL | Update the my.cnf] **********************************

    changed: [10.201.0.15]

    TASK [ANXS.mysql : include] ****************************************************

    included: /home/tomas/ansible/roles/ANXS.mysql/tasks/secure.yml for 10.201.0.15

    TASK [ANXS.mysql : MySQL | Test whether the root password has already been changed (external hostname).] ***

    failed: [10.201.0.15] (item=ansible-mysql) => {"failed": true, "item": "ansible-mysql", "msg": "unable to connect to database, check login_user and login_password are correct or /root/.my.cnf has the credentials. Exception message: (1045, \"Access denied for user 'root'@'localhost' (using password: YES)\")"}

    failed: [10.201.0.15] (item=127.0.0.1) => {"failed": true, "item": "127.0.0.1", "msg": "unable to connect to database, check login_user and login_password are correct or /root/.my.cnf has the credentials. Exception message: (1045, \"Access denied for user 'root'@'localhost' (using password: YES)\")"}

    failed: [10.201.0.15] (item=::1) => {"failed": true, "item": "::1", "msg": "unable to connect to database, check login_user and login_password are correct or /root/.my.cnf has the credentials. Exception message: (1045, \"Access denied for user 'root'@'localhost' (using password: YES)\")"}

    failed: [10.201.0.15] (item=localhost) => {"failed": true, "item": "localhost", "msg": "unable to connect to database, check login_user and login_password are correct or /root/.my.cnf has the credentials. Exception message: (1045, \"Access denied for user 'root'@'localhost' (using password: YES)\")"}

    ...ignoring

    TASK [ANXS.mysql : MySQL | Changing the root password (external hostname).] ****

    changed: [10.201.0.15] => (item=ansible-mysql)

    changed: [10.201.0.15] => (item=127.0.0.1)

    changed: [10.201.0.15] => (item=::1)

    changed: [10.201.0.15] => (item=localhost)

    TASK [ANXS.mysql : MySQL | Test whether the root password has already been changed (local hostname).] ***

    skipping: [10.201.0.15] => (item=127.0.0.1)

    skipping: [10.201.0.15] => (item=::1)

    skipping: [10.201.0.15] => (item=localhost)

    TASK [ANXS.mysql : MySQL | Changing the root password (local hostname).] *******

    skipping: [10.201.0.15] => (item=127.0.0.1)

    skipping: [10.201.0.15] => (item=::1)

    skipping: [10.201.0.15] => (item=localhost)

    TASK [ANXS.mysql : MySQL | Configure MySql for easy access as root user] *******

    changed: [10.201.0.15]

    TASK [ANXS.mysql : MySQL | Remove anonymous MySQL server user] *****************

    ok: [10.201.0.15] => (item=ansible-mysql)

    ok: [10.201.0.15] => (item=localhost)

    TASK [ANXS.mysql : MySQL | Remove the MySQL test database] *********************

    ok: [10.201.0.15]

    TASK [ANXS.mysql : include] ****************************************************

    included: /home/tomas/ansible/roles/ANXS.mysql/tasks/databases.yml for 10.201.0.15

    TASK [ANXS.mysql : MySQL | Make sure the MySQL databases are present] **********

    [DEPRECATION WARNING]: Using bare variables is deprecated. Update your playbooks so that the

    environment value uses the full variable syntax ('{{mysql_databases}}').

    This feature will be

    removed in a future release. Deprecation warnings can be disabled by setting

    deprecation_warnings=False in ansible.cfg.

    TASK [ANXS.mysql : include] ****************************************************

    included: /home/tomas/ansible/roles/ANXS.mysql/tasks/users.yml for 10.201.0.15

    TASK [ANXS.mysql : MySQL | Make sure the MySQL users are present] **************

    [DEPRECATION WARNING]: Using bare variables is deprecated. Update your playbooks so that the

    environment value uses the full variable syntax ('{{mysql_users}}').

    This feature will be removed in

     a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in

    ansible.cfg.

    changed: [10.201.0.15] => (item={u'name': u'mujuser', u'pass': u'mojeheslo'})

    TASK [ANXS.mysql : include] ****************************************************

    skipping: [10.201.0.15]

    RUNNING HANDLER [ANXS.mysql : restart mysql] ***********************************

    changed: [10.201.0.15]

    PLAY RECAP *********************************************************************

    10.201.0.15                : ok=16   changed=6    unreachable=0    failed=0

Připojte se do cílové VM a pokuste se nalogovat do MySQL vytvořeným účtem.

    tomas@labserver:~/ansible$ ssh ubuntu@10.201.0.15 -i ~/mujKlic.pem

    Warning: Permanently added '10.201.0.15' (ECDSA) to the list of known hosts.

    Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-86-generic x86_64)

    ..

    Last login: Wed Jun  8 09:33:16 2016 from 10.201.0.5

    ubuntu@ansible-mysql:~$ mysql -umujuser -pmojeheslo

    Welcome to the MySQL monitor.  Commands end with ; or \g.

    Your MySQL connection id is 36

    Server version: 5.5.49-0ubuntu0.14.04.1 (Ubuntu)

    ...

    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

    mysql> exit

    Bye

    ubuntu@ansible-mysql:~$ exit

    logout

    Connection to 10.201.0.15 closed.

    tomas@labserver:~/ansible$

Tímto úvod do Ansible ukončíme. Jde o nejjednodušší vstup do světa automatizace konfigurací vašich VM a ze systému rolí se dá poskládat i velmi komplexní system. Například Helion OpenStack Lifecycle Manager (instalátor a udržovač Helion OpenStack) je postaven právě na Ansible a zahruje stovky/tisíce kroků a desítky rolí.

Stojí za zmínku, že nepotřebujete, aby všechny VM měly Floating IP. Jednou z možností je nepoužívat Ansible mimo váš tenant/projekt, ale provozovat jej uvnitř. Vytvoříte si tam VM s Ansiblem a odtamtud budete všechno řešit uvnitř. Druhá možnost je použít SSH proxy. V zásadě vytvoříte VM s FloatingIP, která bude pro Ansible zajišťovat konektivitu do dalších VM uvnitř projektu.

Chef pro automatizaci VM

Chef je velmi mocný nástroj pro konfiguraci a automatizace OS a aplikací. Ve srovnání s Ansible je o poznání komplikovanější na používání, ale za to velmi robustní, bezpečný a výkonný. V labu si vyzkoušímenasazení v režimu Chef-server (zdroj pravdy, místo kde jsou uloženy předpisy pro cílové stanice, je tam orgaizační členění i účty uživatelů, GUI i API), Chef-workstation (pracovní stanice administrátora) a Chef-client (agent uvnitř cílové VM, který si stahuje z Chef-serveru předpisy, které vynucuje). Na hraní můžete použít také Chef-solo (ten, stejně jako Ansible s volbou local, dokáže nastavit přímo VM, ve které běží bez potřeby dalších komponent).

Primární model fungování Chefu je pull, tedy Chef-client si vyžádá informace z Chef-serveru a lokálně je vynutí (tento proces je spuštěn se startem chef-client, což lze řešit i jako démona a nastavit pravidelné spuštění třeba každých 10 minut). To má pozitivní vliv na výkon i přehlednost. Přesto, podobně jako to řeší Ansible, podporuje i push metodu (knife ssh) a samotného chef-client můžete také instalovat push metodou (knife bootstrap).

labServer je připraven jako chef-server a současně chef-workstation.

Připojte se na labServer a vygenerujte nový repozitář.

    tomas@labserver:~$ chef generate repo chef-repo

    [2016-06-08T10:04:50+00:00] WARN: ExpandNodeObject#load_node is deprecated. Please use Chef::PolicyBuilder::Dynamic instead of using ExpandNodeObject directly at /opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-dk-0.9.0/lib/chef-dk/chef_runner.rb:54:in `policy'

    Compiling Cookbooks...

    ...

    Recipe: code_generator::repo

      * cookbook_file[/home/tomas/chef-repo/cookbooks/README.md] action create

        - create new file /home/tomas/chef-repo/cookbooks/README.md

        - update content in file /home/tomas/chef-repo/cookbooks/README.md from none to 86e9ef

        (diff output suppressed by config)

      * execute[initialize-git] action run

        - execute git init .

      * template[/home/tomas/chef-repo/.gitignore] action create

        - create new file /home/tomas/chef-repo/.gitignore

        - update content in file /home/tomas/chef-repo/.gitignore from none to 3523c4

        (diff output suppressed by config)

Workstation musí být shopna bezpečným způsobem (šifrování a ověřování certifikáty) komunikovat s chef-server (i v našem případě, kdy je oboce na stejném systému).

Skočte do repozitáře, stáhněte si SSL certifikáty a ověřte jejich pravost.

    tomas@labserver:~/$ cd chef-repo/

    tomas@labserver:~/chef-repo$ knife ssl fetch

    WARNING: Certificates from labserver will be fetched and placed in your trusted_cert

    directory (/home/tomas/chef-repo/.chef/trusted_certs).

    Knife has no means to verify these are the correct certificates. You should

    verify the authenticity of these certificates after downloading.

    Adding certificate for labserver.helion.demo in /home/tomas/chef-repo/.chef/trusted_certs/labserver_helion_demo.crt

Vaše workstation vám může pomoci s instalací chef klientů - vypište si aktuální seznam.

    tomas@labserver:~/chef-repo$ unset http_proxy

    tomas@labserver:~/chef-repo$ unset https_proxy

    tomas@labserver:~/chef-repo$ knife client list

    helion-validator

Pojďme vytvořit prázdnou Ubuntu VM (l1.small, Security Group povolující SSH a web), s kterou si budeme hrát. Chef vyžaduje přítomnost plných doménových jmen (FQDN), takže v praxi je žádoucí mít enterprise DNS server. Ten v labu nemáme, takže potřebujeme ručně do VM přidat záznam do hosts souboru s překladem labserver.helion.demo na jeho IP adresu. To udělejte zadáním následujícího skriptu (současně s nastavení proxy pro apt). Pokud se vám nechce opisovat, najdete ho na labServeru v adresáři chef-repo pod názvem nodnschef.sh.

    #!/bin/bash

    printf '10.201.0.5 labserver.helion.demo\n' | sudo tee -a /etc/hosts

Tohle je naše výsledná VM.

Na VM teď není nic. V případě Ansible by to nevadilo (tomu stačí SSH přístup), ale Chef potřebuje agenta (chef-client). Pokud jsme jeho instalaci nezařídili nějak jinak (může být už součástí image, dá se nainstalovat iniciačním skriptem nebo přes OpenStack Heat), lze použít push metodu instalace. Ta se provádí z workstation (nikoli ze chef serveru - v našem labu je to totéž, ale myslete na to v praxi z pohledu síťové konektivity). Použijte příkaz knife bootstrap, namiřte na Floating IP vaší VM, zadejte přístupové údaje (-x jako login, -i odkaz na SSH klíč), pojmenujte tento node (-N, takhle bude vidět v chef-server), povolte sudo (--sudo) a nastavte http_proxy (chef klient se bude stahovat z Internetu).

    tomas@labserver:~/chef-repo$ knife bootstrap 10.201.0.13 -i ~/mujKlic.pem -N prvniPokus -x ubuntu --sudo --bootstrap-proxy http://web-proxy.corp.hp.com:8088 --bootstrap-no-proxy labserver.helion.demo

    Doing old-style registration with the validation key at ~/chef-repo/.chef/chefhelion.pem...

    Delete your validation key in order to use your user credentials instead

    Connecting to 10.201.0.13

    10.201.0.13 sudo: unable to resolve host chef-vm

    10.201.0.13 -----> Installing Chef Omnibus (-v 12)

    10.201.0.13 downloading https://www.opscode.com/chef/install.sh

    10.201.0.13   to file /tmp/install.sh.1376/install.sh

    10.201.0.13 trying wget...

    10.201.0.13 ubuntu 14.04 x86_64

    10.201.0.13 Getting information for chef stable 12 for ubuntu...

    10.201.0.13 downloading https://omnitruck-direct.chef.io/stable/chef/metadata?v=12&p=ubuntu&pv=14.04&m=x86_64

    10.201.0.13   to file /tmp/install.sh.1380/metadata.txt

    10.201.0.13 trying wget...

    10.201.0.13 sha1        7d30b300f95f00036919ee8bf3b95ab73429e57e

    10.201.0.13 sha256      663d6c42c90bbb9463bc02a7c5d777f7aa6ebd52c071a0c1963bc8c4db76dea2

    10.201.0.13 url https://packages.chef.io/stable/ubuntu/14.04/chef_12.10.24-1_amd64.deb

    10.201.0.13 version     12.10.24

    10.201.0.13 downloaded metadata file looks valid...

    10.201.0.13 downloading https://packages.chef.io/stable/ubuntu/14.04/chef_12.10.24-1_amd64.deb

    10.201.0.13   to file /tmp/install.sh.1380/chef_12.10.24-1_amd64.deb

    10.201.0.13 trying wget...

    10.201.0.13 Comparing checksum with sha256sum...

    10.201.0.13 Installing chef 12

    10.201.0.13 installing with dpkg...

    10.201.0.13 Selecting previously unselected package chef.

    (Reading database ... 51169 files and directories currently installed.)

    10.201.0.13 Preparing to unpack .../chef_12.10.24-1_amd64.deb ...

    10.201.0.13 Unpacking chef (12.10.24-1) ...

    10.201.0.13 Setting up chef (12.10.24-1) ...

    10.201.0.13 Thank you for installing Chef!

    10.201.0.13 Starting the first Chef Client run...

    10.201.0.13 Starting Chef Client, version 12.10.24

    10.201.0.13 Creating a new client identity for prvniPokus using the validator key.

    10.201.0.13 resolving cookbooks for run list: []

    10.201.0.13 Synchronizing Cookbooks:

    10.201.0.13 Installing Cookbook Gems:

    10.201.0.13 Compiling Cookbooks...

    10.201.0.13 [2016-06-08T10:25:34+00:00] WARN: Node prvniPokus has an empty run list.

    10.201.0.13 Converging 0 resources

    10.201.0.13

    10.201.0.13 Running handlers:

    10.201.0.13 Running handlers complete

    10.201.0.13 Chef Client finished, 0/0 resources updated in 05 seconds

Zdá se, že se chef-client stáhnul, nainstaloval i připojil. Vidíte ho v knife client?

    tomas@labserver:~/chef-repo$ knife client list

    helion-validator

    prvniPokus

Chef přichází s řadou hotových veřejně dostupných kuchařek, stáhneme si jednu, která se nám bude hodit (provede apt-get update, což potřebujeme pro pozdější instalace balíčků, a zařídí jeho pravidelné opakování, takže se server sám patchuje - někdy to může být riskantní, ale pro některé situace se to hodí).

    tomas@labserver:~/chef-repo$ cd cookbooks/

    tomas@labserver:~/chef-repo/cookbooks$ source ~/proxy

    tomas@labserver:~/chef-repo/cookbooks$ knife cookbook site download apt

    Downloading apt from Supermarket at version 4.0.0 to /home/tomas/chef-repo/cookbooks/apt-4.0.0.tar.gz

    Cookbook saved: /home/tomas/chef-repo/cookbooks/apt-4.0.0.tar.gz

    tomas@labserver:~/chef-repo/cookbooks$ tar zxf apt-4.0.0.tar.gz

Ještě stáhněte zdroj compat_resource, který také potřebujeme.

    tomas@labserver:~/chef-repo/cookbooks$ knife cookbook site download compat_resource

    Downloading compat_resource from Supermarket at version 12.10.6 to /home/tomas/chef-repo/cookbooks/compat_resource-12.10.6.tar.gz

    Cookbook saved: /home/tomas/chef-repo/cookbooks/compat_resource-12.10.6.tar.gz



    tomas@labserver:~/chef-repo/cookbooks$ tar zxf compat_resource-12.10.6.tar.gz

Vytvoříme teď také naší novou kuchařku a necháme si vygenerovat výchozí adresářovou strukturu.

    tomas@labserver:~/chef-repo/cookbooks$ chef generate cookbook mujWebServer

    [2016-06-08T10:29:09+00:00] WARN: ExpandNodeObject#load_node is deprecated. Please use Chef::PolicyBuilder::Dynamic instead of using ExpandNodeObject directly at /opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-dk-0.9.0/lib/chef-dk/chef_runner.rb:54:in `policy'

    Compiling Cookbooks...

    Recipe: code_generator::cookbook

      * directory[/home/tomas/chef-repo/cookbooks/mujWebServer] action create

        - create new directory /home/tomas/chef-repo/cookbooks/mujWebServer

      * template[/home/tomas/chef-repo/cookbooks/mujWebServer/metadata.rb] action create_if_missing

        - create new file /home/tomas/chef-repo/cookbooks/mujWebServer/metadata.rb

        - update content in file /home/tomas/chef-repo/cookbooks/mujWebServer/metadata.rb from none to 6252be

        (diff output suppressed by config)

      ...

      * template[/home/tomas/chef-repo/cookbooks/mujWebServer/recipes/default.rb] action create_if_missing

        - create new file /home/tomas/chef-repo/cookbooks/mujWebServer/recipes/default.rb

        - update content in file /home/tomas/chef-repo/cookbooks/mujWebServer/recipes/default.rb from none to 21a293

        (diff output suppressed by config)

      * cookbook_file[/home/tomas/chef-repo/cookbooks/mujWebServer/.gitignore] action create

        - create new file /home/tomas/chef-repo/cookbooks/mujWebServer/.gitignore

        - update content in file /home/tomas/chef-repo/cookbooks/mujWebServer/.gitignore from none to dd37b2

        (diff output suppressed by config)

Skočte do adresáře kuchařky a podívejte se na její strukturu.

    tomas@labserver:~/chef-repo/cookbooks$ cd mujWebServer/

    tomas@labserver:~/chef-repo/cookbooks/mujWebServer$ tree

    .

    ├── chefignore

    ├── metadata.rb

    ├── Policyfile.rb

    ├── README.md

    ├── recipes

    │   └── default.rb

    ├── spec

    │   ├── spec_helper.rb

    │   └── unit

    │       └── recipes

    │           └── default_spec.rb

    └── test

        └── integration

            ├── default

            │   └── serverspec

            │       └── default_spec.rb

            └── helpers

                └── serverspec

                    └── spec_helper.rb

    10 directories, 9 files

Nás teď bude recept, tedy konkrétní sada kroků. Výchozí (prázdný) byl vytvořen a ten my teď změníme.

tomas@labserver:~/chef-repo/cookbooks/mujWebServer$ nano recipes/default.rb

Takhle bude vypadat

    #

    # Cookbook Name:: mujWebServer

    # Recipe:: default

    #

    # Copyright (c) 2015 The Authors, All Rights Reserved.

    package 'apache2'

    service 'apache2' do

      supports :status => true

      action [:enable, :start]

    end

    file '/var/www/html/index.html' do

      content 'Tohle je muj web!

    '

    end

Teď musíme uploadnout (v našem případě je to stejný server, ale i tak) obě kuchařky z chef workstation na chef server.

    tomas@labserver:~/chef-repo/cookbooks/mujWebServer$ unset http_proxy

    tomas@labserver:~/chef-repo/cookbooks/mujWebServer$ unset https_proxy

    tomas@labserver:~/chef-repo/cookbooks/mujWebServer$ knife cookbook upload mujWebServer

    Uploading mujWebServer [0.1.0]

    Uploaded 1 cookbook.

    tomas@labserver:~/chef-repo/cookbooks$ knife cookbook upload compat_resource

    Uploading compat_resource [12.10.6]

    Uploaded 1 cookbook.

    tomas@labserver:~/chef-repo/cookbooks$ knife cookbook upload apt

    Uploading apt            [4.0.0]

    Uploaded 1 cookbook.

Otevřte si v jiném okně další SSH sessin na labServer a z ní se zkuste napojit do cílové VM.

    tomas@labserver:~$ ssh ubuntu@10.201.0.13 -i ~/mujKlic.pem

Spusťte chef-client a sledujte co se děje.

    ubuntu@chef-vm:~$ sudo chef-client

    sudo: unable to resolve host chef-vm

    Starting Chef Client, version 12.10.24

    resolving cookbooks for run list: []

    Synchronizing Cookbooks:

    Installing Cookbook Gems:

    Compiling Cookbooks...

    [2016-06-08T11:03:11+00:00] WARN: Node prvniPokus has an empty run list.

    Converging 0 resources

    Running handlers:

    Running handlers complete

    Chef Client finished, 0/0 resources updated in 01 seconds

Klient v pořádku vidí Chef server, ale nemá co dělat - nodu prvniPokus nebyla přiřazená žádná kuchařka. To můžeme udělat v jednom kroku přímo v příkazu knife bootstrap použitím volby --run-list apt,mujWebServer. My jsme to ale schválně neudělali a přidáme si kuchařku až teď. Následující příkazy zadejte na labServer.

    tomas@labserver:~/chef-repo$ knife node run_list add prvniPokus apt

    prvniPokus:

      run_list: recipe[apt]

    tomas@labserver:~/chef-repo$ knife node run_list add prvniPokus mujWebServer

    prvniPokus:

      run_list:

        recipe[apt]

        recipe[mujWebServer]

Spusťte v cílové VM chef-client znova.

    ubuntu@chef-vm:~$ sudo chef-client

    sudo: unable to resolve host chef-vm

    Starting Chef Client, version 12.10.24

    resolving cookbooks for run list: ["apt", "mujWebServer"]

    Synchronizing Cookbooks:

      - apt (4.0.0)

      - compat_resource (12.10.6)

      - mujWebServer (0.1.0)

    Installing Cookbook Gems:

    Compiling Cookbooks...

    [2016-06-08T13:58:36+00:00] WARN: Chef::Provider::AptRepository already exists!  Cannot create deprecation class for LWRP provider apt_repository from cookbook apt

    [2016-06-08T13:58:36+00:00] WARN: AptRepository already exists!  Deprecation class overwrites Custom resource apt_repository from cookbook apt

    Converging 12 resources

    Recipe: apt::default

      * file[/var/lib/apt/periodic/update-success-stamp] action nothing (skipped due to action :nothing)

      * apt_update[periodic] action periodic

        - update new lists of packages

        * directory[/var/lib/apt/periodic] action create (up to date)

        * directory[/etc/apt/apt.conf.d] action create (up to date)

        * file[/etc/apt/apt.conf.d/15update-stamp] action create_if_missing (up to date)

        * execute[apt-get -q update] action run

          - execute apt-get -q update

      * execute[apt-get update] action nothing (skipped due to action :nothing)

      * execute[apt-get autoremove] action nothing (skipped due to action :nothing)

      * execute[apt-get autoclean] action nothing (skipped due to action :nothing)

      * directory[/var/cache/local] action create

        - create new directory /var/cache/local

        - change mode from '' to '0755'

        - change owner from '' to 'root'

        - change group from '' to 'root'

      * directory[/var/cache/local/preseeding] action create

        - create new directory /var/cache/local/preseeding

        - change mode from '' to '0755'

        - change owner from '' to 'root'

        - change group from '' to 'root'

      * template[/etc/apt/apt.conf.d/10recommends] action create

        - create new file /etc/apt/apt.conf.d/10recommends

        - update content in file /etc/apt/apt.conf.d/10recommends from none to f41e1d

        --- /etc/apt/apt.conf.d/10recommends        2016-06-08 13:59:04.760616000 +0000

        +++ /etc/apt/apt.conf.d/.chef-10recommends20160608-2081-1t4xtqc     2016-06-08 13:59:04.760616000 +0000

        @@ -1 +1,4 @@

        +# Managed by Chef

        +APT::Install-Recommends "1";

        +APT::Install-Suggests "0";

        - change mode from '' to '0644'

        - change owner from '' to 'root'

        - change group from '' to 'root'

      * apt_package[apt-transport-https] action install (up to date)

    Recipe: mujWebServer::default

      * apt_package[apache2] action install

        - install version 2.4.7-1ubuntu4.9 of package apache2

      * service[apache2] action enable (up to date)

      * service[apache2] action start (up to date)

      * file[/var/www/html/index.html] action create

        - update content in file /var/www/html/index.html from 538f31 to 15cc2e

        --- /var/www/html/index.html        2016-06-08 14:00:33.808616000 +0000

        +++ /var/www/html/.chef-index.html20160608-2081-9o8mp2      2016-06-08 14:00:46.912616000 +0000

        @@ -1,379 +1,2 @@

        -

        -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

        -<html xmlns="http://www.w3.org/1999/xhtml">

        -  <!--

        ...

        -

        +Tohle je muj web!

    Running handlers:

    Running handlers complete

    Chef Client finished, 7/17 resources updated in 02 minutes 15 seconds

    ubuntu@chef-vm:~$

Chef vám říká co dělá a také co změnil a jak (u souboru index.html odstranil řádky s „-“ a přidal s „+“. Vyzkoušejme výsledek - z labServer zkuste kouknout na náš nový web.

    tomas@labserver:~/chef-repo$ curl 10.201.0.13

    Tohle je muj web!

Chef klient nemusí hned po akci skončit Je možné nechat jej běžet a on bude v pravidelných intervalech kontaktovat Chef server a spouštět co se mu řekne. To je velmi příjemná vlastnost, kdy jednak klient sám opraví cokoli, co se v mezičase pokazilo (ale pozor - možná včetně vašeho manuálního zásahu do VM, takže s tím procesně počítejte a ideálně nepřistupujte do VM přímo, spíše skrz modifikaci receptů), ale také stáhne nejnovější „zadání“. Má to i pozitivní vliv na výkon celého řešení (pull a lokální spuštění je rychlejší, než push krok za krokem v případě Ansible). Obvykle je vhodné interval nastavit třeba na 30 minut. V našem labu ale chceme výsledky dřív, takže použijeme (pro praxi nevhodných) 20 vteřin.

Zapněte ve VM chef-client s intervalem opakování 20 vteřin (spustíme jako normální proces, ať můžeme pohodlně sledovat výstup - dá se ale použít volba -d a spustit chef-client jako démona, typicky jako službu po startu systému). Před tím můžete modifikovat kuchařku (nezapomeňte ji také uploadovat na Chef server).

    ubuntu@chef-vm:~$ sudo chef-client -i 20

Sledujte výstup v chef-vm a v labServer modifikujte váš recept, tedy změňte obsah webové stránky.

    tomas@labserver:~/chef-repo$ nano cookbooks/mujWebServer/recipes/default.rb

    tomas@labserver:~/chef-repo$ knife cookbook upload mujWebServer

    Uploading mujWebServer   [0.1.0]

    Uploaded 1 cookbook.

Co se odehrálo v konzoli chef-vm? Chef se spouští každých 20 vteřin a v jistý okamžik zjistil, že konfigurace neodpovídá požadovanému stavu a provedl změnu (poznáte podle - a +).

    Recipe: mujWebServer::default

      * apt_package[apache2] action install (up to date)

      * service[apache2] action enable (up to date)

      * service[apache2] action start (up to date)

      * file[/var/www/html/index.html] action create

        - update content in file /var/www/html/index.html from 25c6a1 to 5d96a8

        --- /var/www/html/index.html        2015-12-07 12:19:19.480603000 +0000

        +++ /var/www/html/.index.html20151207-6961-145rh8c  2015-12-07 12:21:00.964603000 +0000

        @@ -1,4 +1,4 @@

        -Tohle je muj web!

        +Tohle je muj web2!

Vyzkoušejte i z labServer.

    tomas@labserver:~/chef-repo$ curl 10.201.0.13

    Tohle je muj web2!

Upravte kuchařku znovu a sledujte co se děje v okně s cílovou VM.

    Recipe: mujWebServer::default

      * apt_package[apache2] action install (up to date)

      * service[apache2] action enable (up to date)

      * service[apache2] action start (up to date)

      * file[/var/www/html/index.html] action create

        - update content in file /var/www/html/index.html from 5d96a8 to 057a5f

        --- /var/www/html/index.html        2015-12-07 12:21:00.964603000 +0000

        +++ /var/www/html/.index.html20151207-7951-quv8zl   2015-12-07 12:22:33.984603000 +0000

        @@ -1,4 +1,4 @@

        -Tohle je muj web2!

        +Tohle je muj web3!

Ověřte změnu také z labServer.

    tomas@labserver:~/chef-repo$ curl 10.201.0.13

    Tohle je muj web3!

Na tomto příkladu jsme si ukázali, jak Chef periodicky kontroluje, že jsou stanice v požadovaném stavu (desired state) a pokud ne, napraví to. Jednak se vám VM a dokumentace nerozjedou (je stále ve stavu, jaký chcete) a pokud potřebujete provést změnu, zapíšete ji do receptu a ona se vykoná. Bezpečně, opakovatelně a bez chyb.

Výhodou Chef řešení v porovnání s Ansible je, že v cílové VM běží chef-client, který se může pravidelně hlásit na chef-server a spouštět případné úpravy a aktualizace. Tuto komunikaci tedy iniciuje samotná VM, takže stavový firewall (mikrosegmentace, Security Group) ji může pustit ven a při tom není potřeba otevírat porty. Floating IP, kterou jsme v předhozí části labu používali pro bootstrap proces, tak můžeme z VM zase odebrat (například proto, že se nejedná o front end systém, ke kterému mají přistupovat uživatelé, ale je to třeba aplikační či databázový server, se kterým komunikuje jen aplikace). Jak už víme, instance bez Floating IP může přes virtuální router přistupovat do vnějšího světa přes source NAT podobně, jako vaše domácí počítače přistupují na Internet přes váš router. Chef-client se tedy do serveru dobouchá i když je za NAT.

Vytvoření instance s Floating IP, bootstrap Chef klienta a následné odebrání IP není zrovna praktické. Místo toho můžeme použít SSH gateway. Stačí mít ve vašem virtuálním světě (tenant/project) jednu obyčejnou VM s Floating IP, ze které je přístup na ostatní VM bez Floating IP. Chef knife dokáže bootstrap proces tunelovat skrz tuto gateway (na ní není žádný speciální software; jak uvidíte stačí třeba holý Ubuntu Server).

Vytvořte si další instanci Ubuntu, ale tentokrát bez Floating IP, ale nezapomeňte použít tento startup skript (připomínám, že v praxi to nebude nutné, protože budete mít v prostředí DNS server).

    #!/bin/bash

    printf '10.201.0.5 labserver.helion.demo\n' | sudo tee -a /etc/hosts

Z GUI si zjistěte přiřazenou privátní adresu.

Proveďme bootstrap přes gateway (poslouží nám Ubuntu VM, kterou už máme) a rovnou nainstalujeme web server s naší stránkou.

    tomas@labserver:~/chef-repo$ knife bootstrap 192.168.1.17 -i ~/mujKlic.pem -N Chef-vm2 -x ubuntu --sudo --bootstrap-proxy http://web-proxy.corp.hp.com:8088 --bootstrap-no-proxy labserver.helion.demo -G ubuntu@10.201.0.13 --run-list apt,mujWebServer

    Doing old-style registration with the validation key at ~/chef-repo/.chef/chefhelion.pem...

    Delete your validation key in order to use your user credentials instead

    Connecting to 192.168.1.17

    192.168.1.17 sudo: unable to resolve host chef-vm2

    192.168.1.17 -----> Installing Chef Omnibus (-v 12)

    192.168.1.17 downloading https://www.opscode.com/chef/install.sh

    192.168.1.17   to file /tmp/install.sh.1377/install.sh

    192.168.1.17 trying wget...

    192.168.1.17 ubuntu 14.04 x86_64

    192.168.1.17 Getting information for chef stable 12 for ubuntu...

    192.168.1.17 downloading https://omnitruck-direct.chef.io/stable/chef/metadata?v=12&p=ubuntu&pv=14.04&m=x86_64

    192.168.1.17   to file /tmp/install.sh.1381/metadata.txt

    192.168.1.17 trying wget...

    192.168.1.17 sha1       bc4a6642d6093b54de856da31f0651a56b0fdc8e

    192.168.1.17 sha256     f1cf5d0f6dd12d2d2296ec6d8dbb16363f8541f5c15298cafa70e65ff2b5a22f

    192.168.1.17 url        https://packages.chef.io/stable/ubuntu/14.04/chef_12.11.18-1_amd64.deb

    192.168.1.17 version    12.11.18

    192.168.1.17 downloaded metadata file looks valid...

    192.168.1.17 downloading https://packages.chef.io/stable/ubuntu/14.04/chef_12.11.18-1_amd64.deb

    192.168.1.17   to file /tmp/install.sh.1381/chef_12.11.18-1_amd64.deb

    192.168.1.17 trying wget...

    192.168.1.17 Comparing checksum with sha256sum...

    192.168.1.17 Installing chef 12

    192.168.1.17 installing with dpkg...

    192.168.1.17 Selecting previously unselected package chef.

    (Reading database ... 51169 files and directories currently installed.)

    192.168.1.17 Preparing to unpack .../chef_12.11.18-1_amd64.deb ...

    192.168.1.17 Unpacking chef (12.11.18-1) ...

    192.168.1.17 Setting up chef (12.11.18-1) ...

    192.168.1.17 Thank you for installing Chef!

    192.168.1.17 Starting the first Chef Client run...

    192.168.1.17 Starting Chef Client, version 12.11.18

    192.168.1.17 Creating a new client identity for Chef-vm2 using the validator key.

    192.168.1.17 resolving cookbooks for run list: ["apt", "mujWebServer"]

    192.168.1.17 Synchronizing Cookbooks:

    192.168.1.17   - apt (4.0.0)

    192.168.1.17   - compat_resource (12.10.6)

    192.168.1.17   - mujWebServer (0.1.0)

    192.168.1.17 Installing Cookbook Gems:

    192.168.1.17 Compiling Cookbooks...

    ...

    192.168.1.17 Recipe: apt::default

    192.168.1.17   * file[/var/lib/apt/periodic/update-success-stamp] action nothing (skipped due to action :nothing)

    192.168.1.17   * apt_update[periodic] action periodic

    192.168.1.17     - update new lists of packages

    192.168.1.17     * directory[/var/lib/apt/periodic] action create (up to date)

    192.168.1.17     * directory[/etc/apt/apt.conf.d] action create (up to date)

    192.168.1.17     * file[/etc/apt/apt.conf.d/15update-stamp] action create_if_missing (up to date)

    192.168.1.17     * execute[apt-get -q update] action run

    192.168.1.17       - execute apt-get -q update

    192.168.1.17

    192.168.1.17   * execute[apt-get update] action nothing (skipped due to action :nothing)

    192.168.1.17   * execute[apt-get autoremove] action nothing (skipped due to action :nothing)

    192.168.1.17   * execute[apt-get autoclean] action nothing (skipped due to action :nothing)

    192.168.1.17   * directory[/var/cache/local] action create

    192.168.1.17     - create new directory /var/cache/local

    192.168.1.17     - change mode from '' to '0755'

    192.168.1.17     - change owner from '' to 'root'

    192.168.1.17     - change group from '' to 'root'

    192.168.1.17   * directory[/var/cache/local/preseeding] action create

    192.168.1.17     - create new directory /var/cache/local/preseeding

    192.168.1.17     - change mode from '' to '0755'

    192.168.1.17     - change owner from '' to 'root'

    192.168.1.17     - change group from '' to 'root'

    192.168.1.17   * template[/etc/apt/apt.conf.d/10recommends] action create

    192.168.1.17     - create new file /etc/apt/apt.conf.d/10recommends

    192.168.1.17     - update content in file /etc/apt/apt.conf.d/10recommends from none to f41e1d

    192.168.1.17     --- /etc/apt/apt.conf.d/10recommends   2016-06-09 04:07:44.409341000 +0000

    192.168.1.17     +++ /etc/apt/apt.conf.d/.chef-10recommends20160609-1465-15p9pmx        2016-06-09 04:07:44.409341000 +0000

    192.168.1.17     @@ -1 +1,4 @@

    192.168.1.17     +# Managed by Chef

    192.168.1.17     +APT::Install-Recommends "1";

    192.168.1.17     +APT::Install-Suggests "0";

    192.168.1.17     - change mode from '' to '0644'

    192.168.1.17     - change owner from '' to 'root'

    192.168.1.17     - change group from '' to 'root'

    192.168.1.17   * apt_package[apt-transport-https] action install (up to date)

    192.168.1.17 Recipe: mujWebServer::default

    192.168.1.17   * apt_package[apache2] action install

    192.168.1.17     - install version 2.4.7-1ubuntu4.9 of package apache2

    192.168.1.17   * service[apache2] action enable (up to date)

    192.168.1.17   * service[apache2] action start (up to date)

    192.168.1.17   * file[/var/www/html/index.html] action create

    192.168.1.17     - update content in file /var/www/html/index.html from 538f31 to 2182e0

    192.168.1.17     --- /var/www/html/index.html   2016-06-09 04:08:47.289341000 +0000

    192.168.1.17     +++ /var/www/html/.chef-index.html20160609-1465-11mc083        2016-06-09 04:09:10.861341000 +0000

    192.168.1.17     @@ -1,379 +1,2 @@

    192.168.1.17     -

    192.168.1.17     -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    192.168.1.17     -<html xmlns="http://www.w3.org/1999/xhtml">

    192.168.1.17     -  <!--

    ...

    192.168.1.17     -</html>

    192.168.1.17     -

    192.168.1.17     +Tohle je muj web2!

    192.168.1.17

    192.168.1.17 Running handlers:

    192.168.1.17 Running handlers complete

    192.168.1.17 Chef Client finished, 7/17 resources updated in 02 minutes 01 seconds

    tomas@labserver:~/chef-repo$

Ověřme, že vše dopadlo dobře. Protože cílová VM je náš backend, tedy nemá Floating IP a dostane se k ní pouze jiná VM v našem tenantu, skočíme nejprve do první VM a z té vyzkoušíme stáhnout úvodní stránku.

  tomas@labserver:~/chef-repo$ ssh ubuntu@10.201.0.13 -i ~/mujKlic.pem "wget -qO- 192.168.1.17"

  Warning: Permanently added '10.201.0.13' (ECDSA) to the list of known hosts.

  Tohle je muj web2!

Právě jsme si předveli, že je možné používat i instalovat Chef za NATem.

Na závěr vyzkoušíme ještě jeden způsob rozchození VM spravované přes Chef v OpenStack prostředí. Utilitka knife je, jak jsme si už mohli všimnout, docela šikovná. Dokonce do ní existuje plugin pro Openstack. Díky tomu nemusíme připravovat VM dopředu, ale přímo jedním knife příkazem se nám VM vytvoří, nainstaluje se na ni Chef klient, ten se zaregistruje a spustí naše kuchařky. Pojďme si ho stáhnout a vyzkoušet.

    tomas@labserver:~/chef-repo$ cd ..

    tomas@labserver:~$ source proxy

    tomas@labserver:~$ chef gem install knife-openstack

    Fetching: knife-cloud-1.2.1.gem (100%)

    WARNING:  You don't have /home/tomas/.chefdk/gem/ruby/2.1.0/bin in your PATH,

              gem executables will not run.

    Successfully installed knife-cloud-1.2.1

    Fetching: knife-openstack-1.3.2.gem (100%)

    Successfully installed knife-openstack-1.3.2

    2 gems installed

    tomas@labserver:~$ unset http_proxy

    tomas@labserver:~$ unset https_proxy

    tomas@labserver:~$

Nejprve si poznamenáme některé vstupy, které budeme pro volání potřebovat - například ID favor, image, sítě apod. Protože jsme zatím neprobrali příkazovou řádku, která by pro tento úkol byla snadnější, použijeme GUI. Pokud se cítíte rovnou zkusit CLI, kde dostanete inforamce podstatně rychleji, přeskočte následující obrazovky.

Nejprve zjistěme Flavor ID pro l1.small v ADMIN, SYSTEM, Flavors

Najděte Image ID obrazu Ubuntu 14.04 v sekci PROJECT, COMPUTE, Images

Dál potřebujteme Network ID, které najdete v PROJECT, NETWORK, Networks

Chcete totéž najít rychleji z příkazové řádky? Můžete to udělat takhle:

    tomas@labserver:~$ source stack

    tomas@labserver:~$ openstack flavor list

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

    | ID                                   | Name      |   RAM | Disk | Ephemeral | VCPUs | Is Public |

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

    | 1                                    | m1.tiny   |   512 |    1 |         0 |     1 | True      |

    | 2                                    | m1.small  |  2048 |   20 |         0 |     1 | True      |

    | 3                                    | m1.medium |  4096 |   40 |         0 |     2 | True      |

    | 3ef6acf8-b0ae-45d0-ae0f-990b956aaa79 | l1.medium |  4096 |   10 |         0 |     2 | True      |

    | 4                                    | m1.large  |  8192 |   80 |         0 |     4 | True      |

    | 5                                    | m1.xlarge | 16384 |  160 |         0 |     8 | True      |

    | e81cf7b8-0c43-4114-a5ef-f4e56316dc0e | l1.small  |  2048 |    5 |         0 |     1 | True      |

    | fc17693b-ff34-4b23-98a6-acebc7da5ce3 | web.tiny  |   512 |    5 |         0 |     1 | True      |

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

    tomas@labserver:~$ openstack image list

    +--------------------------------------+--------------+--------+

    | ID                                   | Name         | Status |

    +--------------------------------------+--------------+--------+

    | fe14d439-75af-45d0-9084-08479e4a58c8 | web-server   | active |

    | 61de0c96-c30b-4207-924a-bb9188448878 | mujImage     | active |

    | 73fd1e9e-9370-4dc1-ac06-a6a9a598df14 | CoreOS       | active |

    | 767ec27b-0eed-43ea-9631-9115aaa78f05 | Stackato     | active |

    | bb0eba2a-6ce1-4393-b89f-4a219add5da7 | Ubutnu_14.04 | active |

    | e9664fca-74b0-4a59-95e9-87a1a844d031 | Cirros       | active |

    | 04d32087-6a66-4d04-8481-cdb3b8b472a3 | Ubuntu_16.04 | active |

    +--------------------------------------+--------------+--------+

    tomas@labserver:~$ openstack network list

    +--------------------------------------+---------+--------------------------------------+

    | ID                                   | Name    | Subnets                              |

    +--------------------------------------+---------+--------------------------------------+

    | d4712d32-e929-4c20-9b9c-fe9fe66b85f6 | ext-net | 46c758ce-febc-413d-b2cf-72f45e9df8b0 |

    | e99ab504-8e64-47c7-b33c-3f056a1c6844 | Web-sit | a5f5b1d2-8d0f-4edf-ab07-0717d1277378 |

    | 5431eac3-92cb-4464-8cd2-51ceb6804ed4 | mojeSit | 231efe61-4aa3-45ba-8904-4fdd3b1baabd |

    +--------------------------------------+---------+--------------------------------------+

Teď už stačí jen vyplnit příkaz knife openstack. Je tam toho docela hodně (v praxi můžete některé z těchto údajů uložit do konfiguračního souboru pro zjednodušení - i v našem případě jsou přihlašovací údaje pro Openstack zaznamenány v chef-repo/.chef/knife.rb). Bereme složitější scénář, tedy instance bude bez Floating IP a bootstrap proběhne přes SSH gateway. Říkáme jak se bude server jmenovat, informuje jej o proxy, určujeme flavor, image a sítě, SSH gateway a příslušé klíče, run-list pro spuštění kuchařek a také předáváme konfigurační skript v části user-data (jak si jistě vzpomínáte potřebujeme udělat statický záznam na labserver.helion.demo, protože v labu nemáme DNS službu). Knife a Chef automaticky provedou vše potřebné - nastartují server, nainstalují Chef klienta, spustí kuchařku, kterou tam natáhnou web server a naší stránku.

    tomas@labserver:~$ source stack

    tomas@labserver:~$ cd chef-repo/

    tomas@labserver:~/chef-repo$ knife openstack server create -N knifeTest --sudo --bootstrap-proxy http://web-proxy.corp.hp.com:8088 --bootstrap-no-proxy labserver.helion.demo --flavor e81cf7b8-0c43-4114-a5ef-f4e56316dc0e  --image bb0eba2a-6ce1-4393-b89f-4a219add5da7 --network-ids 5431eac3-92cb-4464-8cd2-51ceb6804ed4 --openstack-private-network --bootstrap-network mojeSit  --ssh-gateway ubuntu@10.201.0.13 --ssh-gateway-identity ~/mujKlic.pem --ssh-user ubuntu --openstack-ssh-key-id mujKlic -i ~/mujKlic.pem --run-list apt,mujWebServer --user-data nodnschef.sh

    Waiting for server [wait time = 600]......

    Instance ID        caa0d8d8-8985-46aa-b823-01f185fedd21

    Name               knifeTest

    Flavor             e81cf7b8-0c43-4114-a5ef-f4e56316dc0e

    Image              bb0eba2a-6ce1-4393-b89f-4a219add5da7

    Keypair            mujKlic

    State              ACTIVE

    Availability Zone  nova

    Bootstrapping the server by using bootstrap_protocol: ssh and image_os_type: linux

    Waiting for sshd to host (192.168.1.18).......................................................................................done

    Doing old-style registration with the validation key at ~/chef-repo/.chef/chefhelion.pem...

    Delete your validation key in order to use your user credentials instead

    Connecting to 192.168.1.18

    192.168.1.18 sudo: unable to resolve host knifetest

    192.168.1.18 -----> Installing Chef Omnibus (-v 12)

    192.168.1.18 downloading https://www.opscode.com/chef/install.sh

    192.168.1.18   to file /tmp/install.sh.1378/install.sh

    192.168.1.18 trying wget...

    192.168.1.18 ubuntu 14.04 x86_64

    192.168.1.18 Getting information for chef stable 12 for ubuntu...

    192.168.1.18 downloading https://omnitruck-direct.chef.io/stable/chef/metadata?v=12&p=ubuntu&pv=14.04&m=x86_64

    192.168.1.18   to file /tmp/install.sh.1382/metadata.txt

    192.168.1.18 trying wget...

    192.168.1.18 sha1       bc4a6642d6093b54de856da31f0651a56b0fdc8e

    192.168.1.18 sha256     f1cf5d0f6dd12d2d2296ec6d8dbb16363f8541f5c15298cafa70e65ff2b5a22f

    192.168.1.18 url        https://packages.chef.io/stable/ubuntu/14.04/chef_12.11.18-1_amd64.deb

    192.168.1.18 version    12.11.18

    192.168.1.18 downloaded metadata file looks valid...

    192.168.1.18 downloading https://packages.chef.io/stable/ubuntu/14.04/chef_12.11.18-1_amd64.deb

    192.168.1.18   to file /tmp/install.sh.1382/chef_12.11.18-1_amd64.deb

    192.168.1.18 trying wget...

    192.168.1.18 Comparing checksum with sha256sum...

    192.168.1.18 Installing chef 12

    …

    192.168.1.18 Starting Chef Client, version 12.11.18

    192.168.1.18 Creating a new client identity for knifeTest using the validator key.

    192.168.1.18 resolving cookbooks for run list: ["apt", "mujWebServer"]

    192.168.1.18 Synchronizing Cookbooks:

    192.168.1.18   - apt (4.0.0)

    192.168.1.18   - compat_resource (12.10.6)

    192.168.1.18   - mujWebServer (0.1.0)

    192.168.1.18 Installing Cookbook Gems:

    192.168.1.18 Compiling Cookbooks...

    192.168.1.18 Converging 12 resources

    192.168.1.18 Recipe: apt::default

    192.168.1.18   * file[/var/lib/apt/periodic/update-success-stamp] action nothing (skipped due to action :nothing)

    192.168.1.18   * apt_update[periodic] action periodic

    192.168.1.18     - update new lists of packages

    192.168.1.18     * directory[/var/lib/apt/periodic] action create (up to date)

    192.168.1.18     * directory[/etc/apt/apt.conf.d] action create (up to date)

    192.168.1.18     * file[/etc/apt/apt.conf.d/15update-stamp] action create_if_missing (up to date)

    192.168.1.18     * execute[apt-get -q update] action run

    192.168.1.18       - execute apt-get -q update

    192.168.1.18

    192.168.1.18   * execute[apt-get update] action nothing (skipped due to action :nothing)

    192.168.1.18   * execute[apt-get autoremove] action nothing (skipped due to action :nothing)

    192.168.1.18   * execute[apt-get autoclean] action nothing (skipped due to action :nothing)

    192.168.1.18   * directory[/var/cache/local] action create

    192.168.1.18     - create new directory /var/cache/local

    192.168.1.18     - change mode from '' to '0755'

    192.168.1.18     - change owner from '' to 'root'

    192.168.1.18     - change group from '' to 'root'

    192.168.1.18   * directory[/var/cache/local/preseeding] action create

    192.168.1.18     - create new directory /var/cache/local/preseeding

    192.168.1.18     - change mode from '' to '0755'

    192.168.1.18     - change owner from '' to 'root'

    192.168.1.18     - change group from '' to 'root'

    192.168.1.18   * template[/etc/apt/apt.conf.d/10recommends] action create

    192.168.1.18     - create new file /etc/apt/apt.conf.d/10recommends

    192.168.1.18     - update content in file /etc/apt/apt.conf.d/10recommends from none to f41e1d

    192.168.1.18     --- /etc/apt/apt.conf.d/10recommends   2016-06-09 05:18:17.216186000 +0000

    192.168.1.18     +++ /etc/apt/apt.conf.d/.chef-10recommends20160609-1469-pohs2d 2016-06-09 05:18:17.216186000 +0000

    192.168.1.18     @@ -1 +1,4 @@

    192.168.1.18     +# Managed by Chef

    192.168.1.18     +APT::Install-Recommends "1";

    192.168.1.18     +APT::Install-Suggests "0";

    192.168.1.18     - change mode from '' to '0644'

    192.168.1.18     - change owner from '' to 'root'

    192.168.1.18     - change group from '' to 'root'

    192.168.1.18   * apt_package[apt-transport-https] action install (up to date)

    192.168.1.18 Recipe: mujWebServer::default

    192.168.1.18   * apt_package[apache2] action install

    192.168.1.18     - install version 2.4.7-1ubuntu4.9 of package apache2

    192.168.1.18   * service[apache2] action enable (up to date)

    192.168.1.18   * service[apache2] action start (up to date)

    192.168.1.18   * file[/var/www/html/index.html] action create

    192.168.1.18     - update content in file /var/www/html/index.html from 538f31 to 2182e0

    192.168.1.18     --- /var/www/html/index.html   2016-06-09 05:20:11.672186000 +0000

    192.168.1.18     +++ /var/www/html/.chef-index.html20160609-1469-1izafp2        2016-06-09 05:20:26.548186000 +0000

    192.168.1.18     @@ -1,379 +1,2 @@

    192.168.1.18     -

    192.168.1.18     -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    192.168.1.18     -<html xmlns="http://www.w3.org/1999/xhtml">

    192.168.1.18     -  <!--

    ...

    192.168.1.18     -</html>

    192.168.1.18     -

    192.168.1.18     +Tohle je muj web2!

    192.168.1.18

    192.168.1.18 Running handlers:

    192.168.1.18 Running handlers complete

    192.168.1.18 Chef Client finished, 7/17 resources updated in 02 minutes 52 seconds

    Instance ID        caa0d8d8-8985-46aa-b823-01f185fedd21

    Name               knifeTest

    Flavor             e81cf7b8-0c43-4114-a5ef-f4e56316dc0e

    Image              bb0eba2a-6ce1-4393-b89f-4a219add5da7

    Keypair            mujKlic

    State              ACTIVE

    Availability Zone  nova

    tomas@labserver:~/chef-repo$

Pokud je Knife vaším oblíbeným nástrojem, dává smysl používat Openstack plugin do něj.

Chef nám přes OpenStack vytvořil požadovanou VM a rovnou do ní nahrál vše, co potřebujem. Web server je funkční.

Máme hotovo, vyčistěme zdroje v labu, prosím. Zrušte VM v OpenStack.

Projděte si seznam Chef nodů a klientů a odmazejte ty vaše, prosím. Současně take ukončete vaše běžící VM, ať šetříme zdroje labu.

    tomas@labserver:~/chef-repo$ knife node list

    Chef-vm2

    knifeTest

    prvniPokus

    tomas@labserver:~/chef-repo$ knife node delete Chef-vm2 knifeTest prvniPokus -y

    Deleted node[Chef-vm2]

    tomas@labserver:~/chef-repo$ knife node delete knifeTest -y

    Deleted node[knifeTest]

    tomas@labserver:~/chef-repo$ knife node delete prvniPokus -y

    Deleted node[prvniPokus]

    tomas@labserver:~/chef-repo$ knife client list

    Chef-vm2

    helion-validator

    knifeTest

    prvniPokus

    tomas@labserver:~/chef-repo$ knife client delete Chef-vm2 -y

    Deleted client[Chef-vm2]

    tomas@labserver:~/chef-repo$ knife client delete knifeTest -y

    Deleted client[knifeTest]

    tomas@labserver:~/chef-repo$ knife client delete prvniPokus -y

    Deleted client[prvniPokus]

Zapouzdřené aplikace aneb immutable server

Dotahování image je sice výborné z pohledu opakovatelnosti, dokumentace, přenositelnosti a plné automatizace, ale může trvat dlouho. Pokaždé musíte stáhnout hromady balíčků (někdy je dobrý nápad mít lokální cache), upravit a nakopírovat spousty souborů, instalovat služby. Všechno sice dělá precizní automat, ale zkrátit čas se mu nemusí podařit. Pokud by v předpisu byla chyba, je nutné ji zachytit, a protožo takový deployment už má blízko k Operations týmu, musí v něm být potřebné znalosti. Ze všech těchto důvodů se dá jít ještě dál a připravovat zlaté obrazy, tedy golden image a immutable server.

Myšlenka spočívá v tom, že vyjdete z předchozího scénáře, protože ten vám dává všechny příjemné vlastnosti desired state způsobu práce. Jeho výsledky ovšem přetavíte v hotový obraz – a samozřejmě automatizovaně. Můj nejoblíbenější nástroj je v tomto ohledu jednoznačně Packer. Je to jednoúčelový nástroj – stejných výsledků dosáhnete i v rámci univerzálnější orchestrace typu HPE Operation Orchestration či jeho open source varianty CloudSlang. Začínáte tím, že Packeru předhodíte výchozí obraz s OS. V předchozím kroku byly nástroje nezávislé na hypervisoru, tady to tak není – nicméně můžete jedním krokem a způsobem vyrobit obrazy pro různé platformy. Do předpisu tedy dáme třeba Debian obraz ve vSphere, OpenStack s KVM a Amazon AMI – tyto obvykle nemusíme vytvářet, existují už hotové. Packer pak každý tento image spustí v příslušném prostředí a provede „dotažení“ – shell skript, Ansible, Chef a mnohé další podle vaší chutě. Následně z výsledku udělá nový image a ten připraví ke spuštění. Tak například v OpenStack to funguje tak, že Packer si sám na pozadí vytvoří instanci výchozího image, zajistí spuštění dotahovačů, pak instanci vypne, udělá z ní nový image, který je v OpenStack k dispozici pro spuštění. Totéž platí pro Amazon nebo vSphere a kromě toho Packer umí i čisté QEMU/KVM nebo VirtualBox včetně přípravy Vagrant boxů. A mimochodem dnes už podporuje i Docker kontejner, takže se stává docela dobrou migrační cestou pro ty, co kromě VM zkouší i kontejnery.

Výsledkem je, že provoz získává image s instancí aplikace, kterou stačí spustit v požadovaném počtu. Je dokonce možné v zapouzdření jít tak daleko, že necháte Packer na konci procesu zlikvidovat management přístup do VM, tedy zakázat SSH či RDP. Řešení je velmi spolehlivé, jednoduché pro provozáky a vše se spouští velmi rychle a dají se tak použít vychytávky jako je autoscaling cloud native aplikací. Je tu ale jedna změna – v předchozím případě nám konfigurační nástroj mohl zajistit i aplikační konfiguraci (tedy sdělit VM s aplikací kde má DB a jak se do ní nalogovat). V tomto scénáři něco takového není vhodné – naše zlaté obrazy by neměly mít pevně danou konfiguraci v sobě. Nastavení a objevování nodů by tedy mělo být ideálně mimo vlastní obraz. Na to existují nástroje jako je Etcd, Consul, Zookeper nebo doozerd – ale o těch jindy. Immutable servery jsou perfektní, ale už po vás vyžadují trochu víc znalostí a přemýšlení – ale odměna je sladká.

Tohle si vyzkoušíte v druhé pokročilejší části labu Helion OpenStack a některé funkce jako je Etcd nebo Consul v připravovaném labu zaměřeném na moderní vývoj aplikací, kontejnery, Helion Stackato a Helion Development Platform.

Packer pro automatickou tvorbu imagů

Packer (packer.io) je zajímavý nástroj pro automatické vytváření hotových image jedním procesem pro různé platformy. Nejdříve si vyzkoušíme jednoduchý příklad přímo na našem OpenStack a později popíšeme další možnosti.

Nejprve budeme potřebovat znát UUID startovacího image (v našem labu to bude Ubuntu a už je předvyplněn, ale zkontrolujte to), identifikátor vaší sítě a Security Group, která povolí SSH přístup.

    tomas@labserver:~$ source stack

    tomas@labserver:~/packer$ openstack network list

    +--------------------------------------+---------+--------------------------------------+

    | ID                                   | Name    | Subnets                              |

    +--------------------------------------+---------+--------------------------------------+

    | d4712d32-e929-4c20-9b9c-fe9fe66b85f6 | ext-net | 46c758ce-febc-413d-b2cf-72f45e9df8b0 |

    | e99ab504-8e64-47c7-b33c-3f056a1c6844 | Web-sit | a5f5b1d2-8d0f-4edf-ab07-0717d1277378 |

    | 5431eac3-92cb-4464-8cd2-51ceb6804ed4 | mojeSit | 231efe61-4aa3-45ba-8904-4fdd3b1baabd |

    +--------------------------------------+---------+--------------------------------------+

    tomas@labserver:~/packer$ openstack security group list

    +---------------------------+--------------+---------------------------+---------------------------+

    | ID                        | Name         | Description               | Project                   |

    +---------------------------+--------------+---------------------------+---------------------------+

    | 42fa6ec7-86b2-4ca0-92f8-6 | default      | Default security group    | d2811986367044f9a5d9efa18 |

    | a2c70f2a3a7               |              |                           | 0e746cd                   |

    | 616f4f6f-ba2a-4768-b1f9-3 | WebServery   | Webova farma pro moji     | d2811986367044f9a5d9efa18 |

    | 011e49a7d19               |              | aplikaci                  | 0e746cd                   |

    | 73ead103-f579-4681-9b0a-  | WebFrontend  | Povoleni portu 80 a 443   | d2811986367044f9a5d9efa18 |

    | 652623b49b44              |              |                           | 0e746cd                   |

    | 95e4e1e7-966b-            | SSH+ICMP     | Povoluje SSH přístup a    | d2811986367044f9a5d9efa18 |

    | 4a10-8512-a985a2791229    |              | ICMP                      | 0e746cd                   |

    | b4720c8e-66a6-4964-9ec1-a | MojeAplikace | Skupina aplikacnich       | d2811986367044f9a5d9efa18 |

    | 4c58565b02b               |              | serveru                   | 0e746cd                   |

    +---------------------------+--------------+---------------------------+---------------------------+

Na labServer v adresáři packer najdete příklad hotové Packer šablony. Bude potřeba v ní editovat některé údaje – zejména UUID vaší sítě a dále upravit výčet Security Groups (pokud jste použili jiný název pro skupinu povolující SSH). Pokud máte v projektu již přidělené a volné Floating IP, vyplňte je prosím do části “floating_ip”, abychom šetřili zdroje labu (tento řádek můžete take odstranit a Packer si sám řekne o novou Floating IP). Dále změňte položku “networks”, ověřte, že i ostatní parametry jsou v pořádku případně změňte název výsledného obrazu (image_name).

    tomas@labserver:~/packer$ cat packer_web.json

    {

      "builders": [{

        "type": "openstack",

        "ssh_username": "ubuntu",

        "image_name": "mujPackerImage",

        "source_image": "bb0eba2a-6ce1-4393-b89f-4a219add5da7",

        "flavor": "l1.small",

        "networks": ["5431eac3-92cb-4464-8cd2-51ceb6804ed4"],

        "security_groups": ["default", "SSH+ICMP"],

        "use_floating_ip": true,

        "floating_ip": "10.201.0.13",

        "floating_ip_pool": "ext-net"

      }],

      "provisioners": [{

        "type": "shell",

        "inline": [

          "export http_proxy=http://web-proxy.corp.hp.com:8088",

          "sudo -E apt-get update",

          "sudo -E apt-get install nginx -y",

          "printf 'Web server zabaleny Packerem\n\n' | sudo tee /usr/share/nginx/html/index.html"

          ]

      }]

    }

Přihlašovací údaje do OpenStack si Packer vezme z prostředí (ENV), takže je nemusíme zadávat do šablony. V první části (builder) pracujeme s OpenStack a v druhé (provisioning) děláme požadované operace. Pro jednoduchost jsme zvolili jednoduché spuštění skriptu přímo uvnitř VM při vytváření image – tento script stáhne webový server a modifikuje hlavní stránku. Pokročilejší možnosti si popíšeme později.

Nejprve přidejte do prostředí informaci o doméně a proveďte validaci šablony co do syntaxe.

    tomas@labserver:~/packer$ source ~/stack

    tomas@labserver:~/packer$ export OS_DOMAIN_NAME=Default

    tomas@labserver:~/packer$ packer validate packer_web.json

    Template validated successfully.

Pokud je vše v pořádku, spusťte budování nového image. Sledujte textový výpis i GUI OpenStack – uvidíte co se děje.

    tomas@labserver:~/packer$ packer build packer_web.json

    openstack output will be in this color.

    ==> openstack: Discovering enabled extensions...

    ==> openstack: Loading flavor: l1.small

        openstack: Verified flavor. ID: e81cf7b8-0c43-4114-a5ef-f4e56316dc0e

    ==> openstack: Creating temporary keypair: packer 57591c3c-d3e8-9407-f2ba-2d23a0b30485 ...

    ==> openstack: Created temporary keypair: packer 57591c3c-d3e8-9407-f2ba-2d23a0b30485

    ==> openstack: Successfully converted BER encoded SSH key to DER encoding.

    ==> openstack: Launching server...

        openstack: Server ID: 5db137ef-0fbe-4998-9858-9781814fe496

    ==> openstack: Waiting for server to become ready...

    ==> openstack: Associating floating IP with server...

        openstack: IP: 10.201.0.13

        openstack: Added floating IP 10.201.0.13 to instance!

    ==> openstack: Waiting for SSH to become available...

    ==> openstack: Connected to SSH!

    ==> openstack: Provisioning with shell script: /tmp/packer-shell520314446

        openstack: sudo: unable to resolve host mujpackerimage

        openstack: Get:1 http://security.ubuntu.com trusty-security InRelease [65.9 kB]

        ...

        openstack: Get:35 http://archive.ubuntu.com trusty/universe Translation-en [4089 kB]

        openstack: Fetched 15.3 MB in 16s (935 kB/s)

        openstack: Reading package lists...

        ...

        openstack: Setting up nginx-light (1.4.6-1ubuntu3.5) ...

        openstack: Setting up nginx (1.4.6-1ubuntu3.5) ...

        openstack: sudo: unable to resolve host mujpackerimage

        openstack: Web server zabaleny Packerem

        openstack:

    ==> openstack: Stopping server: 5db137ef-0fbe-4998-9858-9781814fe496 ...

        openstack: Waiting for server to stop: 5db137ef-0fbe-4998-9858-9781814fe496 ...

    ==> openstack: Creating the image: mujPackerImage

        openstack: Image: e5c2239f-0276-492f-bbc1-834a070cfc9d

    ==> openstack: Waiting for image mujPackerImage (image id: e5c2239f-0276-492f-bbc1-834a070cfc9d) to become ready...

    ==> openstack: Terminating the source server: 5db137ef-0fbe-4998-9858-9781814fe496 ...

    ==> openstack: Deleting temporary keypair: packer 57591c3c-d3e8-9407-f2ba-2d23a0b30485 ...

    Build 'openstack' finished.

    ==> Builds finished. The artifacts of successful builds are:

    --> openstack: An image was created: e5c2239f-0276-492f-bbc1-834a070cfc9d

Prohlédněte si Image ve vašem OpenStack

Vytvořte novou instanci z tohoto image a dejte jí Floating IP a Security Group povolující webový přístup.

    tomas@labserver:~/packer$ curl 10.201.0.13

    Web server zabaleny Packerem

Instanci i Image prosím zrušte, abychom šetřili zdroje v labu.

Pro inspiraci si prohlédněte další předpis, který (pro účely jiného labu) používáme k vytvoření obrazu Docker host systému:

    {

      "builders": [{

        "type": "openstack",

        "ssh_username": "ubuntu",

        "image_name": "Docker",

        "source_image": "8490e531-6c9d-4caa-8e15-61e5f749b0ff",

        "flavor": "m1.small",

        "networks": ["b830b33d-06fc-470a-aa12-ec4e709ef3c4"],

        "use_floating_ip": true,

        "floating_ip": "10.201.0.12",

        "floating_ip_pool": "ext-net"

      }],

      "provisioners": [{

        "type": "shell",

        "inline": [

          "export http_proxy=http://web-proxy.corp.hp.com:8088",

          "export https_proxy=http://web-proxy.corp.hp.com:8088",

          "sudo -E apt-get update",

          "sudo -E curl -sSL https://get.docker.com/ | sh",

          "sudo -E usermod -aG docker ubuntu",

          "sudo -E wget https://github.com/docker/machine/releases/download/v0.5.4/docker-machine_linux-amd64 -O /usr/local/bin/docker-machine",

          "sudo -E chmod +x /usr/local/bin/docker-machine",

          "sudo -E wget https://github.com/docker/compose/releases/download/1.5.2/docker-compose-Linux-x86_64 -O /usr/local/bin/docker-compose",

          "sudo -E chmod +x /usr/local/bin/docker-compose",

          "sudo mkdir /etc/systemd/system/docker.service.d",

          "printf 'export http_proxy=http://web-proxy.corp.hp.com:8088\n' | sudo tee -a /etc/default/docker",

          "printf 'http_proxy=http://web-proxy.corp.hp.com:8088\n' | sudo tee -a /etc/environment",

          "printf 'https_proxy=http://web-proxy.corp.hp.com:8088\n' | sudo tee -a /etc/environment",

          "printf 'no_proxy=localhost,10.0.0.7,16.21.188.203\n' | sudo tee -a /etc/environment",

          "printf 'Defaults env_keep = http_proxy\n' | sudo tee -a /etc/sudoers"

          ]

      }]

    }

Packer je velmi mocný nástroj – dotkněme se některých dalších možností. Podstatné je, že můžete v jedné šabloně kombinovat víc providerů a postupů. Z jednoho místa jedním konzistentním procesem tak můžete vytvořit zlaté diskové obrazy pro OpenStack, vSphere, čisté KVM/QEMU, Vagrant nebo třeba Amazon a dokonce i Docker kontejner (což může být zajímavá varianta v postupném přechodu na kontejnerové technologie). Z jakých částí se skládá?

  • Builders – prostředí, pro která má Packer vytvářet hotový obraz. Možnosti zahrnují Amazon EC2, OpenStack, VMware, QEMU, VirtualBox, Google Compute Engine nebo třeba i Docker kontejner

  • Provisioners – nástroje, které ze základního obrazu „dotáhnou“ VM do stavu, který chcete zmrazit do zlatého obrazu. Mezi ně patří jednoduchý i složitější bash shell, PowerShell, uploadování souborů, lokální Ansible, Chef Solo, Puppet Masterless nebo Salt

  • Post-processors – po ukončení všech operací můžete ještě výsledek zabalit nebo kolem něj vytvořit nějaký předpis. Sem patří příprava Vagrant prostředí, upload do vSphere, komprese do archivu nebo push do Docker registru

Potřebujete konzistentním způsobem vytvářet obrazy pro velmi různorodá prostředí? Packer je dobrý způsob, jak to vyřešit. Začněte ze základních image s OS, automatizovaně přidejte cokoli potřebujete a získejte výsledek pro různé platformy od klasických hypervisorů přes IaaS u vás až po public cloud nebo přenositelný Docker kontejner.