TÌM HIỂU VAGRANT (PHẦN 2) - Vagrant + Chef

Vagrant provisioning

Trong bài viết Tìm hiểu Vagrant Phần 1, chúng ta đã cùng nhau tìm hiểu sơ lược về vagrant, có thể setup 1 máy ảo phục vụ cho phát triển web 1 cách đơn giản với Ubuntu 12.04 LTS và shell provision.

Trước tiên, hãy cùng nhau nhìn lại 2 file config chính là Vagrantfile và setup.sh

Vagrantfile

Vagrant.configure(2) do |config|
 	config.vm.box = "hashicorp/precise32"

setup.sh

# Install PHP
sudo apt-get install -y python-software-properties build-essential
sudo add-apt-repository -y ppa:ondrej/php5
sudo apt-get update
sudo apt-get install -y git-core subversion curl php5-cli php5-curl php5-mcrypt php5-gd

Có 3 vấn đề đặt ra ở đây với provision bằng shell script.

  • Thứ nhất là Vagrantfile viết bằng ruby, còn file setup.sh là shell script. Liệu có cách nào chỉ dùng 1 loại ngôn ngữ cho tất cả ? Đây không phải là hoàn toàn bắt buộc, nhưng rõ ràng provisioning cũng có cấu trúc như Vagrantfile sẽ rất hợp lý.
  • Thứ 2 là có thể thấy việc cài đặt php khá phực tạp, kèm theo đó là khá nhiều module nhưng lại không thể dám chắc như vậy đã đủ chưa, vì điều này phụ thuộc khá nhiều vào kinh nghiệm của người viết file setup.
  • Thứ 3 là dòng setup PHP kia chỉ chạy trên Ubuntu, nếu là CentOS hay Fedora thì chắc chắn không chạy. Vậy nếu spec thay đổi và vagrant box không còn là Ubuntu nữa, chúng ta sẽ phải viết lại file setup.sh? Có khác nào tạo 1 project mới?

Trên đây là 3 vấn đề có thể thấy được thông qua shell provisioning. Đó không phải là các vấn đề quá lớn, nhưng để có thể có được 1 máy ảo được quản lý chặt chẽ, hỗ trợ versioning tốt nhất có thể thì shell không phải là lựa chọn tốt nhất. Thật may là chúng ta có các provisioner.

Có 3 cái tên được đưa ra trên documentation của Vagrant, đó là Ansible, Chef và Puppet. Bài viết này tôi sẽ giới thiệu Chef. Không phải vì Chef có gì hơn kém 2 cái tên còn lại, đơn giản chỉ là 1 lựa chọn, và cái tên nó cũng khá thú vị!

Chef

Chef, bản chất là 1 phần mềm quản lý config cho server. Các config của server được hiểu là "recipes" sẽ được viết dưới dạng Ruby thuần và Domain-specific-language (DSL). Chef vừa có khả năng quản lý thiết lập cho 1 máy cũng như quản lý cho cả 1 hệ thống server của công ty. Chef có thể tích hợp được trong các platform điện toán đám mây như Rackspace, Internap, Amazon EC2, Google Cloud Platform, OpenStack, SoftLayer, and Microsoft Azure để có thể tự động config nhiều server cùng lúc. Tự động chính là từ khóa chính để làm bật lên ưu điểm của Chef.

Tại sao chúng ta dùng Chef?

  • Tính hiệu quả: Config của tất cả server sẽ được lưu tại 1 repository duy nhất
  • Khả năng mở rộng: Bạn chỉ cần tăng số server của mình lên, phân chia chúng theo role và node. Chef sẽ quản lý phần còn lại cho bạn.
  • Tái sử dụng và tiết kiệm: Bạn không cần làm đi làm lại 10 lần việc cài 1 phần mềm, bạn chỉ cần tạo 1 node Chef và phần còn lại sẽ được cài đặt tự động.
  • Tài liệu: Cũng như "clean code" là tại liệu rõ ràng nhất cho dự án của bạn, chef chính là tài liệu cho hệ thống server của bạn, tất cả thông tin về server được lưu ở chef recipes. (Rõ ràng bạn không thể nói shell script là tài liệu được!!!)

