Tạo môi trường dev thông minh bằng virtual machine

Setup environment trên máy tính để dev là công việc bắt buộc phải làm ngay khi bước vào triển khai dự án. Websites và webapps ngày nay thường được build dưới hình thức của những tổ hợp công nghệ, kết nối nhiều nguồn tài nguyên lại với nhau, khiến cho vấn đề setup environment và đồng bộ hóa các environments giữa máy chủ production và máy chủ dev, cũng như giữa các máy dev với nhau trở nên khó khăn hơn.

Có rất nhiều tổ hợp công nghệ, chẳng hạn MEAN stack là tổ hợp MongoDB, ExpressJS, AngularJS và Node.js - chúng đi với nhau và bạn phải hiểu cả 4 thứ để kiểm soát được chúng. Hay như tổ hợp LAMP kinh điển (Linux – Apache – MySQL – Perl/PHP) dù đã trải qua hàng chục năm nhưng vẫn được sử dụng mỗi ngày. Với xu hướng cloud computing hiện nay,  mọi việc không dừng ở đó. Nhiều công nghệ mới cũ được tổ hợp lại với nhau theo những cách thức vô cùng phức tạp, khó mà nắm bắt. Bằng cách kết hợp một số trong những cái tên dưới đây, người ta có thể tạo ra vô vàn kiến trúc:

  • Cloud computing: Amazon, Azure, Rackspace...
  • OS platform: RedHad, Ubuntu Server, CentOS...
  • Web server: Apache, nginx, Tornado, Node.js...
  • Database: MariaDB, MongoDB, CouchDB, Neo4j…
  • Mail server: Dovecot, Axigen, deepOfix...
  • Background processing: Gearman, RabbitMQ, Beanstalkd...
  • PubSub: Redis, Parse...
  • Search engine: Elasticsearch, Sphinx, Solr...
  • Caching: Varnish, Memcached, APC / OpCache....
  • Monitoring: Nagios, SolarWinds, OpManager...

Một hệ thống web có thể bao gồm nhiều thành phần, phân tán ra nhiều đám mây, chạy trên nhiều OS, sử dụng nhiều loại databases,  web servers và áp dụng nhiều kiểu caching. Developers lần đầu tiếp cận một tổ hợp công nghệ có thể phải mất hàng tuần để setup environment mà chưa chắc đã thành công.


May mắn thay, chúng ta có thể giải quyết tất cả những điều đó bằng một concept: "virtualization".

Đã đến lúc nói tạm biệt với localhost!

Mở file cấu hình database connection trong dự án mới nhất của bạn, nếu có chữ "localhost" đâu đó thì hãy cẩn thận: có thể bạn vẫn chưa sẵn sàng cho sân chơi cloud computing, clustering và cross-platform. Nó cũng giống như một web developer sau 3 năm làm việc với PHP/MySQL mà vẫn dùng XAMP vậy. Nó có nghĩa là bạn đang chạy tất cả các services trên cùng một máy. Nó có nghĩa là ứng dụng của bạn đang vận hành trên một hệ sinh thái không giống chút nào với thực tế ngoài kia.

Không có 2 hệ thống hoàn toàn giống nhau. Developer phải có khả năng thiết kế environment đặc thù cho từng hệ thống, và phải tìm cách tách biệt các dịch vụ khác nhau ra các servers khác nhau. Đó là khu biệt hóa chức năng để tối ưu hóa performance. Ít nhất cũng nên để ứng dụng web ở máy chủ dịch vụ web, còn database ở trên server chuyên về lưu trữ. Tại vì:

- Nếu server chỉ cung cấp một service duy nhất, bạn có thể yên tâm áp dụng cấu hình tốt nhất cho riêng service đó.
- Dễ dàng thực thi các thao tác backup, replicate... trên máy chủ database, cũng như  scaling máy chủ ứng dụng web.

Cấu hình database connection nên có những IP addresses thay vì  chỉ "localhost" hay "127.0.0.1".

