Vagrant

İçindekiler tablosu yükleniyor...

Not: Vagrant VM kullanıcısı vagrant, parolası vagrant'tır.

Vagrant ne işe yarıyor

Vagrant bir sanal makine yöneticisi. Bilgisayarınızdaki sanal makinelerin oluşturulmasından kurulumuna, çalıştırılmasına ve izlenmesine yönelik kolaylıklar sunuyor. Açık kaynak ve cross-platform (MacOS, Windows, Linux) bir yazılım. Şu anda VMWare, VirtualBox ve AWS (Amazon Web Services) üzerinden oluşturulan VM'leri yönetebiliyorsunuz. Bu ne demek oluyor? Aynı Vagrant konfigürasyonu üzerinden farklı VM'leri çok rahat kullanabiliyorsunuz.

Peki bu bizim gerçek hayatta ne işimize yarayacak? Örnekler ne olabilir?

Öncelikle development kalitesini arttıran bir yönü var. Şirkete ilk başladığınızda projeyi kendi bilgisayarınızda ayağa kaldırmak için ne kadar uğraştınızı hatırlıyor musunuz?

Ya da tüm bu işlemleri staging, test ve production ortamlarına da yapmak yaşlanmanıza neden olabilir. Diyelim ki deployment sürecinize yeni bir ortam ekliyorsunuz (mesela UAT için) ve yeni bir makine, yeni kurulum yapmanız gerekiyor. Uygulamanızın tüm bağımlılıklarının o makineye kurulması gerekiyor. Bu projenizin büyüklüğüne göre bazen bir haftayı bulan süreçlere uzayabilir.

Ancak vagrant'ın belki de en yararlı olduğu konu production ortamındaki hatalarının development'da yakalanabilmesini sağlaması. "Bende çalışıyor" - "Kendi ortamımda reproduce edemedim" gibi iğrenç söylemler tarih oluyor :)

Gereksinimler

Vagrant provider olarak kullanacağı bir VM yöneticisine ihtiyaç duyuyor. Birçok provider desteklendiğini daha önceden söylemiştik. Bu yazı için varsayılan olarak sunulan ve yine açık kaynak ücretsiz VM VirtualBox'ı kullandım. Virtualbox'ı indirmek için: tıklayın.

Vagrant kurulumu

  1. Bir adet vagrant http://www.vagrantup.com/downloads

Box konumunu ayarlamak

Not: Bu anlatım Mac OS X veya Linux için geçerlidir

Vagrant'ın indirdiği box dosyaları default yeri:

~/.vagrant.d/boxes

Çok yer kaplayabileceğinden ötürü bu folder'ı değiştirmek isterseniz favori text editörünüzde .bash_profile dosyanızı açın: (nano yerine vi de kullanabilirsiniz)

1sudo nano ~/.bash_profile

Şu satırı ekleyin:

export VAGRANT_HOME="/<BURAYA ISTEDIGIN FOLDERI YAZ>" Artık indirilip oluşturulan VM dosyaları istediğimiz bir folder altında olacak.

İşletim sistemi kurmak

Harshi Corp.'un Atlas'ı üzerinde birçok Linux seçeneği mevcut tabii ancak Ubuntu aşina olduğum bir dağıtım ve LTE sürümü olduğundan seçiyorum: https://atlas.hashicorp.com/ubuntu/boxes/trusty64

Dökümantasyonunda söylediği şekilde kuruyorum.

1vagrant init ubuntu/trusty64
2vagrant up

init komutu bulunduğumuz yerde bir VagrantFile yaratacaktır. Buradaki bilgilere göre vagrant up dediğimizde kurulum, bu ayarlar üzerinden gerçekleşecek.

up komutuyla birlikte ilgili işletim sistemi dosyası indirilir ve o sanal makine çalıştırılır.

vagrant --help ile yararlı birçok komutu görebilirsiniz.

Box'a bağlanmak