Các khái niệm trong chef

  • Chef Client: Command line tool, sử dụng cho việc config server
  • Chef Solo: Phiên bản của Chef Client, config server mà không phụ thuộc vào bất kỳ server nào khác.
  • Node: Host chaỵ Chef Client, có thể là web server, database server hoặc bất kỳ loại server nào.
  • Recipes: 1 file Ruby trong đó có chứa các câu lệnh chạy trên node (nginx ssl module, apache php module).
  • Resources: Resources của node, chưa đựng các files, directories, users và services.
  • Cookbook: Tập hợp các Recipes (nginx cookbook, postgresql cookbook).
  • Role: Config có thể tại sử dụng ở nhiều node (web role, database role,...).
  • Template: 1 file chứa attributes, dùng để tạo ra file config (đây là 1 file erb).
  • Attribute: Biến được truyền trong qua Chef và được sử dụng ở recipes, templates.

Học chef

Bài viết chỉ nhằm mục đích giới thiệu sơ qua về Chef, bạn đọc có hứng thú có thể tìm hiểu thêm trên mạng, bởi để dùng Vagrant với Chef, chúng ta chỉ cần biết đến 1 phần rất nhỏ của Chef, nếu không muốn nói chỉ là khái niệm. Trong bài viết Vagrant is easy - Chef is hard (Part 2), tác giả đã đưa ra nhận định của mình về học chef. Khó! Lý do thì có lẽ chỉnh bởi chef quá mạnh và quá rộng, tài liệu chính thức về học Chef lại khá sơ sài và nhằm đến những phần căn bản nhất khi làm việc với Linux, không hướng đến cái mà web engineer cần. Tuy được coi là "khó", nhưng không phải hoàn toàn là như vậy, chúng ta có thể bắt đầu với từ khóa "Chef Solo", và sau đó có thể tiếp tục enjoy Chef. Bài viết sau đây là 1 tutorial khá hay về Chef Solo. Hy vọng bạn đọc có thể học được từ đây. http://leopard.in.ua/2013/01/04/chef-solo-getting-started-part-1/

Vagrant + Chef

Cách học Chef tốt nhất là có trong tay 1 máy ảo, bởi bạn có thể "thực hành" mà không sợ làm hỏng "máy chủ" của mình.

Sau đây sẽ hướng dẫn provisioning cho vagrant sử dụng Chef.

  1. Config Vagrantfile

    Việc đầu tiên là sửa file Vagrantfile, cho phép thực hiện provisioning bằng Chef, không phải bằng shell như hiện tại.

    Vagrant.configure("2") do |config|
        config.vm.provision "chef_solo" do |chef|
            chef.add_recipe "apache"
        end
    end
Các options của Chef Solo
- **cookbooks_path:** (string hoặc array) Chỉ định nơi lưu cookbooks.
- **data_bags_path:** (string) Nơi lưu data bag. Mặc định thì không có data bag nào hết.
- **environments_path:** (string) Định nghĩa môi trường. Mặc định thì thư mục này không được thiết lập.
- **environment:** (string) Môi trường mà bạn muốn Chef sẽ chạy và là 1 phần của nó.
- **recipe_url:** (string) URL chứa cookbooks
- **roles_path:** Danh sách các paths để định nghĩa routes. Mặc định danh sách này rỗng.
- **synced_folder_type:** Phương thức để sync folder, đảm bảo provisioning hoạt động tốt nhất có thể.
  1. Add cookbooks

    Tiếp theo tạo thư mục lưu Chef cookbooks. Từ root directory của app, bạn tạo 1 thư mục cookbooks, sau đó add recipes theo sơ đồ sau.

    [email protected]:~/study/vagrant-sample$ tree
    .
    ├── cookbooks
    │   └── apache
    │       └── recipes
    │           └── default.rb
    ├── README.md
    ├── Vagrantfile
    └── web
        ├── index.html
        └── phpinfo.php