Để làm điều đó thì bạn không nên install mọi thứ đồ nghề lên PC một cách trực tiếp, mà hãy tạo ra các máy ảo và cài đặt tools trên máy ảo.

Virtualize it! Hãy ảo hóa môi trường dev của bạn!

SSH to virtual web server.png
Figure 1 : Kết nối vào máy ảo bằng Terminal

Điều này giúp bạn:

  • giữ cho máy tính luôn sạch sẽ: vì mọi thứ chỉ hoạt động trong sandbox. Tắt máy ảo là xong. Đặc biệt nếu là máy tính riêng, chắc hẳn bạn không muốn tốn resource để giữ nginx và mongodb chạy trong khi đang xem YouTube.
  • dễ dàng thay đổi môi trường dev: bạn có thể dev 1 dự án đang chạy CentOS và 1 dự án khác dùng Windows Server mà không cần rời xa giao diện Mac OS và các software quen thuộc.
  • thao tác với máy ảo ở local cũng giống như với các máy ảo trên AWS, Azure, WebFaction... Bạn sẽ không phải lúng túng khi được quăng cho 1 cái EC2 instance mới. Xem các hình Figure 1 và Figure 2, hệ thống server trên EC2 được tái hiện trong hệ thống server ảo tại local.
  • có thể tạo ra hệ thống nhiều server với cấu hình và limit như trong thực tế. Ví dụ website của bạn dùng 3 con EC2 trong đó có 1 con m3.xLarge và 2 con  m3.medium, bạn có thể tạo ra 3 máy ảo và set RAM, storage… y như vậy để test performance và khả năng đáp ứng.
  • và đây là điều quan trọng nhất: bạn có thể clone máy ảo ra cho nhiều người khác cùng sử dụng. Mọi thứ đều consistent, không chút nào khác biệt.

Có nhiều công cụ giúp bạn tạo máy ảo, như VMware, VirtualBox, OpenVZ, Xen... ở đây chủ yếu nhắc đến VirtualBox, vì công cụ này chạy được trên cả Windows, Mac và Linux. Về cách cài đặt và sử dụng VirtualBox, các bạn có thể tham khảo chi tiết tại link dưới:


AWS EC2 instances.png
Figure 2 : Các instances trên AWS EC2


Nhưng trước hết hãy ghi nhớ một số khái niệm cần thiết khi làm việc với các công cụ ảo hóa.

Các concepts trong visualizing

  • PM (physical machine) : máy tính vật lý của bạn
  • VM (virtual machine) : máy ảo được tạo ra bên trong PMs, cô lập với môi trường của PMs
  • Host (host OS) : là hệ điều hành gốc trên PM.
  • Guest (guest OS) : hệ điều hành chạy trong VM.
  • Guest Additions : phần mở rộng chức năng cho guest giống như drivers trên host.
  • Shared folders : các thư mục dùng chung giữa host và guest. Đây là khái niệm đặc biệt quan trọng, nhờ nó, bạn có thể lưu trữ, chỉnh sửa source code bằng IDE quen thuộc trên host OS, và run chúng trên guest OS. Chỉ có thể dùng Shared folders sau khi đã cài đặt Guest Additions cho VM.

Sau đây, tôi đề cập một số bước nên làm khi ảo hóa môi trường dev.


Những điều nên làm với visualizing

1, Tạo sẵn một bộ core

Cài đặt một server lên máy ảo hoàn toàn giống như cài đặt trên máy vật lý. Bạn vẫn mất chừng đó thời gian để điền các thông tin và chờ đợi quá trình sao chép hệ điều hành lên hard disk hoàn tất. Vì vậy, bạn nên setup các bộ core trước. Đó là các máy ảo cài đặt sẵn Ubuntu Server, RedHad, CentOS... và chỉ có duy nhất hệ điều hành, không chứa gì khác.

