Hướng dẫn sử dụng Chef

Trong loạt bài về Vagrant trên Viblo (link 1, link2), chúng ta đã tìm hiểu những khái niệm cơ bản về Chef, cũng như sử dụng các cookbook có sẵn trên mạng để tự động cài các package cần thiết. Trong bài viết này, mình sẽ giúp các bạn hiểu hơn về Chef để có thể tự tạo một cookbook cho riêng mình.

Chef là gì ?

Một công việc bạn thường xuyên phải làm khi tham gia một dự án web là cài đặt môi trường. Thông thường chúng ta sẽ phải cài đặt môi trường phát triển local sao cho giống nhất với môi trường production trên server để tránh các lỗi phát sinh vì vấn đề không tương thích. Cách làm truyền thống là chúng ta sẽ duy trì một danh sách các phần mềm và phiên bản cần thiết và yêu cầu local cài theo danh sách này. Tuy nhiên, mọi chuyện sẽ trở nên rất phức tạp và mất thời gian nếu có quá nhiều phần mềm cần cài đặt cũng như mỗi lần cần nâng cấp cũng phải yêu cầu tất cả các máy local nâng cấp theo.

Và vấn đề bên trên có thể được giải quyết một cách dễ dàng bằng Chef, một công cụ quản lí các thiết lập cho server. Chúng ta dùng Chef để định nghĩa xem server cần phải cài đặt những package gì, config những file gì, chạy những service gì, v.v và sau đó chạy những cài đặt này một cách tự động lên tất cả những máy mà chúng ta cần.

Ý tưởng về Chef giống như về một người đầu bếp. Bạn viết ra một quyển sách nấu ăn (cookboook) trong đó có nhiều công thức (recipes) và anh ta sẽ nấu tất cả các món đó theo đúng công thức mà bạn đã yêu cầu.

Làm việc với file

Để bắt đầu tìm hiểu về Chef, chúng ta bắt đầu với một ví dụ đơn giản nhất: yêu cầu Chef tạo một file helloworld.txt có nội dung "Hello World"

Khởi tạo thư mục làm việc. Thư mục thường được đặt tên là chef-repo.

mkdir ~/chef-repo
cd ~/chef-repo

Từ thư mục ~/chef-repo, chúng ta tạo file hello.rb và lưu nó lại. (Lưu ý là Chef sử dụng Ruby)

file 'helloworld.txt' do
  content 'hello world'
end

Tiếp đó từ Terminal, chúng ta chạy chef-apply để chạy những gì mà bạn đã viết.

chef-apply hello.rb

Output:

Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * file[helloworld.txt] action create
    - create new file helloworld.txt
    - update content in file helloworld.txt from none to b94d27
        --- helloworld.txt	2015-07-27 12:54:24.731552226 +0900
        +++ /tmp/.helloworld.txt20150727-12861-1ys9rsb	2015-07-27 12:54:24.732552231 +0900
        @@ -0,0 +1 @@
        +hello world

Bây giờ chúng ta thử chạy lại chef-apply lần nữa xem sao.

chef-apply hello.rb

Output:

Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * file[helloworld.txt] action create (up to date)

Chúng ta thấy rằng Chef không tạo lại hay thay đổi file hello.rb bởi vì nó nhận thấy file hello.rb đã tồn tại và có nội dung giống như nội dung mong muốn. Điều này cũng đúng với các tài nguyên khác. Ví dụ, nếu bạn chạy chef để cài 1 package rồi, lần sau bạn chạy lại chef thì package đó sẽ không cần cài đặt lại nữa. Đây là một điểm rất hay của Chef.

Giờ chúng ta thay đổi hello.rb, đổi nội dung từ hello world sang hello chef

file 'helloworld.txt' do
  content 'hello chef'
end

Chạy lại chef-apply

chef-apply hello.rb

Output

* file[helloworld.txt] action create
  - update content in file helloworld.txt from b94d27 to c38c60
      --- helloworld.txt	2015-07-27 12:54:24.732552231 +0900
      +++ /tmp/.helloworld.txt20150728-10061-swxmd7	2015-07-28 16:32:37.802320744 +0900
      @@ -1 +1 @@
      -hello world
      +hello chef

Lần này thì Chef thay đổi nội dung file helloworld.txt bởi vì chúng ta đã thay đổi công thức, và Chef đã cập nhật lại file để đúng với công thức đã đặt ra.

Chúng ta cũng có thể xoá file bằng Chef. Tạo file remove_hello.rb

file 'helloworld.txt' do
  action :delete
end
chef-apply remove_hello.rb

Dùng Chef để cài đặt package và service

Một trong những tác vụ hay được làm nhất đó là cài đặt các package. Trong bài viết này mình sẽ hướng dẫn các bạn cài Apache bằng Chef.

Chúng ta hãy tạo ra file webserver.rb với nội dung như sau:

package 'httpd' do
  action :install
end