öncelikle kurulu box'ları görmek için: vagrant box list diyoruz.

1ubuntu/trusty64 (virtualbox, 20151020.0.0)

Şimdi de bağlanmak için vagrant ssh diyoruz, bu bizi VagrantFile'daki sisteme bağlayacak.

1vagrant@vagrant-ubuntu-trusty-64:~$

Artık terminal bağlantım değişti, bu ssh ile bağlanabildiğimi gösteriyor.

Gerekliliklerin kurulması

Aşağıdaki gereklilikler tamamen benim bu örnekte anlattığım node.js uygulaması ve onun bağımlılıklarını içerir.

Uygulamamızı çalıştırmak için gerekli araçları kuracağız.

1sudo apt-get -y install git build-essential
2curl --silent --location https://deb.nodesource.com/setup_4.x | sudo bash -
3sudo apt-get install -y nodejs redis-server
4sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
5echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
6sudo apt-get update
7sudo apt-get install -y mongodb-org

Redis ayarlarımızı yapalım: (vi yerine nano da kullanabilirsiniz) Uygulamamızın kullandığı konfigürasyon redis.sh scriptinde bu path kullanılıyor. ~~~ sudo vi /etc/redis/redis.conf ~~~

notify-keyspace-events geçen satırı şu şekilde değiştirelim:

1notify-keyspace-events "Kgs"

Ardından redis'i yeniden başlatalım:

1sudo service redis-server restart

Şimdi de uygulamayı indirip çalıştıralım:

1git clone https://github.com/dhalsim/chatcat.git
2cd chatcat
3git checkout dort
4npm install
5sudo npm install grunt-cli -g

Bu komutların hepsini bir dosyaya kaydediyoruz: provision.sh. Ardınan VagrantFile'ı açıp düzenleme yapıyoruz. Şu şekile getirin:

1 -*- mode: ruby -*-
2
3Vagrant.configure(2) do |config|
4  config.vm.box = "ubuntu/trusty64"
5  config.vm.network "forwarded_port", guest: 3000, host: 8080
6  config.vm.provision :shell, path: "provision.sh"
7end

ssh'tan exit ile çıkıyoruz:

1vagrant reload --provision

Böylece vagrant, VM'i kapatacak, tekrar açacak ve verdiğimiz provision.sh dosyasından kurulum yapacak

Vagrant senkronizasyon

Vagrant VM'ler üzerinde geliştirme yapmak özellikle grafik arabirimi olmadığından çok zor olabilir. terminal programlarıyla çok içli dışlı değilseniz, host makinenizdeki uygulamalarınızı kullanmak istiyorsanız, vagrant VM guest makineniz ile host makineniz arasında ortak senkronize dosyaları kullanabilirsiniz. Data transferi açısından da faydalıdır.

Burada Mac OSX host makinesi ve VirtualBox ubuntu guest makinesi arasındaki kullanımı anlatacağım. Sizde farklı bir kombinasyon varsa ve bunlar işe yaramazsa ayrıntılı bilgi vagrant dökümantasyonu'nda.

Şimdi VagrantFile'ı değiştirelim:

1Vagrant.configure(2) do |config|
2  config.vm.box = "ubuntu/trusty64"
3  config.vm.network "forwarded_port", guest: 3000, host: 8080
4  config.vm.provision :shell, path: "provision.sh"
5  config.vm.synced_folder "~/Projects/chatcat", "/home/vagrant/chatcat"
6end
  • config.vm.synced_folder komutunu ekledik
  • ilk parametredeki path, host makinedeki
  • ikinci parametredeki path, guest makinesindeki yeri belirtiyor
1vagrant reload
2vagrant ssh

ile kontrol ediyoruz. Artık host makinemizde istediğimiz editör/IDE ile bir dosya değiştirdiğimizde otomatik olarak o dosya Vagrant tarafından guest makineye senkron edilecek.