Bạn có thể chạy các lệnh update và upgrade lên version mới nhất, rồi install thêm 2 thứ: gitopenssh-server. Git là công cụ phải có để quản lý source code. OpenSSH-Server cho phép bạn login vào máy ảo này qua ssh. Dùng ssh trên cửa sổ terminal riêng tiện hơn là thao tác qua giao diện QEMU mặc định của máy ảo.

Kế đó, bạn dùng chức năng export của VirtualBox để xuất ra các file nén OVA.  Từ các files nén này, bạn có thể import trở lại VirtualBox để tạo ra các máy ảo mới.

Tới đây, bạn đã có những server "ready-to-use". Chúng có thể bao gồm Ubuntu-core, RedHad-core, CentOS-core... Từ các bản standard này, bạn có thể phát triển theo nhiều nhánh: máy chủ dữ liệu, máy chủ web, file server, etc.

2, Tạo ra các máy ảo chuyên dụng

Giả sử bạn đi theo dòng Ubuntu, trước hết, bạn cần đem phiên bản Ubuntu-core import vào VirtualBox, đặt tên máy ảo mới là WebServer rồi login vào. Ở trong máy ảo WebServer này, bạn cài đặt nginx cho lắng nghe cổng 80, cài thêm Apache cho lắng nghe cổng 8080, cài Node.js, PhantomJS, và các đồ nghề cần thiết cho máy chủ web. Sau khi hoàn tất mọi thứ, đừng vội sử dụng mà hãy export ra một file OVA để tiện dùng lại sau này.

Tương tự, cũng dùng Ubuntu-core để tạo ra 1 máy ảo khác gọi là DbServer chẳng hạn. Login vào máy này và install MongoDB, MariaDB... sau đó, cũng export ra một file OVA trước khi sử dụng.

Tới đây, bạn đã có 3 files: Ubuntu-core.ova, WebServer.ova, và DbServer.ova. Thậm chí bạn có thể build sẵn những máy ảo chuyên biệt hơn, chẳng hạn MongoDB.ova, Neo4j.ova, nginx.ova, ApacheTomcat.ova, etc. Không có giới hạn nào cho khả năng sáng tạo của bạn. Mục tiêu duy nhất là làm cho việc setup môi trường trở nên nhanh chóng và hoàn hảo.

OVA files.png
Figure 3 : My .OVA files

Bất kể ở thời điểm nào bạn cũng có thể dùng lại chúng để tạo ra máy chủ cần thiết trong vài phút. Nếu một team khác cũng cần dùng Neo4j, bạn chỉ việc share file Neo4j.ova để họ tự tạo ra máy ảo sẵn có Neo4j.  Không cần phải làm gì thêm nữa! Một team khác cần máy chủ chạy Node.js 0.10.35, có Redis để chạy PubSub. OK. Bạn chỉ việc import WebServer.ova, tạo máy ảo mới, login vào, thêm 1 phút để install redis-server. Xong export ra thành NodeRedis.ova đưa cho họ sử dụng. Chưa bao giờ công việc trở nên dễ dàng hơn thế! Giả như họ cài đặt linh tinh làm server lỗi cũng không sao, cứ remove VM đó đi và import lại NodeRedis.ova trên  một VM mới là được.


4. Dùng static IP

Các máy ảo nên được cấu hình sử dụng static IP để tránh phải điều chỉnh file hosts nhiều lần. Để biết IP hiện tại của máy ảo, bạn login vào guest và gõ lệnh ifconfig.

Thiết lập static IP bằng cách chỉnh sửa file /etc/network/interfaces. Ví dụ sau dùng nano:

~ $ sudo nano /etc/network/interfaces

Đây là một file mẫu chuẩn (thay X bằng 1 số bất kỳ, chú ý conflict):