Chạy chef-apply webserver.rb. Output:

Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * package[httpd] action install
    - install version 2.2.15-31.el6.centos of package httpd

Chúng ta chạy lại lần nữa chef-apply webserver.rb. Output:

Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * package[httpd] action install (up to date)

Lần này thì httpd không được cài nữa vì đã được cài trước đó.

Để kích hoạt và chạy service Apache, chúng ta thêm đoạn sau vào cuối file webserver.rb:

service 'httpd' do
  action [:enable, :start]
end

Sau khi cài và khởi động Apache thành công, chúng ta sẽ đặt trang chủ cho nó. Trang chủ mặc định của Apache có path là ``/var/www/html/index.html. Vận dụng kiến thức đã được học ở phần trước, chúng ta sẽ tạo một file index có nội dung Hello World bằng cách thêm đoạn sau vào cuối filewebserver.rb`

file '/var/www/html/index.html' do
  content '<html>
  <body>
    <h1>hello world</h1>
  </body>
</html>'
end

Vậy là xong, bây giờ hãy chạy chef-apply và bạn sẽ có một webserver Apache cùng một trang chủ theo đúng ý của mình.

Cookbook, recipe và template

Theo ví dụ ở phần trước, chúng ta đã thiết lập một web server và đặt trang chủ cho nó. Tuy nhiên, có một vấn đề là code HTML của trang chủ bị nhúng vào trong Chef recipe, gây khó khăn trong việc quản lí, đặc biệt nếu trang chủ lớn hoặc chúng ta tạo ra nhiều trang. Để giải quyết vấn đề trên, chúng ta cần tạo ra một cookbook. Cookbook cung cấp cấu trúc tổ chức các công thức (recipe) và các external files để mọi thứ được quản lí dễ dàng hơn.

Tạo thư mục cookbooks là nơi chứa tất cả các cookbooks

mkdir cookbooks
cd cookbooks

Dùng chef command để generate ra cookbook tên là install_httpd

chef generate cookbook install_httpd

Chef sẽ tự động sinh ra cho chúng ta cấu trúc thư mục như sau:

.
└── install_httpd
    ├── Berksfile
    ├── chefignore
    ├── metadata.rb
    ├── README.md
    └── recipes
        └── default.rb

Bạn để ý file default.rb trong thư mục recipes. Đây là recipe mặc định khi chạy cookbook sau này. Do chúng ta quản lí recipes bằng cookbook nên toàn bộ nội dung của webserver.rb cần được chuyển sang file default.rb này.

Bây giờ chúng ta sẽ chuyển code HTML trang chủ sang một file khác, gọi là file template. Để tạo template, chúng ta chạy lệnh sau:

chef generate template install_httpd index.html

File index.html.erb sẽ được tạo ra trong thư mục install_httpd/templates/default. Lưu ý, extension của file này là .erb vì đây là định dạng template của Ruby (cho phép nhúng mã Ruby vào trong).

Bây giờ chúng ta hãy copy nội dung HTML của trang chủ trong recipe sang template index.html.erb.

<html>
  <body>
    <h1>hello world</h1>
  </body>
</html>

Đồng thời sửa lại nội dung default.rb

package 'httpd' do
  action :install
end

service 'httpd' do
  action [:enable, :start]
end

template '/var/www/html/index.html' do
  source 'index.html.erb'
end

Bây giờ chúng ta chạy cookbook này bằng lệnh chef-client. Lưu ý là lệnh chef-apply dùng để chạy một recipe, còn chef-client dùng để chạy một cookbook. Trong trường hợp này, chúng ta sẽ dùng chef-client để chạy duy nhất default recipe của cookbook install_httpd bằng tham số run-list:

sudo chef-client --local-mode --runlist 'recipe[install_httpd]'

Lưu ý đoạn: recipe[install_httpd] tương đương với recipe[install_httpd::default]. Nếu bạn có một recipe khác, ví dụ ./install_httpd/recipes/remove_httpd.rb, bạn có thể chạy nó bằng truyền tham số recipe[install_httpd::remove_httpd] cho run-list.

Tổng kết

Đến hiện tại mình đã giới thiệu tới các bạn những kĩ thuật cơ bản nhất để làm việc với file, package, service, template bằng Chef, cũng như cách tổ chức các recipes theo cookbook. Để tìm hiểu sâu hơn, bạn có thể tham khảo trang tài liẹu chính thức của Chef tại: http://docs.chef.io

Tham khảo

https://viblo.asia/dinhhoanglong91/posts/wznVGLqQvZOe

https://tuantranf.wordpress.com/2013/11/15/lam-quen-voi-chef-infrastructure-as-code-1/

http://leopard.in.ua/2013/01/04/chef-solo-getting-started-part-1/

https://learn.chef.io/learn-the-basics/rhel/get-set-up/

https://adamcod.es/2013/01/15/vagrant-is-easy-chef-is-hard-part2.html