iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 14
1
DevOps

CI 從入門到入坑系列 第 14

到處流浪的伺服器

昨天有提到,概念上是要開發人員每次測試的時候都自己建環境。但相信維運人員幫開發人員建一個專用的伺服器後,開發人員可能會為了 compile .Sass 檔,所以裝一個 Ruby + Node ;為了要切換版本,又裝了 rvm 和 nvm ,還裝了 gulp 之類的 global 套件,結果就開不了機了。相信維運人員很難照顧到開發人員求新求變的需求。

「什麼?難道開發人員沒辦法求新求變嗎?」當然可以,正所謂「自己的環境自己管」。環境建在自己電腦上不就好了嗎?

「可是有一堆不一樣的開發環境耶,版本也都不一樣」當然沒問題,現在虛擬化技術已經很成熟了,有很多專案正是做自動化建立客製化的虛擬機,最常見的應該就屬 VagrantDocker 了,這些技術都有著下列特色:

  • 應用隔離: 可以同時執行多個應用
  • 儲存再發佈: 環境資訊可以以檔案的形式傳輸與重現
  • 環境即程式碼: 代表環境資訊可以跟原始碼一起被記錄進版控系統
  • 具備可攜性: 因有上面兩個特性,環境就可以隨時帶著走

這些特色不但可以讓環境資訊輕鬆共享,也讓開發人員能輕鬆建立與管理虛擬機。

Vagrant 基本

Vagrant 安裝需注意它要搭配虛擬化系統,通常是用 VirtualBox 。裝好 VirtualBox 再裝 Vagrant 即可。

Vagrant 操作並不難,首先要先了解它的啟動主要是參考 Vagrantfile 這個檔案,只要跟這個檔案同目錄或是子目錄,都會去認這個檔的設定做操作。那以下是一個練習,先建個子目錄,再初始化 Vagrantfile:

$ mkdir -p /path/to/project
$ cd /path/to/project
$ vagrant init ubuntu/trusty64

這個指令會初始化 Ubuntu Trusty64 的 Vagrantfile 的樣版,裡面有非常多設定的說明可以參考,晚點再來看。先看如何啟動:

$ vagrant up

...

==> default: Mounting shared folders...
    default: /vagrant => /Users/miles/GitHub/MilesChou/book-intro-of-ci

第一次執行會花比較久時間,它會把虛擬機的映像檔載下來並啟動它。訊息裡會看到它有掛載了一個共用資料夾,表示 /Users/miles/GitHub/MilesChou/book-intro-of-ci 的修改,會同步進虛擬機的 /vagrant 。代表主機寫的程式可以靠這個方法連結進虛擬機,或是虛擬機做的 compile 結果可以回傳至主機。

另外可以看到它會開一個 ssh port 供連線,接著我們再下連結指令:

$ vagrant ssh
Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-92-generic x86_64)

...

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

這樣就進去虛擬機了,因為是 ubuntu 所以可以下 apt 指令安裝想要的開發軟體,如 PHP 等,裝完輸入 exit 即可離開。

接著可能會需要關機:

$ vagrant halt

系統玩壞了想砍掉重練:

$ vagrant destroy

如果想重開機或重新載入設定:

$ vagrant reload

Example

以下先來個範例:

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.synced_folder ".", "/vagrant"
  config.vm.network "private_network", ip: "10.10.10.10"
  config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.provision "shell", path: "install.sh"
end

Vagrantfile 是用 Ruby 的語法寫的,會 Ruby 應該不陌生。來看設定的部分在做什麼:

config.vm.synced_folder ".", "/vagrant"

這個就是預設的同步資料夾設定,左邊是 Host 的 Vagrantfile 相對目錄,右邊是 Guest 的絕對目錄,就算沒有這一行 Vagrant 也會幫忙做。

config.vm.network "private_network", ip: "10.10.10.10"

這是指主機限定的網路設定,意思就是 10.10.10.10 只有開 Vagrant 的主機才連得到。通常用 Vagrant 應該用 private_network 居多,畢竟通常主要目的是為了隔離應用

config.vm.network "forwarded_port", guest: 80, host: 8080

偶爾還是會有需求讓其他人能連線進來,這時就可以開 forwarded_port ,上面的設定代表連 Host 8080 port 會轉到 Guest 的 80 port 。因此假設虛擬機裝好 Apache (預設 80 port ),其他人連主機的 8080 就會看到 Apache 的預設首頁。

config.vm.provision "shell", path: "install.sh"

最後這就是關鍵了,當 vagrant up 的時候,預設會啟動 provision ,也就是預置環境。預置的方法有很多,通常我使用的是單純的 shell script ,如同範例這樣。 install.sh 預設會在虛擬機裡以 root 權限執行,範例如下:

#!/bin/bash
########################################
#                                      #
#  Install packages for Ubuntu 14.04   #
#                                      #
########################################

# Setup Timezone
TIMEZONE="Asia/Taipei"

# Setup packages and version
PACKAGES_LIST="
build-essential
curl
git
mariadb-server
nginx
php-pear
php5-cli
php5-curl
php5-dev
php5-fpm
php5-mysqlnd
php5-xdebug
vim
"

PACKAGES=""
for package in $PACKAGES_LIST
do
    PACKAGES="$PACKAGES $package"
done

DEFAULT_SITE="
server {
    listen 80;
    root /vagrant/public;
    index index.html index.htm index.php;
    server_name localhost;
    location / {
        try_files \$uri \$uri/ =404 /index.php\$is_args\$args;
        expires off;
    }
    location ~ \.php\$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)\$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_read_timeout $TIMEOUT;
        fastcgi_index index.php;
        include fastcgi_params;
    }
    location ~ /\.ht {
        deny all;
    }
}
"

# is root?
if [ "`whoami`" != "root" ]; then
    echo "You may use root permission!"
    exit 1
fi

# set time zone
ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime

# update time
ntpdate time.stdtime.gov.tw

# update server
apt-get update
apt-get install python-software-properties

# Add PHP 5.6 PPA
add-apt-repository -y ppa:ondrej/php5-5.6
apt-get update

# set default root password
export DEBIAN_FRONTEND=noninteractive
debconf-set-selections <<< 'mariadb-server-5.5 mysql-server/root_password password password'
debconf-set-selections <<< 'mariadb-server-5.5 mysql-server/root_password_again password password'

# install packages
apt-get install -y $PACKAGES $EXTENSIONS

# set MySQL password and domain
mysql -uroot -ppassword -e 'USE mysql; UPDATE `user` SET `Host`="%" WHERE `User`="root" AND `Host`="localhost"; DELETE FROM `user` WHERE `Host` != "%" AND `User`="root"; FLUSH PRIVILEGES;'
mysql -uroot -ppassword -e 'CREATE DATABASE `default` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;'
mysql -uroot -ppassword -e 'CREATE DATABASE `testing` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;'
# mysql -uroot -ppassword -e "SET PASSWORD = PASSWORD('');"

# modified mysql config
sed -i 's/127\.0\.0\.1/0\.0\.0\.0/g' /etc/mysql/my.cnf

# modified php5-fpm conf
sed -i 's/^listen =.*/listen = \/var\/run\/php5-fpm\.sock/g' /etc/php5/fpm/pool.d/www.conf
sed -i 's/^;listen.owner =/listen.owner =/g' /etc/php5/fpm/pool.d/www.conf
sed -i 's/^;listen.group =/listen.group =/g' /etc/php5/fpm/pool.d/www.conf
sed -i 's/^;listen.mode =/listen.mode =/g' /etc/php5/fpm/pool.d/www.conf
sed -i 's/^;clear_env =/clear_env =/g' /etc/php5/fpm/pool.d/www.conf

# modified php.ini
sed -i "s/^;date.timezone =.*/date.timezone = $TIMEZONE/g" /etc/php5/fpm/php.ini

# install composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

# modified php.ini
sed -i "s/^error_reporting =.*/error_reporting = E_ALL \| E_STRICT/g" /etc/php5/fpm/php.ini
sed -i "s/^display_errors =.*/display_errors = On/g" /etc/php5/fpm/php.ini
sed -i "s/^display_startup_errors =.*/display_startup_errors = On/g" /etc/php5/fpm/php.ini

# modified nginx default site
echo "$DEFAULT_SITE" > "/etc/nginx/sites-available/default"

# restart services
service php5-fpm restart
service nginx restart
service mysql restart

今日回顧

有了自動化建置的工具,開發者就不需要再害怕把伺服器搞壞了,甚至是可以做一些進階的測試。不管怎麼看,對開發人員或維運人員都是有益無害的。

相關連結


上一篇
開發如何考慮維運
下一篇
管理貨櫃的碼頭工人-- Docker ( 1/3 )
系列文
CI 從入門到入坑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
凍仁翔
iT邦新手 3 級 ‧ 2016-12-15 00:36:46

Vagrant!它已經是 DevOps 的必備技能之一了啊!/images/emoticon/emoticon08.gif

Miles iT邦新手 2 級 ‧ 2016-12-15 08:27:48 檢舉

沒錯!我第一次用也是覺得很驚豔!後來大多都用 Docker ,但如果遇到很難用 Docker 的時候,還是會轉回來用 Vagrant ,然後繼續裝 Docker (被揍

凍仁翔 iT邦新手 3 級 ‧ 2016-12-15 14:22:03 檢舉

用 Docker 開發的話,真的會被雷到!XDD

我要留言

立即登入留言