/////////////////////////////////////////////////////////////////////
GNU nano 2.2.6         File: /etc/network/interfaces

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
address 192.168.1.5
gateway 192.168.1.1
netmask 255.255.255.0
broadcast 192.168.1.255
# Using wifi
# wpa-ssid
WIFI_NAME
# wpa-psk PASSWORK_WIFI_HERE
# Set DNS
# dns-nameservers 8.8.8.8 8.8.4.4
/////////////////////////////////////////////////////////////////////

Sau khi khởi động lại VM, bạn có thể connect đến guest OS này bằng SSH từ trên host OS:

~ $ ssh root@192.168.1.x


Tham khảo thêm cơ chế networking của VirtualBox:



5. Mouting và Symlink

Để chạy source code của 1 website trên máy ảo, bạn nên mount thư mục chia sẻ vào một nơi cố định, chẳng hạn: /var/www/shared

Nếu mounting thành công, bạn có thể thấy các thư mục web xuất hiện trong location này.

Sau đó, bạn sẽ cấu hình server point tới đây như khi làm trên máy thực.

Bạn cần để cho server script chạy trong guest OS có thể sửa đổi files/folders ở host OS (nằm dưới shared folder). Lệnh sau giúp mounting chính xác trên VM chạy Linux:

~ $ sudo mount -t vboxsf -o uid=1000,gid=1000 SHARED_FOLDER /MOUNT_PATH


Một vấn đề thường gặp khác là symlink. VirtualBox không cho phép dùng symlink trong guest. Nếu bạn thực sự cần dùng symlink, hãy tham khảo:


Một số module Node.js tự động thiết lập symlink khi install. Điều này có thể gây ra lỗi. Tuy nhiên Node.js cung cấp tùy chọn -no-bind-links để ngăn chặn việc tạo symlinks:

~ $ sudo npm install --no-bind-links


Tham khảo:



6. Máy vật lý cũng nên có cấu trúc phù hợp

Một khi đã áp dụng hệ thống máy ảo cho môi trường dev, vai trò của máy thực sẽ ít quan trọng hơn. Bạn có thể làm việc trên Windows, Linux hay Mac OS X tùy ý. Dù sao máy tính cho developer nên là multi boot chứa ít nhất 1 Windows và 1 Linux, có phân vùng chung giữa các OS này.

Nhiều máy hiện nay vẫn áp dụng cách chia phân vùng ổ cứng truyền thống, thời Windows XP. Tôi nhớ là dạo đó người ta hay chia ổ cứng thành 4 phần :

  • C: System chứa file hệ thống
  • D: Data chứa dữ liệu công việc
  • E: Entertainment chứa phim ảnh, game, nhạc…

Developer phần mềm thì không nên làm như vậy. Theo kinh nghiệm của tôi, với 1 ổ cứng bất kỳ, chúng ta nên phân chia như sau:

  • Partition 1 (30% dung lượng): Windows OS, 7 hay 8 tùy cấu hình máy
  • Partition 2 (30% dung lượng): Linux, Ubuntu hoặc Linux Mint
  • Partition 3 (38% dung lượng): Storage, FAT32, chứa dữ liệu mà cả Windows và Linux có thể truy cập. Các files OVAs, source code, libraries/packages… hãy để  ở đây.
  • 2% dung lượng còn lại dùng cho hệ thống, như swap, EFI, etc.

Tôi không rõ Norton Ghost có thể tạo ra các bản ghost multi boot như: Win7-Mint, Win8-Ubuntu, Win8-Mint-Solaris, etc… hay không. Nếu được vậy thì quá tốt!


Kết luận

Trên đây là những định hướng trong việc áp dụng công nghệ máy ảo để tạo ra môi trường dev thông minh, linh hoạt, nhằm cải thiện hiệu suất công việc và nâng cao năng lực thiết kế, kiểm soát, vận hành hệ thống máy tính, máy chủ. Mức độ áp dụng vào thực tiễn như thế nào đòi hỏi sự mạnh dạn thay đổi nhận thức cũng như thói quen ở mỗi developer và những người quản lý.