De câte ori ai auzit "Dar funcționează pe mașina mea" sau "Dar la mine pe local merge"? Cât timp îți ia să-ți setezi mediul de lucru? De câte ori ai întâlnit diferențe între serverul de pe producție și cel de dezvoltare? Imaginează-ți o lume ideală în care toți dezvoltatorii lucrează pe aceeași platformă, în care platformele de dezvoltare și cele de producție au fost construite bazându-se pe aceleași specificații. Această lume există și se numește virtualizare. Vagrant este un tool de virtualizare, care are un răspuns la toate aceste întrebări, transformând această lume ideală într-o lume reală. Vagrant poate fi folosit pentru a crea și a configura medii de dezvoltare performante, portabile și reproductibile.
Vagrant este dezvoltat în Ruby de către Mitchell Hashimoto, Mithchell este un developer pasionat de automatizare. A început proiectul Vagrant în 2010, în timpul liber. În următorii ani proiectul a crescut și a început să fie folosit cu încredere de un număr tot mai mare de dezvoltatori. Ca urmare în 2012 Mitchell a înființat propria lui companie HashiCorp, pentru a dezvolta și pentru a oferi training-uri și suport profesional pentru Vagrant. În momentul de față Vagrant este un proiect open source, fiind rezultatul a sute de contribuitori pe GitHub.
Pentru a realiza magia, Vagrant se bazează pe giganții lui, acționând ca un layer în fața providerilor VirtualBox, VMware, AWS sau alții. De asemenea, instrumente din industria-standard de provisionare, cum sunt script-urile Shell, Chef și Puppet pot fi folosite pentru a seta automat un nou mediu de dezvoltare. Vagrant poate fi folosit și în proiecte scrise în alte limbaje de programare cum ar fi PHP, Pyton, Java, C# sau JavaScript și poate fi instalat atât pe sisteme Linux, Mac OS X cât și pe Windows.
Vagrant oferă mașini virtuale tranzistorii, portabile care se pot muta dintr-o parte într-alta, fără a avea o locație fixă, exact ca un vagabond. Dacă ești programator, poți folosi Vagrant pentru a izola dependințele și configurațiile lor cu un singur mediu de dezvoltare consistent. Odată ce a fost creat Vagrantfile trebuie doar să rulezi comanda vagrant-uppentru ca totul să funcționeze pe mașina ta. Ca inginer de sistem, Vagrant îți oferă un mediu disponibil și un flux de muncă consistent pentru dezvoltarea și testarea script-urilor de management a infrastructurii. Poți testa foarte rapid shell script-uri, rețete Chef și module Puppet, folosind virtualizarea pe mașini locale cum sunt VirtualBox sau VMware. Apoi cu aceleași configurări, poți testa script-urile remote din cloudscum sunt AWS sau RackSpace, folosind același mod de lucru. Ca designer, folosind Vagrant poți să setezi cu ușurință un nou mediu de dezvoltare bazat pe fișierul de configurare Vagrantfile, care este deja configurat, fără să-ți mai faci griji cum să reconfigurezi aplicația.
Folosind Vagrant poți obține următoarele beneficii:
Înainte de a începe primul proiect Vagrant, trebuie să instalezi VirtualBox sau orice alt provider suportat de Vagrant. Pentru acest exemplu eu am folosit VirtualBox. Primul pas constă în instalarea instrumentului Vagrant, prin descărcarea și instalarea pachetului sau a executabilului corespunzător, de pe pagina oficială de descărcare a Vagrant-ului. Executabilul va adăuga automat vagrant în calea de sistem, fiind disponibil în terminal imediat după instalare, cum se poate vedea mai jos.
$ vagrant
Usage: vagrant [-v] [-h] command []
-v, --version Print the version and exit.
-h, --help Print this help.
Available subcommands:
box manages boxes: installation, removal, etc.
destroy stops and deletes all traces of the vagrant machine
halt stops the vagrant machine
help shows the help for a subcommand
init initializes a new Vagrant environment by creating a Vagrantfile
package packages a running vagrant environment into a box
plugin manages plugin s: install, uninstall, update, etc.
provision provisions the vagrant machine
reload restarts vagrant machine, loads new Vagrantfile configuration
resume resume a suspended vagrant machine
ssh connects to machine via SSH
ssh-config outputs OpenSSH valid configuration to connect to
the machine
status outputs status of the vagrant machine
suspend suspends the machine
up starts and provisions the vagrant environment
Următorul pas este inițializarea instrumentului Vagrant în noul proiect, rulând comanda:
$ vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please
Read the comments in the Vagrantfile as well as documentation on`vagrantup.com` for more information on using Vagrant.
După rularea acestei comenzi, Vagrantfile este generat automat în directorul proiectului pe care s-a făcut inițializarea. Vagrantfile este scris în Ruby, dar nu este necesară cunoașterea acestui limbaj de programare, deoarece majoritatea modificărilor constau într-o simplă atribuire de variabile. Fișierul Vagrantfile are următoarele roluri:
Fișierul Vagrantfile generat automat conține următoarele linii:
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "precise32"
# The url from where the 'config.vm.box' box will be fetched if it
# doesn't already exist on the user's system.
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
Directiva config.vm.box = "precise32", descrie tipul mașinii virtuale. "Box-ul" reprezintă scheletul pe care mașinile virtuale Vagrant vor fi construite. Acestea sunt fișiere portabile care pot fi folosite de către oricine, pe orice platformă pe care rulează Vagrant. Un lucru important de observat este faptul că aceste așa-zise cutii sunt create pe baza provider-ilor. În aces sens, înainte de instalarea scheletului mașinii virtuale, trebuie verficat provider-ul pe care se bazează. Pentru a selecta un schelet pentru mașina virtuală puteți accesa http://www.vagrantbox.es. Aici poate fi găsită o listă cu toate base-box-urile care sunt disponibile. Vagrant oferă de asemenea, posibilitatea de a crea "cutii" personalizare. Un instrument util în acest scop este Veewee**,care are ca obiectiv automatizarea tuturor pașilor pentru construirea acestor "cutii" cât și colectarea celor mai bune practici într-o modalitate transparentă.O "cutie"**poate fi adăugată și din linia de comandă tastând:
$ vagrant box add
Unde
$ vagrant box add precise32 http://files.vagrantup.com/precise32.box
Comenzile disponibile pentru management-ul "cutiilor" sunt listate mai jos.
$ vagrant box -h
Usage: vagrant box []
Available subcommands:
add
list
remove
repackage
For help on any individual command run `vagrant box COMMAND -h`
For help on any individual command run vagrant box COMMAND -h
Sunt două modalități care pot fi folosite pentru specificarea provider-ului, similar modului cum a fost descris mai sus pentru "cutii". O opțiune constă în specificarea provider-ului ca parametru din linia de comandă. Dacă este selectată această metodă, trebuie să te asiguri că argumentul prevăzut coincide cu cel specificat în directiva config.vm.provider.
$ vagrant up --provider=virtualbox
Celalaltă opțiune este să se specifice provider-ul doar în directiva config.vm.provider.
Important de menționat este faptul că unele "cutii" nu necesită specificarea provider-ului, deoarece pot funcționa cu orice tip de provider.
Vagrantfile oferă posibilitatea configurării provider-ilor prin adăugarea directivei vb.customize. De exemplu, dacă vrei să mărești memoria alocată mașinii virtuale, poți să faci cum este descris mai jos.
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
config.vm.provider :virtualbox do |vb|
# # Don't boot with headless mode
# vb.gui = true
#
# # Use VBoxManage to customize the VM. For example to change memory:
vb.customize ["modifyvm", :id, "--memory", "2048"]
end
Accesarea paginilor web în curs de dezvoltare, de pe mașina virtuală nu este o idee prea bună. Tocmai de aceea, Vagrant oferă funcționalități pentru configurarea rețelei, cu scopul de a accesa mașina virtuală, de pe mașina locală. Vagrantfile are trei directive care pot fi folosite pentru configurarea rețelei.
config.vm.network :forwarded_port, guest: 80, host: 8080
Traducând această directivă, deducem faptul că Apache-ul instalat pe mașina virtuală, creată de Vagrant, poate fi accesat de pe mașina locală, folosind url-ul http://127.0.0.1:8080. Aceasta înseamnă că tot traficul din rețea a fost redirecționat spre portul specificat pe mașina virtuală.
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
config.vm.provider :virtualbox do |vb|
# # Don't boot with headless mode
# vb.gui = true
#
# # Use VBoxManage to customize the VM. For example to change memory:
vb.customize ["modifyvm", :id, "--memory", "2048"]
end
config.vm.network :public_network
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
config.vm.network :public_network
config.vm.network :private_network, ip: "192.168.33.10"
access to the machine
# using a specific IP.
config.vm.network :private_network, ip: "192.168.33.10"
Vagrantfile oferă posibilitatea de a confgura namespace-ul config.ssh pentru a specifica numele utilizatorului, host-ul, port-ul, guest_port-ul, private_key_path, forward_agent, forward_x11 și shell.
Vagrant.configure("2") do |config|
config.ssh.private_key_path = "~/.ssh/id_rsa"
config.ssh.forward_agent = true
end
În timp ce mulți utilizatori editează fișierele de pe mașinile virtuale folosind doar editoare sincronizate cu mașina virtuală prin SSH, Vagrant oferă posibilitatea de sincronizare automată a fișierelor de pe ambele mașini, folosind folder-ele sincronizate. În mod implicit Vagrant oferă posibilitatea da a sincroniza fișierele de pe mașina locală, cu directorul /vagrant de pe mașina virtuală. În acest fel directorul /vagrant localizat pe mașina virtuală, este identic cu cel de pe mașina locală. Astfel nu mai ești nevoit să folosești opțiunile de Upload și Download, din IDE pentru sincronizarea fișierelor. Dacă vrei să modifici directorul sincronizat de pe mașina sincronizată, o poți face adăugând următoarea directivă config.vm.synced_folder "../data", "/vagrant_data" în Vagrantfile.
Vagrant.configure("2") do |config|
config.vm.synced_folder "../data", "/vagrant_data"
end
Provizionarea nu este o sarcină de care se ocupă în mod normal dezvoltatorii, deoarece administratorii de sistem sunt cei care fac lucrurile acestea. Ideea de la care se pornește este de a înregistra configurările setate pe un server, cu scopul de a le replica pe un alt server. Mai demult administratorii de sistem țineau un wiki pentru comenzile rulate pe servere, dar această metodă nu era cea mai bună. Altă opțiune este să creezi back-up-uri .box sau .iso, astfel încât noile servere să poată fi configurate pe baza acestor fișiere. Dar, menținerea la zi a acestor fișiere este dificilă și necesită mai multă muncă, fiind în același timp destul de greu să sincronizezi toate serverele în acest fel. Provizionarea în zilele noastre, oferă posibilitatea de a adăuga software special pentru creare fișierelor de configurare, pentru executarea comenzilor, pentru crearea utilizatorilor sau managementul serviciilor, folosind sisteme moderne de provizionare. Vagrant poate fi integrat cu următoarele sisteme de provizionare: Shell, Ansible, Chef Solo, Chef Client, Puppet, Salt Stack. Cele mai populare sisteme de provizionare sunt Chef și Puppet, fiind menținute de o comunitate mare de utilizatori. Ambele sunt scrise în Ruby, având caracteristici similare cum ar fi modularizarea componentelor, pachete pentru instalarea software-ului sau template-uri pentru fișiere personalizate. Ambele sisteme sunt open source cu un model de plata pentru companii. O scurtă trecere în revistă pentru Puppet și Chef este prezentată în tabelul de mai jos.
Provizionare cu Shell în Vagrant este relativ ușoară. Poți scrie comenzi inline sau poți menționa calea spre script-ul shell. Calea poate fi spre un director local sau extern.
Comandă inline
config.vm.provision :shell, :inline => "curl -L https://get.rvm.io | bash -s stable"
Cale fișier local
config.vm.provision :shell, :path => "install-rvm.sh", :args => "stable"
Cale fișier extern
config.vm.provision :shell, :path=>"https://example.com/install-rvm.sh", :args => "stable"
Modulele Puppet pot fi descărcate de pe https://github.com/puppetlabs. Pe disc, un modul este un director care are structura prezentată în Fig. 1 Structura unui Modul Puppet. Programele Puppet se numesc "manifests" și folosesc extensia .pp pentru fișiere.
Manifestspot folosi tipuri variate de logică, cum sunt declarațiile condiționale, colecțiile de resurse, funcții pentru generarea textului, etc.. Dacă nu vrei să setezi manual fișierele manifest, există un instrument foarte simplu de utilizat cu GUI, care poate genera automat toate aceste fișiere. Acest instrument se numește PuPHPet.
Pentru a configura manual Vagrant cu Puppet, trebuie să setezi directivele Puppet după cum urmează:
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "./tools/puppet/manifests/"
puppet.module_path = "./tools/puppet/modules"
puppet.manifest_file = "init.pp"
puppet.options = ['--verbose']
End
unde init.pp este de forma
include mysql::server
class { '::mysql::server':
root_password => 'strongpassword'
}
MySql init.pp, din module/manifests/init.pp
class mysql::server (
$config_file = $mysql::params::config_file,
$manage_config_file = $mysql::params::manage_config_file,
$package_ensure = mysql::params::server_package_ensure,
)
MySql params.pp, din module/manifests/params.pp
class mysql::params {
$manage_config_file = true
$old_root_password = ''
$root_password = "strongpassword"
}
module/manifests/templates
Mysql Template
[client]
password=<%= scope.lookupvar('mysql::root_password') %>
Rețetele Chef Solo pot fi descărcate de pe Opscode. Structura unei rețete Chef este prezentată în Fig. 2. Structura unei Rețete Chef Solo. Pentru adăugarea configurațiilor doar fișierele scrise îngroșat trebuie modificate.
Vagrantfile trebuie modificat după cum este afișat mai jos pentru a folosi Chef Solo ca provizionar.
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "cookbooks"
chef.add_recipe "vagrant_main"
# chef.roles_path = "../my-recipes/roles"
# chef.data_bags_path = "../my- recipes/data_bags"
# chef.add_role "web"
#
# # You may also specify custom JSON attributes:
# chef.json = { :mysql_password => "foo" }
end
unde vagrant_main are următoarea structură:
vagrant_main/recipes/default.rb
include_recipe "apache2"
include_recipe "apache2::mod_rewrite"
package "mysql-server" do
package_name value_for_platform("default" => "mysql-server")
action :install
end
vagrant_main/templates/default.rb
NameVirtualHost *:80
ServerAdmin webmaster@localhost
ServerName cfratila.tsm.com
ServerAlias www.cfratila.tsm.com
DocumentRoot /var/www
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
ErrorLog <%= node[:apache][:log_dir] %>/tsm-error.log
CustomLog <%= node[:apache][:log_dir] %>/tsm-access.log combined
LogLevel warn
Odată ce ai terminat configurarea fișierului Vagrantfile ești gata pentru crearea mașinii virtuale. Pentru acest pas trebuie să deschizi interfața în linia de comandă și să navighezi în folder-ul proiectului, unde ar trebui să fie fișierul Vagrantfile, pentru a sincroniza directoarele. Apoi rulează vagrant up pentru crearea și pornirea mașinii virtuale. Prima dată când vei rula vagrant up va dura puțin mai mult, pentru că Vagrant va descărca box-ul configurat. În exemplul meu, eu nu am adăugat box-ul rulând comanda vagrant box add
D:projects sm> vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Box 'precise32' was not found. Fetching box from specified URL for the provider 'virtualbox'. Note that if the URL does not have a box for this provider, you should interrupt Vagramt now and add the box yourself. Otherwise Vagrant will attempt to download the full box prior to discovering this error.
Downloading box from URL: http://files.vagrantup.com/precise32.box
Progres: 1%
După ce a fost creată mașina virtuală, poți rula comanda vagrant sshpentru accesare. Pentru sistemele de operate Windows poți instala clientul PuTTY SSH, pentru accesarea mașinii virtuale, folosind credențialele de mai jos.
D:projects sm> vagrant ssh
'ssh' executable not found in any directories in the %PATH% variable. Is an SSH client instaled? Try installing Cygwin, MinGW or Git, all of which contain SSH client. Or use the PuTTY SSH client with the following authentication information shown below:
Host: 127.0.0.1
Port: 2222
Username: vagrant
Private key: C:/Users/Carmen/.vagrant.d/insecure_private_key
Dacă ai modificat doar fișierele de provizionare și vrei să testezi rapid, poți rula doar vagrant provision sau vagrant --provision-with x,y,z, unde x,y,z reprezintă provizionarul :shell, de exemplu. Dacă vrei să salvezi statusul mașinii virtuale pentru a nu boot-a de fiecare dată, poți rula vagrant suspend. Cu vagrant resume se rezumă mașina Vagrant care a fost suspendată.
Procesul de lucru cu Vagrant nu este deloc complicat după cum reiese și din Fig.4. Doar rulând comanda vagrant up pe baza fișierului Vagrantfile, a configurațiilor setate pentru provizionar și provider, mașina virtuală este pornită și funcțională.
Docker este un proiect open source folosit pentru ambalarea, tansportarea și rularea oricărei aplicații ca un container. Ideea de bază constă în crearea componentelor per aplicație. Componenta este de fapt un instantaneu al aplicației făcut la un moment dat. Dacă s-au modificat componentele, poți să faci commit la noul status al instantaneului, ceea ce face foarte ușoară procedura de roll back. Acest proiect, care este încă în stadiu de dezvoltare, sună promițător, pentru că nu folosește mașini virtuale cum funcționează Vagrant, ceea ce înseamnă că atât timpul de pornire cât și modalitatea de folosire a resurselor, sunt mai bune.
Comparând metodologia de lucru a celor două instrumente, putem enunța următoarele afirmații:
Eu sunt un developer focusat pe PHP nu administrator de sistem. Vreau să petrec cât mai mult timp codând. Nu vreau să îmi fac griji legate de setarea mediului de lucru sau de setarea mașinilor virtuale. Tot ceea ce vreau este să îmi setez mediul de lucru într-un mod cât mai simplu și cât mai rapid. Vreau să evit situațiile în care mașina mea virtuală crapă, și trebuie să o reconfigurez de la 0. De când folosesc Vagrant, nu îmi mai fac asemenea griji, pentru că există Vagrantfile, care îmi păstrează toate configurările. Sincronizarea directoarelor și redirecționarea traficului prin forwarding port sunt două caracteristici de care sunt foarte mulțumită. Pe când dezvoltam fără a folosi Vagrant, pierdeam mult timp așteptând să se sincronizeze fișierele de pe mașina mea locală, cu cele de pe mașina virtuală. Cu ajutorul directivei "synced folders" pot să lucrez în timp real pe mașina virtuală. În momentul de față, comunitatea de utilizatori Vagrant este în creștere, dar este posibil ca într-un timp relativ scurt, Docker să devină cel mai folosit instrument în comunitatea de dezvoltatori.