Recipes và cookbooks có thể là các khái niệm rất mới với người vừa làm quen với Chef. Tuy nhiên điều bạn cần biết hầu như chỉ là khái niệm, bởi có rất nhiều cookbooks của Chef được share trên github. Bạn có thể tìm kiếm và sự dụng thoải mái trong project của mình. Check "siêu thị" để tìm cookbooks mà bạn cần.

https://supermarket.chef.io/

Để sử dụng các shared chef cookbooks, ngoài việc download bằng tay, bạn có thể sử dụng tool có sẵn của chef là knife. 1 cách khác là sử dụng git submodule (rất tiện lợi nếu làm việc với git).

Với Knife
    knife cookbook site install apache2
Với
    git submodule add https://github.com/opscode-cookbooks/apache2.git cookbooks/apache2
Nếu dùng knife thì bạn có thể download cookbook ra 1 thư mục khác project để có thể tái sử dụng cho các trường hợp khác, còn với git submodule thì repository của bạn không bị phình lên, và quản lý tổng thể cũng rất tiện lợi. Tôi thích làm việc với git submodule hơn.
  1. Reload provision

    Bạn có thể load provision đơn giản bằng cách chạy lệnh sau

    vagrant provision

Chef provision vs shell provision

Đến đây bạn đọc đã có được khái niệm cơ bản về sử dụng chef. Và bây giờ chúng ta có thể trả lời các câu hỏi ở đâu bài viết đưa ra.

  • Sự khác biệt giữa shell và ruby: Recipe và các file config khác đều được viết bằng Ruby, do vậy chúng ta sẽ chỉ dùng 1 ngôn ngữ cho project của mình. Thêm vào đó Ruby dễ đọc hơn rất nhiều so với shell script.
  • Liệu có đầy đủ setting chưa: Bằng việc sử dụng các cookbooks được chia sẻ trên mạng và đặc biệt là supermarket của chef, chúng ta có thể yên tâm rằng môi trường làm việc được config bởi những người rất có kinh nghiệm, có lẽ chỉ thừa chứ không thiếu.
  • Làm việc với các hệ điều hành khác nhau: Hãy xem cách mà php cookbook cài đặt memcache cho PHP. https://github.com/opscode-cookbooks/php/blob/master/recipes/module_memcache.rb
case node['platform_family']
    when 'rhel', 'fedora'
        %w{ zlib-devel }.each do |pkg|
            package pkg do
                action :install
            end
        end
        php_pear 'memcache' do
            action :install
            # directives(:shm_size => "128M", :enable_cli => 0)
        end
    when 'debian'
        package 'php5-memcache' do
            action :install
        end
    end

Rõ ràng là có những tính toán cẩn thận cho Linux distribution chúng ta muốn sử dụng. Vì vậy bạn có thể yên tâm kể cả đổi hệ điều hành đi chăng nữa, máy ảo của bạn vẫn được khởi động 1 cách bình thường.

Tổng kết

Trên đây là những suy nghĩ về việc sử dụng Chef trong Vagrant, hy vọng có thể giúp ích phần nào cho bạn đọc hiểu thêm về 1 công cụ cũng như 1 trào lưu mới trong việc setup hệ thống các máy chủ. Bạn đọc quan tâm có thể tham khảo repository sau về sử dụng Chef Solo để cài đặt Apache cho máy ảo. https://github.com/dinhhoanglong91/vagrant_sample/tree/chef_solo

Nếu để ý bạn sẽ thấy số lượng git submodules không dừng lại ở 1 mà là 3, bới Apache2 cần cài đặt phụ thuộc vào các cookbooks khác. Đây cũng là 1 vấn đề khá rắc rối của Chef mà không được đề cập ở bài viết này. Tôi sẽ quay lại trong các bài viết tiếp theo!

Nếu bạn đọc quan tâm có thể tìm hiểu Berkshelf

Tài liệu tham khảo