Port Forwarding

Port forwarding, vagrant box'da çalışan bir portu benim bilgisayarımın başka bir portuna yönlendirmek/bağlamak anlamına geliyor.

1config.vm.network "forwarded_port", guest: 3000, host: 3000

Artık VM'in 3000 portu, bizim bilgisayarımızın 3000 portuna yönlenmekte.

Kendi bilgisayarınızda http://localhost:3000'den uygulamamızı deneyebiliriz. Afiyet olsun :)

Private Network

Vagrant sanal makinelerinizin bir private network altında birbirleriyle haberleşebilmelerini sağlayabilirsiniz. Bunun için yapmanız gereken:

1config.vm.network "private_network", ip: "192.168.1.20"

Bu yöntemle port forwarding yapmamıza gerek kalmıyor. O satırı silip localhost yerine http://192.168.1.20:3000 üzerinden de uygulamayı çalıştırabilirsiniz.

Guest OS (konuk işletim sistemi) için bir IP tanımlamak. Ayrıca VM'inizin Host OS (yönetici işletim sistemi) DNS'ini veya başka bir DNS server'ını kullanmasını sağlayabilirsiniz.

VirtualBox için bu şu komutla yapılabiliyor: (VM'in kapalı olduğundan emin olun: vagrant halt)

1VBoxManage list vms  --> VM listesinden ismi alıp aşağıya yazın
2VBoxManage modifyvm "VM İSMİNİZİ BURAYA YAZIN" --natdnshostresolver1 on

Eğer sürekli IP hatırlamakla uğraşmak istemiyorsanız hosts dosyasına anlamlı isimler verebilirsiniz. Mac OSX için dosyayı değiştirelim (vi yerine nano da kullanabilirsiniz)

1sudo vi /private/etc/hosts  

En alt satıra 192.168.1.20 nodeapp.com ekleyip kaydedin. Daha sonra http://nodeapp.com:3000 şeklinde o vagrant üzerindeki node.js uygulamamıza erişebileceğiz. Üstelik eğer diğer VM'lerde de VBoxManage ile yaptığımızı yaparsak, aynı network ve DNS ayarları üzerinden onlar da erişebilirler. Bundan sonraki anlatımlarda nodeapp.com üzerinden gideceğim.

Bu yaptığımız değişiklik facebook login işlemlerinde ve socket işlemlerinde probleme yol açacak. Facebook application ayarlarından localhost geçen yerleri nodeapp.com ile değiştirmemiz gerekiyor. Bunlar config/commons.js'te socket_host değişkeli ve test.json'da değiştireceğimiz callbackURL değişkenidir. Yapılması gerekenler:

  1. http://developers.facebook.com üzerinden uygulamamızın ayarlarını değiştirmeliyiz. Benim önerim Test Apps üzerinden yeni bir test uygulaması yaratıp, Site URL'i http://nodeapp.com:3000/ şeklinde ayarlamanız. Bu durumda test.json'a yeni AppID ve AppSecret değişkenlerini güncellemeyi unutmayın
  2. config/index.js'te daha önceden farketmediğim bir durum var. Onu düzelteceğiz. Normalde yapılması gereken, ortak ayarların ezilmesini sağlamaktır. commons ve environmentConfig yer değiştirecek:

    1module.exports = require('src/lib/utils').extend(commons, environmentConfig);
    
  3. test.json'a commons.json'daki socket_host'u ezebilmek için şunu ekliyoruz:

    1...
    2"socket_host": "http://nodeapp.com:3000",
    3...
    

Bu en çok VM'leriniz arasında iletişim kurmak istediğinizde -ki bunu isteyeceksiniz- IP'ler yerine FQDN'lerle (nodeapp.com gibi) yapabilmenizi sağlayacak.

Uygulamayı servis olarak çalıştırmak

Şimdiye kadar Vagrant üzerinden node.js uygulamamızı Ubuntu/Linux'a kurulumunu ve çalıştırılmasını anlattım. Şimdi ise uygulamamızın yönetimini ve izlenmesini sağlayacak PM2 ismindeki aracın kullanımını göreceğiz. Üstelik PM2 ile uygulamanın crash olması durumunda yeniden başlatılmasını da sağlayacağız. Ayrınca herhangi bir VM restart durumunda da uygulamanın servis olarak otomatik çalışmasını sağlayacağız.

Uygulamamızı VM'i başlattığımızda otomatik başlaması için ayarlamamız gerekiyor. Bu aynı zamanda VM'in yeniden başlamalarında da gerekli olacaktır.

PM2'yi kuruyoruz:

1sudo npm install -g pm2

PM2'nun karışık komutlarında bize bir nebze olsun yardımcı olacak komut tamamlama için:

1pm2 completion install

Bulunduğunuz terminalde işe yaraması için gerekli komut, olmuyorsa terminal penceresini/tabını kapatıp açabilirsiniz de:

1source ~/.bashrc

NOT: pm2 aslında bizim işimize yarayacak birçok özelliğe sahip ancak bu yazının konusunu aştığından buna başka bir yazıda değineceğim. Siz isterseniz araştırabilirsiniz, faydalıdır. http://pm2.keymetrics.io/docs/usage/pm2-doc-single-page/

Servis ayarlarına girmeden önce grunt tarafında değişiklikler yapacağız. Şimdiye kadar uygulamamız dev modunda çalışıyordu. VM için test modunu kullanmaya karar verdim. Siz kafanıza göre ayarlayabilirsiniz. Bana göre servis olarak çalıştırırken de redis, mongo gibi kullanılan tüm program ve ayarlar en rahat yine grunt ile ayarlanabiliyor, ancak bu sefer development için kullandığımız watch, nodemon gibi araçlar yerine pm2 kullanacağız. Uzatmadan yapmamız gerekenlere geçersek:

Spoiler: Programın vagrant için hazır halini git checkout bes diyerek kullanabilirsiniz. O durumda aşağıda yapılan değişikliklerden bazılarına gerek kalmayacak.

  1. dev.json dosyasının içeriğini test.json dosyasına kopyalayın. Kolaylık olması açısından VM üzerinde de cloud yerine aynı makinedeki servis olarak çalışan redis, mongo kullanılacak.
  2. service --status-all ile redis, mongo servislerinin çalıştığından emin olun
  3. console'dan NODE_ENV=test pm2 start app.js ile test edin.
  4. çalışıyorsa pm2 kill ile kapatın
  5. startup.sh adında yeni bir dosya ekliyoruz. Bu dosya bizim oluşturacağımız servis'in çalışmasını, durdurulmasını vs. sağlayacak. Kontrol edilmesi gereken yerler NAME, PM2, USER, APP_HOME gibi değişkenler. Mesela user'ın whoami ile kontrolünü yapabilirsiniz. which pm2 diyerek pm2'nun asıl yerini öğrenebilirsiniz.

     1#!/bin/bash
     2 chkconfig: 2345 98 02
     3#
     4 description: our chatcat node app startup script
     5 processname: chatcat
     6#
     7## BEGIN INIT INFO
     8 Provides:
     9 Required-Start: $local_fs $remote_fs
    10 Required-Stop: $local_fs $remote_fs
    11 Should-Start: $network
    12 Should-Stop: $network
    13 Default-Start:        2 3 4 5
    14 Default-Stop:         0 1 6
    15 Short-Description: chatcat
    16 Description: chatcat node app is started
    17## END INIT INFO
    18
    19NAME=chatcat
    20PM2=/usr/bin/pm2
    21USER=vagrant
    22APP_HOME="/home/vagrant/chatcat"
    23
    24export NODE_ENV="test"
    25
    26get_user_shell() {
    27    local shell=$(getent passwd ${1:-`whoami`} | cut -d: -f7 | sed -e 's/[[:space:]]*$//')
    28
    29    if [[ $shell == *"/sbin/nologin" ]] || [[ $shell == "/bin/false" ]] || [[ -z "$shell" ]];
    30    then
    31      shell="/bin/bash"
    32    fi
    33
    34    echo "$shell"
    35}
    36
    37super() {
    38    local shell=$(get_user_shell $USER)
    39    su - $USER -s $shell -c "NODE_ENV=$NODE_ENV $*"
    40}
    41
    42start() {
    43    echo "Starting $NAME"
    44    super $PM2 start $APP_HOME/app.js
    45}
    46
    47stop() {
    48    super $PM2 dump
    49    super $PM2 delete all
    50    super $PM2 kill
    51}
    52
    53restart() {
    54    echo "Restarting $NAME"
    55    stop
    56    start
    57}
    58
    59reload() {
    60    echo "Reloading $NAME"
    61    super $PM2 reload all
    62}
    63
    64status() {
    65    echo "Status for $NAME:"
    66    super $PM2 list
    67    RETVAL=$?
    68}
    69
    70case "$1" in
    71    start)
    72        start
    73        ;;
    74    stop)
    75        stop
    76        ;;
    77    status)
    78        status
    79        ;;
    80    restart)
    81        restart
    82        ;;
    83    reload)
    84        reload
    85        ;;
    86    force-reload)
    87        reload
    88        ;;
    89    *)
    90        echo "Usage: {start|stop|status|restart|reload|force-reload}"
    91        exit 1
    92        ;;
    93esac
    94exit $RETVAL
    
  6. sudo cp startup.sh /etc/init.d/nodeapp ile dosyayı servislerin çalıştırıldığı path'e kopyalayın

  7. sudo chmod a+x /etc/init.d/nodeapp ile dosyaya çalıştırma izni verin

  8. sudo service nodeapp start ile servisi başlatın. Denemek için sudo /etc/init.d/nodeapp start da diyebilirsiniz.

  9. pm2 list ile uygulamanın başlayıp başlamadığına emin olun

  10. sudo service nodeapp stop uygulamayı durdurun. pm2 list ile çalışan uygulama olmadığına emin olun. ps aux | grep node ile node.js'in çalışmadığını görün.

  11. Her şey OK ise servisi başlangıçta çalışması için şu komutu girelim: sudo update-rc.d nodeapp defaults

    Not: Tüm bunları denerken bir problemle karşılaşırsanız basitten karmaşığa doğru ilerleyin. Önce startup.sh çalışıyor mu. Daha sonra da service çalışıyor mu diye bakabilirsiniz.

  12. Ayrıca provision.sh dosyasında da değişiklik yapmamız gerekiyor:

 1...
 2git clone https://github.com/dhalsim/chatcat.git
 3cd chatcat
 4git checkout bes
 5npm install
 6sudo npm install grunt-cli -g
 7sudo npm install -g pm2
 8sudo cp startup.sh /etc/init.d/nodeapp
 9sudo chmod a+x /etc/init.d/nodeapp
10sudo update-rc.d nodeapp defaults

Şimdilik bu kadar. Vagrant kullanması gerçekten hoş bir ortam sunmuş. Ancak Linux ile çok alakadar olmayan gençlerimiz yabancılık çekiyor olabilir. Linux ile ilgili tonlarca kaynak bulabilirsiniz. Biraz bakmanızda fayda var. Takıldığınız yerlerde yorumlara yazarsanız oradan da yardımcı olmaya çalışırım.

Bir sonraki yazımda uygulamamızı Vagrant üzerinden clustured şekilde nasıl çalıştıracağımızı ve böyle durumunlarda loglama nasıl yönetilir bunun üzerinde duracağım. Loglama açısından çok sağlam bir yazı bizi bekliyor :)


Published: November 14 2015

blog comments powered by Disqus