Thứ Hai, 29 tháng 2, 2016

Tôi đã dùng Docker như thế nào?

Ngày nay, các công cụ như Docker hay Vagrant rất hay được nhắc đến trong giới công nghệ, đặc biệt, đây là các công cụ cần thiết cho mọi Devops.

Nhưng đó là việc của bọn Devops, còn đối với chúng ta, những developer chân đất, sáng ngậm đắng (cà phê), tối nuốt cay (bia rượu), buổi trưa ngồi code thì có cần quan tâm không?

Xin thưa là có. Bất cứ một công cụ nào sinh ra cũng cần có người xài, và bất cứ ai cũng có thể xài.

Đứng ở phương diện của một Developer, chúng ta có thể sử dụng Docker và Vagrant để thiết lập môi trường ảo cho một dự án nào đó, mà không cần tốn quá nhiều công sức cài đặt hoặc làm ảnh hưởng tới máy tính hiện tại. Làm thế nào để sử dụng? Làm thế nào để tạo môi trường ảo, và vì sao phải làm như vậy? Xin mời các bạn đừng hỏi nữa, cứ đọc tiếp.

Disclaimer: Bài viết sau có đề cập đến project của một thành viên của Kipalog nhưng không hề có sự móc nối, PR hay mối tư thù nào giữa tác giả và thành viên này cả :sweat_smile:

Disclaimer #2: Để tiện cho việc theo dõi bài viết, các bạn không cần có chút khái niệm nào về Docker, nhưng cần cài đặt sẵn nó trên máy tính. Sau bài viết này các bạn sẽ dùng được Docker để làm các công việc đơn giản của một Developer, và có kiến thức nền cơ bản để tìm hiểu sâu hơn về công cụ này. Bài viết sẽ không đề cập tới chuyện so sánh giữa Docker và Vagrant tuy nhiên các bạn có thể comment bên dưới để thảo luận về vấn đề này.

Disclaimer #3: Dành cho bạn nào chưa biết về Github, đây là một "mạng xã hội" dành cho các Developer, dùng để chia sẽ các dự án mã nguồn mở. Một người tạo project trên đó, up source code của mình lên, các developer khác nếu thích có thể tham gia đóng góp vào project (fix bug, thêm chức năng, sửa code, review code,...), và hoạt động này gọi chung là Contribute, người đóng góp được gọi là Contributor.
Một contributor muốn contribute cho một project nào đó trên Github thì chỉ việc Fork project đó về, sửa rồi commit, sau đó tạo Pull request để người chủ project biết và sử dụng bản fix của bạn vào project của họ.
Nếu cảm thấy project hay ho, có thể đánh bấm nút Star để "like" cho project đó.
Nếu có một project đạt được nhiều stars trên Github thì người developer đó sẽ cảm thấy rất "sướng" =)) giống như mấy bạn hot gơn muốn có được nhiều like trên Facebook vậy.
Trở thành contributor của một project nhiều sao (stars) cũng rất "sướng".
Các developer thời nay cũng sống ảo chả khác gì các em hot gơn cả, các bạn ạ...

Chuyện kể rằng...

Buổi sáng hôm đó, trời nắng đẹp và se lạnh. Sau khi đánh một giấc đã đời trên xe bus, chàng developer cần mẫn lếch xác vào công ty, việc đầu tiên anh làm là mở máy tính lên và đọc báo, lướt facebook, github,...

Tình cờ trông thấy một project mới trên github (cái này https://github.com/huydx/scalresume)

Tò mò vào xem thử, hoá ra lão ấy viết bằng Scala. Tính bỏ qua rồi nhưng cũng muốn contribute chút gì đó cho cái project.

Thấy README.md của lão viết sơ sài quá, nảy ra ý định add thêm vài dòng hướng dẫn và screenshot cho nó hấp dẫn (đây cũng là cách để trở thành một contributor nhiệt tình trên Github, các bạn chú ý nhá).

Nhưng hồi nào giờ có làm Scala đâu, chả lẽ vì cái project bé tí này =)) mà phải ngồi cài một đống tool vào máy, nào là Java, nào là Scala, SBT,... để build và chụp cho được cái screenshot sao :joy: Chưa kể có một đống dự án của công ty, chưa hoàn thành, ở trong máy, nếu rủi cài vài rồi hư máy thì biết ăn nói làm sao với sếp.

Giải pháp

Thế là nghĩ ngay đến chuyện dùng Docker.
Đối với các bạn chưa biết Docker là gì, thì đây là một công cụ tạo môi trường được "đóng gói" (còn gọi là Container) trên máy tính mà không làm tác động tới môi trường hiện tại của máy.
Một số developer thường tạo sẵn các môi trường này, và upload lên mạng để mọi người lấy về dùng, và mấy cái này gọi là các Images
Đại khái là sẽ làm thế này:

  • Dùng docker tạo một container chứa toàn bộ môi trường develop cần thiết cho Scala
  • Get project về và build, chạy thử
  • Chụp hình add vào README.md
  • Tạo pull request để đóng góp cho cái project này
  • Nghiễm nhiên trở thành contributor dù ko biết chút gì về Scala

Thực hiện

Bước 1: Tìm và tải image Docker cho Scala

Đầu tiên chúng ta cần tìm một image chạy Scala cho Docker. Bước này thì dễ thôi, có thể search trên Google với từ khoá:
Docker image for Scala
Yeah, rất nhiều images, chọn đại cái kết quả đầu tiên trên Docker Hub: https://hub.docker.com/r/lukasz/docker-scala/
Docker Hub là nơi để mọi người upload, chia sẽ các images Docker của mình
Sau khi tìm ra image rồi, chúng ta tiến hành download nó về, bước này gọi là Pull, chúng ta gõ lệnh sau:
docker pull lukasz/docker-scala
Với lukasz/docker-scala là tên của image. Tên này gồm 2 phần, phần đầu trước dấu xoẹt /, lukasz là tên thằng tác giả, và phần sau docker-scala là tên của image.

Dung lượng của image này hơi lớn một tí (1GB) nên có thể pull hơi lâu, các bạn có thể sử dụng mạng của công ty để quá trình pulling diễn ra nhanh hơn

Sau khi pull xong, các bạn có thể dùng lệnh sau để xem danh sách các images được pull về sẵn trong máy:
docker images
Kết quả trả về như sau:
REPOSITORY            TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                latest              91e54dfb1179        6 weeks ago         188.4 MB
lukasz/docker-scala   latest              90b5825bae47        20 months ago       1.217 GB
Như kết quả trên thì trong máy mình đang có 2 images: ubuntu và lukasz/docker-scala

Các images này các bạn chỉ cần tải về 1 lần và để đó dùng lại cho các lần sau được. Nên yên tâm về cái khoản chờ đợi. Trừ khi bạn buồn tình xoá chúng đi :laughing:

Bước 2: Lấy code từ Github về

Trước khi tạo môi trường ảo để chạy, chúng ta sẽ lấy code từ Github về trước. Ví dụ mình lấy code về và lưu ở thư mục /Users/madman/Code
git clone https://github.com/huydx/scalresume.git /Users/madman/Code

Bước 3: Tạo môi trường ảo Scala liên kết với thư mục Code

Bây giờ chúng ta sẽ tạo một môi trường ảo, còn gọi là một container sử dụng image Scala vừa pull về ở bước trên.

Container này liên kết với thư mục code hiện tại của chúng ta, và như thế chúng ta sẽ truy cập được vào thư mục code từ bên trong container.

Gõ lệnh sau:
docker run -v /Users/madman/Code:/src -it lukasz/docker-scala /bin/bash
Ý nghĩa của câu lệnh trên:

  • docker run : lệnh tạo một container cho Docker
  • tham số -v /Users/madman/Code:/src: để liên kết thư mục /Users/madman/Code ở máy tính hiện tại, vào thư mục /src của container.
  • tham số -it lukasz/docker-scala /bin/bash: Để chỉ định images cần tạo là lukasz/docker-scala và tự động chạy lệnh /bin/bash sau khi khởi tạo xong, nhờ đó chúng ta sẽ truy cập được vào chế độ dòng lệnh của container và quản lý nó giống như một máy tính thông thường.

Bước 4: Sử dụng container để build và chạy code

Sau khi chạy lệnh run thì cửa sổ terminal của chúng ta thay đổi thành như thế này:
root@4cc671941ee3:/# 
Lúc này, bạn đã truy cập vào bên trong container docker-scala.

Thử gõ lệnh ls để liệt kê các thư mục hiện có:
ls
Kết quả:
root@4cc671941ee3:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  selinux  src  srv  sys  tmp  usr  var
root@4cc671941ee3:/#
Giống y chang một máy tính Linux! Giờ chúng ta thử kiểm tra môi trường hiện tại xem, gõ lệnh:
scala
Kết quả trên màn hình:
root@4cc671941ee3:/# scala
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
Type in expressions to have them evaluated.
Type :help for more information.

scala>
Như vậy, chúng ta hiện đang có Scala phiên bản 2.10.3 chạy trên nền Java 1.7.0_51

Bây giờ chúng ta có thể build và chạy thử ứng dụng Scala vừa lấy về từ Github và tiến hành Contribute cho nó. Về bước này, mình sẽ nói ở một bài viết khác, dài hơn :))

Để thoát ra khỏi môi trường ảo hiện tại, bạn chỉ cần gõ lệnh:
exit

Tổng hợp (dành cho ai thấy dài quá ko đọc):

Pull một image từ Docker Hub

docker pull <image name>

Tạo một container từ image có sẵn

docker run -v <thư mục trên máy tính>:<thư mục trong container> -it <image name> /bin/bash
Lệnh trên tạo container, liên kết một thư mục trên máy tính vào bên trong container, và truy cập vào chế độ dòng lệnh của container đó.

Đối với các ứng dụng như web, container sẽ tạo một web server trên một cổng nào đó, khi đó chúng ta cần phải map cổng đó từ container ra máy tính ngoài, khi đó chúng ta dùng thêm tham số -p như sau:
docker run -v /abc:/abc -p 80:80 -it ubuntu /bin/bash
Lệnh trên map cổng 80 của container ra cổng 80 của máy tính hiện tại.

Ngoài ra, Còn một số lệnh khác mà các bạn có thể dùng để quản lý Docker của mình:

Liệt kê các images hiện có

docker images
Trong kết quả trả về của lệnh này, chúng ta lưu ý các thông số:

  • TAG: là tên của image, ví dụ lukasz/docker-scala
  • IMAGE ID: là ID của image lưu trong hệ thống, ví dụ 91e54dfb1179

Liệt kê các container đang chạy

docker ps
Trong kết quả của lệnh này cũng có các thông số chúng ta cần lưu ý, đó là:

  • CONTAINER ID: Là ID của container đó, ví dụ 4cc671941ee3
  • NAME: Là tên riêng của container, được tạo ra một cách ngẫu nhiên hoặc có thể tự đặt, ví dụ stupefied_blackwell

Liệt kê toàn bộ các container đang chạy và đã tắt

Sau khi các bạn thoát khỏi container, nếu nó không còn chạy bất cứ một tiến trình nào nữa, thì nó sẽ tự động tắt, nhưng chưa hoàn toàn bị xoá, khi đó chạy lệnh docker ps sẽ ko thấy được. Để xem lại nó thì chúng ta dùng lệnh sau.
docker ps -a

Khởi động và truy cập lại vào một container đã tắt

Nếu một container đã tắt (không xuất hiện khi dùng lệnh docker ps nữa, chúng ta có thể chạy lệnh docker ps -a để lấy ID hoặc NAME của nó, sau đó dùng lệnh sau để khởi động và truy cập lại vào đó)
docker start <ID hoặc NAME>
docker exec -it <ID hoặc NAME> /bin/bash

Xoá một container

Nếu một container đã hết giá trị lợi dụng, dù nó đã tắt nhưng nó vẫn chiếm một phần dung lượng trên máy tính, để xoá nó đi, chúng ta dùng lệnh rm
docker rm <ID hoặc NAME>
Nếu container đang chạy, bạn cũng có thể xoá nhưng phải thêm tham số -f vào sau rm để force remove:
docker rm -f <ID hoặc NAME>

Xoá một image

Cũng như container, nếu bạn đã ko còn nhu cầu sử dụng một image nào đó nữa, thì nên xoá nó đi, vì dung lượng nó khá là nặng, để lại chật máy. Dùng lệnh rmi (tức là remove image đó)
docker rmi <ID hoặc NAME>
hoặc
docker rmi -f <ID hoặc NAME>
Trên đây là một số thao tác sử dụng Docker đơn giản, đủ xài đối với 1 developer với mục đích sử dụng Docker làm công cụ tạo môi trường ảo.

Với các mục đích sử dụng khác, các bạn nên tìm hiểu kĩ hơn về Docker từ những kiến thức cơ bản trong bài viết này.

Happy Dockering ^^

Thứ Bảy, 27 tháng 2, 2016

Cấu hình firewall sử dụng ipset


Iptables là công cụ để quản lý, cấu hình các quy tắc firewall trong Linux kernel. iptables chỉ là một phần trong netfilter framework, chịu trách nhiệm giao tiếp giữa người dùng và netfilter để đẩy các rule của người dùng vào cho Netfiler xử lý.

ipset là một phần mở rộng của iptables cho phép bạn tạo các quy tắc tường lửa match với một tập các địa chỉ. Khác với iptables chain được lưu trữ và xử lý tuyến tính, ipset được lữu trữ dưới dạng cấu trúc dữ liệu, hỗ trợ tìm kiếm hiệu quả hơn.

Bên cạnh những tình huống mà bạn có thể nghĩ ngay tới để áp dụng ipset hiệu quả, chẳng hạn như chặn một số lượng lớn các host riêng lẻ mà không làm ảnh hưởng tới hiệu năng hệ thống hay gây nghẽn mạng, ipset cũng mở ra những cách thức tiếp cận mới khi thiết kế firewal và có thể giúp đơn giản hóa nhiều kịch bản cấu hình.

Trong bài viết này, chúng ta sẽ thảo luận nhanh về cách cài đặt ipset, một số nguyên tắc và khái niệm cốt lõi về cách thức hoạt động của iptables. Sau đó sẽ tập trung vào cách sử dụng, cú pháp và các ví dụ về kết hợp ipset hoạt động cùng iptables.

Cài đặt

ipset chỉ là một package trên hầu hết các distribution, do đó việc cài đặt khá đơn giản, chúng ta sẽ không mất nhiều thời gian ở bước này. Nếu distro của bạn không có sẵn package, hãy thực hiện theo các hướng dẫn cài đặt ở trang chủ http://ipset.netfilter.org/
Để cài đặt ipset trên Ubuntu, thực hiện lệnh:
sudo apt-get install ipset
Để cài đặt ipset trên CentOS, thực hiện lệnh:
sudo yum install ipset

Tổng quan iptables

Một cách ngắn gọn, một iptables firewall là tập hợp các chain, được phân ra 4 bảng chính (raw, mangle, nat, filter), mỗi chain bao gồm một hoặc nhiều các rule. Với mỗi một gói tin, ở từng giai đoạn xử lý, kernel sẽ tham chiếu tới các chain phù hợp để xác định sẽ làm gì với gói tin. Các chain sẽ được tham chiếu theo thứ tự, dựa vào “hướng” của gói tin ( remote-to-local, remote-to-remote hoặc local-to-remote ) . Bảng dưới đây mô tả các chain sẽ được tham chiếu tùy theo hướng cụ thể của gói tin.
Khi tham chiếu một chain, gói tin sẽ được so sánh với từng rule theo thứ tự trong chain đó cho đến khi tìm được rule phù hợp. Khi tìm được rule phù hợp, gói tin sẽ được xử lý theo target của rule đó. Trong trường hợp không có rule phù hợp, default target hoặc một chính sách nào đó mặc định sẽ được chọn để xử lý gói tin.
Một chain là tập các rule được sắp xếp theo thứ tự, một rule đơn giản là sự kết hợp giữa match/target, tương tự như chúng ta sử dụng câu điều kiện nếu … thì …
Một ví dụ đơn giản về match là "TCP destination port 80", một target có thể là “drop the packet”. Target có thể điều hướng packet đến một chain do user tự định nghĩa.
Một câu lệnh định nghĩa các rule của iptables có 3 phần cơ bản để chỉ rõ table/chain, match và target.

Bên cạnh các tính năng được tích hợp sẵn, iptables còn cung cấp khả năng mở rộng như một API cho "match extensions" (module để phân loại gói tin ) và "target extensions" (module để xác định sẽ làm gì với gói tin).

ipset

ipset là một match extension của iptables. Để sử dụng nó, bạn sẽ tạo các set bằng lệnh ipset, sau đó sử dụng nó để chỉ định match specifition của một rule trong iptables. Một set đơn giản là một danh sách các địa chỉ được lưu trữ tối ưu cho việc tra cứu với tốc độ nhanh.
Giả sử nếu bạn muốn chặn traffic từ 2 địa chỉ IP là 1.1.1.1 và 2.2.2.2 thì ta sẽ thực hiện 2 lệnh sau với iptables.
iptables -A INPUT -s 1.1.1.1 -j DROP
iptables -A INPUT -s 2.2.2.2 -j DROP
Điều kiện match ở đây -s 1.1.1.1 có nghĩa là các packet có địa chỉ nguồn là 1.1.1.1. Để chặn cả 1.1.1.1 và 2.2.2.2, bạn phải sử dụng 2 rule riêng biệt trong iptables. Bạn hoàn toàn có thể sử dụng ipset để đạt được mục đích tương tự với cách thực hiện như sau:
ipset -N myset iphash
ipset -A myset 1.1.1.1
ipset -A myset 2.2.2.2
iptables -A INPUT -m set --set myset src -j DROP 
Các lệnh ipset trên sẽ tạo một set có tên là myset thuộc type iphash gồm 2 địa chỉ 1.1.1.1 và 2.2.2.2. Sau đó iptables sẽ chỉ định match với set được tạo ra từ ipset (-m set --set myset src) , có nghĩa là “match với tất cả các packet có địa chỉ nguồn là một trong các địa chỉ trong myset. Flag src nghĩa là match với địa chỉ nguồn, bạn có thể sử dụng flag “dst” cho mục đích match với địa chỉ đích hoặc sử dụng flag “src,dst” khi cần match cả địa chỉ nguồn và địa chỉ đích.
Với cách làm sử dụng ipset, bạn chỉ cần tới 1 rule của iptables. Ở ví dụ trên chúng ta chỉ sử dụng 2 địa chỉ IP, nhưng khi cần chặn tới 1000 địa chỉ thì bạn sẽ thấy rõ sự khác biệt. Thay vì sử dụng 1000 rule của iptables, bạn vẫn chỉ cần 1 rule kết hợp cùng ipset để có được tác dụng tương đương.

Set types

Mỗi set khi tạo ra sẽ thuộc 1 type xác định, đây là cách để xác định loại giá trị được lưu trữ trong set (IP address, network, port …) và cũng như xác định phần nào của gói tin sẽ được kiểm tra để match với set. Ngoài kiểm tra địa chỉ IP được minh họa ở trên, ipset cũng có thể kiểm tra port, IP + Port và cả địa chỉ MAC + IP của gói tin. Hai dạng linh động nhất thường được sử dụng trong ipsetiphash (lưu trữ danh sách các địa chỉ IP) và nethash (lưu trữ danh sách mạng (IP/mask)). Về các set type bạn có thể tham khảo thêm tại ipset man page.

Lợi ích của ipset

Bên cạnh hiệu quả về mặt hiệu năng, ipset cũng cho phép đơn giản hóa cấu hình trong nhiều trường hợp.
Nếu bạn muốn tường lửa cho phép tất cả các gói tin được tiếp tục xử lý ở chain continue ngoại trừ những gói tin đến từ địa chỉ 1.1.1.1 hoặc 2.2.2.2 , bạn sẽ cấu hình iptables như thế nào ?
iptables -A INPUT -s ! 1.1.1.1 -g  continue
iptables -A INPUT -s ! 2.2.2.2 -g  continue
Cấu hình như trên có hoạt động không ? Tất nhiên là không. Nếu gói tin có địa chỉ nguồn là 1.1.1.1, nó sẽ không match với rule đầu tiên, nhưng gói tin này sẽ match với rule thứ 2 (bởi vì địa chỉ nguồn của nó không phải là 2.2.2.2) nên vẫn được chuyển tới chain “continue”. Đây là một ví dụ đơn giản, nhưng nó cũng minh chứng lợi ích của việc đạt được yêu cầu trong một rule duy nhất. Thực tế các rule của iptables là độc lập với nhau nhưng việc kết hợp, sắp xếp và tối ưu các rule để đạt được những yêu cầu cho trước không phải lúc nào cũng đơn giản, đặc biệt là việc kết hợp các rule bình thường và các rule có điều kiện đảo ngược. ipset sẽ làm cho mọi thứ dễ dàng hơn trong những trường hợp như thế.
ipset -N myset iphash
ipset -A myset 1.1.1.1
ipset -A myset 2.2.2.2
iptables -A INPUT -m set ! --set myset src -g continue
Nếu gói tin đi đến có địa chỉ nguồn là 1.1.1.1 hay 2.2.2.2 cũng không thể match với rule (iptables -A INPUT -m set ! --set myset src -g continue ), do đó sẽ không được xử lý tiếp bởi chain “continue”.

Một lợi ích khác của ipset là bạn có thể thay đổi danh sách địa chỉ của set một cách độc lập với iptables. Đối với iptables, thứ tự các rule là một điểm rất quan trọng, do đó việc sửa đổi các rule hay sắp xếp thứ tự sẽ có ảnh hưởng lớn. Ngược lại, ipset lưu trữ các giá trị trên một mặt phẳng, không đòi hỏi thứ tự nên việc thêm, xóa, sửa đổi không mất nhiều thời gian cân nhắc, suy nghĩ.

Giới hạn truy cập

Nếu một ngày boss của bạn nói rằng có một số nhân viên thường xuyên giải trí trên Internet trong giờ hành chính thay vì làm việc, nhiệm vụ khi đó sẽ là giới hạn truy cập trên PC của các nhân viên này chỉ có thể kết nối tới những trang web họ cần để làm việc nhưng không làm ảnh hưởng đến những người khác.
Để giới hạn 3 PC (10.0.0.5, 10.0.0.6 và 10.0.0.7) chỉ có thể kết nối tới 3 địa chỉ worksite1.com, worksite2.com và worksite3.com, bạn thực hiện như sau :
ipset -N limited_hosts iphash
ipset -A limited_hosts 10.0.0.5
ipset -A limited_hosts 10.0.0.6
ipset -A limited_hosts 10.0.0.7
ipset -N allowed_sites iphash
ipset -A allowed_sites worksite1.com
ipset -A allowed_sites worksite2.com
ipset -A allowed_sites worksite3.com
iptables -I FORWARD -m set --set limited_hosts src -m set ! --set allowed_sites dst -j DROP
Ví dụ này sử dụng match cả hai set trong cùng 1 rule. Nếu packet đến có địa chỉ nguồn match với  limited_hosts và địa chỉ đích không match với allowed_sites, gói tin sẽ bị DROP.

Vậy trong tình huống ngược lại, boss muốn chặn truy cập tới một số trang web trên tất cả các host trên mạng LAN, trừ PC của boss và trợ lý. Cách thực hiện sẽ như sau:
ipset -N blocked_sites iphash  
ipset -A blocked_sites badsite1.com  
ipset -A blocked_sites badsite2.com  
ipset -A blocked_sites badsite3.com

ipset -N allowed_hosts iphash  
ipset -A allowed_hosts 10.0.0.5  
ipset -A allowed_hosts 10.0.0.6

iptables -I FORWARD -m set --set ! allowed_hosts src  -m set --set blocked_sites dst -j DROP  
Lưu ý rằng trong nhiều trường hợp, giải pháp này sẽ không hiệu quả đối với nhiều website. Chẳng hạn bạn muốn chặn truy cập vào facebook.com, thực tế là domain này sẽ được phân giải ra rất nhiều IP, mà iptables/ipset chỉ hỗ trợ hostname nếu chúng được phân giải ra một địa chỉ IP duy nhất . Việc phân giải tên miền cũng chỉ xảy ra lúc thực hiện lệnh, sau đó nếu địa chỉ IP thay đổi, iptables cũng không cập nhật sự thay đổi này. Vì những lý do đó, cách tốt nhất để áp dụng chính sách truy cập Web là sử dụng các giải pháp về HTTP Proxy như Squid.

Tự động chặn các truy cập không mong muốn

ipset cũng cung cấp target extension cho iptables có thể tự động thêm hoặc xóa các entry dựa trên iptables rule. Thay vì phải thêm các entry bằng lệnh ipset, bạn có thể cấu hình để iptables thực hiện việc này.
Giả sử có một host đang muốn kết nối vào port 25 nhưng bạn lại không chạy SMTP server trên máy chủ, và bạn muốn chặn luôn các traffic đến từ host này. Cách thực hiện như sau:
ipset -N banned_hosts iphash  
iptables -A INPUT -p tcp --dport 25 -j SET --add-set banned_hosts src  
iptables -A INPUT -m set --set banned_hosts src -j DROP  
Nếu gói tin có destination port là 25, địa chỉ nguồn của nó sẽ được thêm vào banned_hosts, sau đó ta sẽ thêm một rule để chặn các gói tin có địa chỉ nguồn nằm trong banned_hosts.

ipset trong OpenStack

Neutron sử dụng iptables để thiết lập chức năng security group, nhưng ở các phiên bản trước sẽ gặp phải một số vấn đề. Khi một security group có nhiều rule liên quan đến các security group khác, hiệu năng của security group sẽ giảm hay khi một port được update, toàn bộ các chain liên quan đến port này sẽ được xóa đi và tạo lại, điều này cũng gây ra vấn đề hiệu năng cho L2 agent.
Trong Openstack Juno, ipset được sử dụng để tối ưu iptables rule chain. Giả sử bạn có 2 instance A và B có địa chỉ IP là 10.3.25.57, 10.3.25.58 thuộc SECGROUP1. Bạn tạo một intances C mới thuộc SECGROUP2. SECGROUP2 sẽ chỉ cho phép kết nối SSH từ các instance thuộc SECGROUP1.
Ở các phiên bản trước, iptables rule của port thuộc instance C trong L2 agent sẽ như sau :
-A neutron-openvswi-i9f5f8a14-e -m state --state INVALID -j DROP
-A neutron-openvswi-i9f5f8a14-e -m state --state RELATED,ESTABLISHED -j RETURN
-A neutron-openvswi-i9f5f8a14-e -s 10.3.25.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-openvswi-i9f5f8a14-e -p tcp -m tcp --dport 22 -s 10.3.25.57/32 -j RETURN
-A neutron-openvswi-i9f5f8a14-e -p tcp -m tcp --dport 22 -s 10.3.25.58/32 -j RETURN
Khi sử dụng “iptables+ipset”, các rule đối với instance C sẽ như sau:
-A neutron-openvswi-i9f5f8a14-e -m state --state INVALID -j DROP
-A neutron-openvswi-i9f5f8a14-e -m state --state RELATED,ESTABLISHED -j RETURN
-A neutron-openvswi-i9f5f8a14-e -s 10.3.25.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-openvswi-i9f5f8a14-e -p tcp -m tcp --dport 22 -m set --match-set IPv49ba654b2-a3a4-49f8-8 src -j RETURN
-A neutron-openvswi-i9f5f8a14-e -j neutron-openvswi-sg-fallback
ipset chain sẽ chứa địa chỉ IP của các instance thuộc SECGROUP1
# ipset list IPv49ba654b2-a3a4-49f8-8
Name: IPv49ba654b2-a3a4-49f8-8  
Type: hash:ip  
Revision: 2  
Header: family inet hashsize 1024 maxelem 65536  
Size in memory: 16536  
References: 1  
Members:  
10.3.25.57  
10.3.25.58
Bằng cách này, thời gian iptables-save/iptables-load sẽ gỉam đi đáng kể khi chỉ cần chỉnh sửa các ipset trong trường hợp có sự thay đổi về Security Group.

ipset không chỉ cung cấp thêm một phương thức cấu hình mới cho iptables, nó còn hỗ trợ đơn giản hóa nhiều kịch bản mà nếu chỉ sử dụng iptables sẽ gặp khó khăn hoặc kém hiệu quả. Bạn cũng có thể kết hợp ipset với một số tính năng khác của iptables, chẳng hạn như packet marking, để thực hiện các chính sách về network. Bất cứ lúc nào bạn muốn thiết lập các rule firewall áp dụng cho một nhóm host hoặc nhiều địa chỉ cùng một lúc, bạn nên cân nhắc tới việc kết hợp cùng ipset.

Tham khảo

Loadavg

Phần I : Tổng quan Loadavg

Ting ..ting.. không phải lương về đâu các bạn. Tiếng tin nhắn cảnh báo đã không còn xa lạ gì với một sysadmin. Login vào server để kiểm tra nguyên nhân. Quái! Sao lần này login lại lâu đến như vậy. Mọi command cũng chậm hơn rất nhiều so với bình thường. Bình tĩnh tìm hiểu kỹ hơn. Tôi giật mình: server của tôi đang có loadavg cao ngất ngưởng.

Điều này đồng nghĩa với việc server trở nên ì ạch. Việc xử lý process chậm đi đáng kể. Tại sao lại có sự bất thường này? Gãi râu tự hỏi. Vậy:
  • Loadavg là gì và được tính toán như thế nào?
  • Loadavg ở ngưỡng ra sao thì hợp lý?
  • Những yếu tố nào ảnh hưởng đến loadavg?
  • Phương án phân tích và xử lý khi server tải cao thế nào?
Tôi sẽ trả lời 4 câu hỏi kể trên trong phần I của bài viết về Loadavg này.

Loadavg là gì và được tính toán như nào?

Trước tiên bắt đầu với systemload hay còn gọi là load. 
Systemload thể hiện số công việc hiện tại hệ thống đang thực thi. 
Một server hoàn toàn nhàn rỗi có load là 0 
Mỗi tiến trình đang chạy hoặc chờ đợi cpu xử lý sẽ add giá trị 1 vào load 
Ví dụ với load = 5 => Có 5 process đang chạy hoặc chờ xử lý (Thread running, waiting) 
Nhưng chúng ta thường nghe đến khái niệm loadavg

Tại sao không phải là load mà là loadavg???

Ví dụ thế này để các bạn dễ hình dung:
  • Tại 1 phần trăm giây đầu tiên Load = 0 vì server đang rảnh rỗi
  • Tại phần trăm giây tiếp theo Load = 5 vì thời điểm có 5 proces cần xử lý.
  • Tại phần trăm giây sau đó Load = 99 rất lớn vì thời điểm có rất nhiều process chạy qua hệ thống.
Các con số Load cho mỗi một thời điểm này không có ý nghĩa nhiều trong việc đánh giá tải của hệ thống. 
Loadavg thể hiện tải trung bình của hệ thống qua mỗi đoạn thời gian: cho thấy trung bình có bao nhiều process mà server phải thực hiện. 
Hay nói cách khác: giá trị Loadavg cho ta thấy được trung bình khối lượng công việc hệ thống phải xử lý trong mỗi khoảng thời gian: 1 phút, 5 phút và 15 phút.
cat /proc/loadavg
3.00 5.00 4.00
Hiểu giá trị console này như sau: 
Trong 1 phút gần đây trung bình có 3 process cần được xử lý (3 thread running, waiting) 
Tương tự như vậy có trung bình 5 process xử lý trong vòng 5 phút và 4 process xử lý trong vòng 15 phút.

Loadavg ở ngưỡng ra sao thì hợp lý?

Loadavg có một ngưỡng chung? 
Các server đều có một ngưỡng loadavg cố định? 
Câu trả lời là Không 
Điều này còn phụ thuộc vào server có bao nhiêu CPU. Có thể xem số CPU của sever bằng lệnh sau:
cat /sys/devices/system/cpu/online
0-3
Như vậy server hiện tại (bao gồm cả hyper-v threading) có 4 CPUs 
Giả sử với mỗi CPU là 1 cây cầu. Process qua mỗi CPU thể hiện như sau:

Với 4 CPUs chúng ta có 4 cây cầu và có thể xử lý với mức Loadavg <= 4.00 là mức lý tưởng.

Để thấy rõ hơn điều này ta thực hiện 1 vài thử nghiệm với server 4 CPUs. Chúng ta cùng xem nó xử lý process như nào khi loadavg lần lượt bằng: 1.00, 4.00 và 8.00
  • Case 1: Server 4 CPUs với loadavg = 1.00
Process vừa tạo được hoàn toàn sử dụng CPU với tốc độ xử lý bình thường, performance đạt 100%. Loadavg lúc này tăng lên 1.00.
  • Case 2: Server 4 CPUs với loadavg = 4.00

4 process chạy đồng thời đang phân chia sử dụng 4 CPUs mà server đang có. Tốc độ xử lý vẫn đạt 100%. Loadavg lúc này đã tăng lên 4.00
  • Case 3: Server 4 CPUs với loadavg = 8.00

Loadavg thời điểm này lên tới 8.00 gấp đôi số CPU hiện có. Mỗi process chỉ còn sử dụng được 50% CPU => Tốc độ xử lý chậm đi tương ứng.
Qua hàng loạt case test, ta thấy loadavg nên duy trì nhỏ hơn hoặc bằng số CPU. Process càng vượt quá CPU hiện có bao nhiêu, tốc độ xử lý càng chậm đi tương ứng.

Những yếu tố nào ảnh hưởng đến loadavg?

Vậy điều gì làm tải của hệ thống tăng cao.
Như 1 vài case test ở mục 2 cho thấy mối quan hệ giữa CPU utilization và loadavg

Nhưng liệu loadavg có chỉ phụ thuộc vào CPU utilization?

Tải của hệ thống có thể được tính toán (count) dựa trên các tiến trình đang được xử lý (running on CPU) và các tiến trình runable (waiting for CPU)
Ngoài ra tải còn bao gồm các tiến trình uninterruptible sleep states (waiting disk I/O hoặc network). Những tiến trình này cũng góp phần làm tăng cao tải hệ thống mặc dù nó không thực sự sử dụng CPU.
--> Có 3 yếu tố góp phần làm tăng tải hệ thống:
  • Cpu Utilazion
  • Disk I/O
  • Network Traffic
Việc phân tích sự ảnh hưởng của các yếu tố này sẽ khá dài và phức tạp, chúng ta sẽ cùng nhau tìm hiểu sâu thêm trong những phần sau. Giờ tôi sẽ hướng dẫn bạn cách phân tích và xử lý khi server gặp tải cao.

Phương án phân tích và xử lý khi server tải cao như nào?

Chúng ta đã thống nhất với nhau ba yếu tố:
  • Cpu Utilazion
  • Disk I/O
  • Network Traffic
đều có thể gây ảnh hưởng đến tải của hệ thống.

Cần xử lý những gì khi loadavg lên quá cao?

Ta cần phải phân tích yếu tố nào gây tải cao hệ thống.
Trước hết cần phải theo dõi CPU utilization.
  • Nếu lượng CPU utilization lớn hơn 100% và Loadavg vượt quá số CPU đang có. 
--> Có thể kết luận loadavg cao bởi lượng lớn các process đang running hoặc waiting cpu xử lý.
Sử dụng top -i để theo dõi các process running phân tích các process và đưa phương án.
  • Nếu lượng cpu sử dụng vẫn bình thường (tức không quá cao) nhưng loadavg vẫn cao hơn số cpu đang có. 
--> Vậy có thể kết luận có thể disk I/O hoặc network traffic hoặc cả hai là yếu tố chính gây ra tải cao cho hệ thống. 
Sử dụng 1 số tool linux cung cấp như iotop, atop, vmstat để có thể phân tích chính xác yếu tố nào và đưa ra phương án xử lý.

Phần II : Các yếu tố ảnh hưởng tới Loadavg

1. CPU utilization và load average

Trong trường hợp CPU của bạn được dùng cho những tính toán rất nhẹ nhàng có thể xong tức thì nhưng số lượng process cần CPU lại rất cao, các process cần xử lý tại một thời điểm vượt mức CPU core server hiện có. Điều này nói lên rằng CPU của bạn đang bị quá tải process. Có nhiều lý do dẫn đến trường hợp này và mỗi trường hợp có nhiều cách giải quyết khác nhau.

Một ví dụ hay thấy trường hợp này là máy chủ web. Việc render các trang web là không hề nặng, tuy vậy với các máy chủ web chịu trafic lớn (số lượng connection lớn), các process phục vụ request sẽ phải xếp hàng dẫn đến tình trạng trang web bị phục vụ với thời gian kéo dài hơn.

Tuy nhiên trong quá trình vận hành hệ thống, không ít lần tải hệ thống lên rất cao mặc dù các tiến trình không thực sự sử dụng nhiều CPU. Vậy là lúc chúng ta xem xét yếu tố tiếp theo gây ra tải cao hệ thống.

2. Disk I/O và load average

Trong phần này ta sẽ cùng nhau làm rõ một số vấn đề :
  • I/O wait ảnh hưởng loadavg như nào?
  • Khi nào I/O wait xảy ra?
  • Mối quan hệ I/O wait và CPU?
  • Khi nào thì high I/O wait?
I/O wait là giá trị thời gian mà một CPU (hoặc tất cả các CPU) idle bởi vì các tiến trình Runnable đang chờ đợi một hoạt động I/O disk được hoàn thành trong khoảng thời gian nhất định.
I/O wait = ((CPU waiting on disk time)/ periods) * 100% 
Một trường hợp hay gặp trong database server:

Máy chủ DB dành thời gian chủ yếu đợi thao tác vào ra (I/O) như khi truy vấn cơ sở dữ liệu. Số lượng query lớn, số lượng truy vấn cần sắp xếp lớn nhưng dữ liệu cần sắp xếp lại rất bé, thời gian đợi dữ liệu từ disk lại cao. Vì vậy phần lớn CPU sẽ idle, nhưng loadavg vẫn cao.

Rối tung lên phải không nào? Để tôi ví dụ cụ thể cho các bạn dễ hình dung:

Trong một truy vấn tốn thời gian là 1s để lấy 10.000 rows và thực hiện 1 số thao tác với các row đó:


Process đi vào CPU để xử lý. CPU sẽ truy cập vào disk để lấy thông tin các rows. Tại thời điểm này CPU sẽ idle và chờ disk phản hồi, đây chính là thời điểm waiting on disk.

Như ảnh trên waiting on disk sẽ tốn 700ms trong 1s. I/O wait tại thời điểm này đo được là 70%.

Đến đây chắc hản các bạn cũng giống tôi thắc mắc ngưỡng của I/O wait. Vậy như nào là high I/O wait?

High I/O wait phụ thuộc vào số lượng CPU server đang có. 50% iowait của server 2 cpu chỉ tươg đương với 12.5% iowait trên server có 8 cpu. Tỉ lệ nghịch với số lượng cpu của server.


Tổng quát lại : nếu phần trăm I/O wait lớn (1/số lượng cpu) * 100% thì đây là lúc bạn cần phải xem xét lại disk I/O hệ thống của mình.

3. Network traffic và load average

Đã khi nào bạn gặp trường hợp tải hệ thống vẫn rất cao mặc dù I/O wait và CPU utilization tương đối thấp chưa? Nếu rồi thì có lẽ (có lẽ thôi nhé) hệ thống của bạn đang gặp phải trường hợp thứ 3 process waiting for Network I/O

Tôi sẽ thử vài ví dụ để chứng minh network cũng gây ảnh hưởng đến loadavg:


Thực hiện traffic nhận 50 nghìn package với khoảng 1,5Gb data qua lo interface. Ta cùng theo dõi CPU utilization và run-queue utilization.

CPU sử dụng 21% ở user mode và 79% ở kernel mode. Bởi vì tại thời điểm này linux kernel đang phaỉ làm việc rất nhiều để xử lý lượng lớn traffic.

Bảng thống kê loadavg hiện đang show ta thấy trung bình có 13 process trong run-queue và loadavg-1 đang sắp đạt mốc 13. Đây chính là dấu hiệu cho thấy loavg bị ảnh hưởng bởi quá trình thực hiện network I/O. Các process network đã sử dụng 1 lượng lớn thời gian của CPU và buộc loadavg tăng lên. Ta sẽ xác nhận điều này bằng các giá trị show trong top util


Như đã thấy các process network stress đã không thực sự sử dụng quá nhiều CPU. Việc tiêu thụ cpu chủ yếu là si = 50% cho thấy cpu utilization chủ yếu cho việc xử lý software interrupts.

Chúng ta đã cùng phân tích một số các yếu tố ảnh hưởng loadavg, tuy nhiên điều này có thể vẫn còn chưa đủ. Bản chất Loadavg được tính toán dựa trên số lượng process chờ đợi trong run-queue. Do đó ngoài các process đang được xử lý, tải hệ thống vẫn tiếp tục tăng khi bạn có một hoặc một vài process trạng thái UNINTERRUPTIBLE_SLEEP đang chờ đợi thành phần khác như hardware hoặc software để tiếp tục xử lý.

Linux includes processes in uninterruptible sleep in its load calculation. Such processes show with State 'D' in the usual process inspection tools. This state is usually used by device drivers waiting for disk or network IO. That "usual explanation" is true for Linux, but not most other unixes

Link tham khảo

Ansible

Phần 1 - Cài đặt và cấu hình

Ansible là gì?

Ansible đang là công cụ Configuration Management khá nổi bật hiện nay.
  • Là công cụ mã nguồn mở dùng để quản lý cài đặt, cấu hình hệ thống một cách tập trung và cho phép thực thi câu lệnh điều khiển.
  • Sử dụng SSH (hoặc Powershell) và các module được viết bằng ngôn ngữ Python để điểu khiển hệ thống.
  • Sử dụng định dạng JSON để hiển thị thông tin và sử dụng YAML (Yet Another Markup Language) để xây dựng cấu trúc mô tả hệ thống.

Đặc điểm của Ansible

  • Không cần cài đặt phần mềm lên các agent, chỉ cần cài đặt tại master.
  • Không service, daemon, chỉ thực thi khi được gọi
  • Bảo mật cao ( do sử dụng giao thức SSH để kết nối )
  • Cú pháp dễ đọc, dễ học, dễ hiểu

Yêu cầu cài đặt

  • Hệ điều hành: Linux (Redhat, Debian, Ubuntu, Centos, ...), Windows
  • Thư viện Jinja2: dùng để xây dựng template cấu hình
  • Thư viện PyYAML: hỗ trợ cấu trúc YAML
  • Python 2.4 trở lên

Cài đặt Ansible

  • Trên CentOS:
    • Cài đặt EPEL repo
    • Cài đặt thông qua yum:
sudo yum install ansible 
  • Trên Ubuntu:
Cấu hình PPA, cài đặt: 
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible 
Trên các phiên bản Ubuntu cũ, gói software-properties-common có tên khác là python-software-properties

Cấu hình

Demo sử dụng hệ điều hành Ubuntu 14.04, với các hệ điều hành khác cũng hoàn toàn tương tự. 
Server master: 192.168.1.100  
Server agent: 192.168.1.101
  • Tạo tài khoản truy cập SSH trên agent
Do policy của hệ thống giới hạn tài khoản root truy cập cũng như để thuận tiện cho việc quản lý (tránh dùng chung account của người quản trị) thì nên tạo 1 tài khoản khác phục vụ cho ansible
Tạo tài khoản:
sudo adduser ansible
Cấu hình sudo cho phép tài khoản ansible sử dụng không cần password 
sudo vi /etc/sudoers.d/ansible
ansible ALL=(ALL)   NOPASSWD:ALL  
  • Tạo ssh key
Để thuận tiện cho việc sử dụng Ansible cũng như giới hạn 1 số hệ thống chỉ cho phép xác thực qua key. (Ansible có hỗ trợ kết nối thông qua password)

Tạo ssh keyfile: ( trên master ) 
ssh-keygen -C "ansible@master"
Enter file in which to save the key (/home/ubuntu/.ssh/id_rsa): '/etc/ansible/ansible_key'
...
Lý do không đặt ssh key ở thư mục mặc định là do rất có thể có nhiều người quản trị cùng tham gia quản lý.)
Copy keyfile sang agent: 
ssh-copy-id -i /etc/ansible/ansible_key.pub ansible@192.168.1.101
Kiểm tra:
ssh -i /etc/ansible/ansible_key ansible@192.168.1.101
  • Cấu hình host và group
Ansible lưu thông tin những hệ thống trong file /etc/ansible/hosts (inventory) theo cấu trúc dạng INI như sau: 
mail.example.com

[webservers]
foo.example.com  
bar.example.com

[dbservers]
one.example.com  
two.example.com  
three.example.com 
Trong đó: 
*.example.com: hostname của các host (phải cấu hình tiếp trong file /etc/hosts để xác định địa chỉ IP) 
[webservers], [dbservers]: là các group 

Ở ví dụ demo này, cấu hình /etc/ansible/hosts như sau:
[webservers]
web1 ansible_ssh_host=192.168.1.101
ansible_ssh_private_key_file=ansible_key
ansible_ssh_user=ansible
List các tham số hỗ trợ: inventory parameters

Sử dụng các lệnh cơ bản
ansible web1 -m ping
ansible webservers -m ping
ansible all -m ping
ansible web1 -m command -a 'df -h'
ansible web1 -s -m command -a 'fdisk -l'
ansible -i /etc/ansible/hosts all -m ping
Chú ý:
  • Ansible cho phép chỉ định 1 host, 1 group hoặc tất cả (all) khi thực thi
  • -m: lựa chọn sử dụng module
  • -a: tham số gửi vào module
  • -s: sử dụng sudo
  • -i: chỉ định inventory file (mặc định /etc/ansible/hosts)

Phần 2 - Playbook

Về Playbook

Playbook thông thường là những tấm bảng ghi sơ đồ vị trí, chiến thuật di chuyển của từng cầu thủ mà các HLV sử dụng để truyền đạt cho cầu thủ (nếu bạn xem đá bóng). Ví dụ như Willian đá hộ công, Eden Hazard đột phá cánh trái hay Branislav Ivanović đá hậu vệ.

Ansible sử dụng khái niệm Playbook cũng mang ý nghĩa tương tự. Việc triển khai hệ thống mới cũng tương tự như sơ đồ chiến thuật, các group [webservers], [databases] cũng như tuyến tiền đạo, hậu vệ, các dịch vụ cũng như kết nối tới các thành phần khác nhau trong hệ thống của từng server cũng giống nhiệm vụ của một cầu thủ trên sân.

Ansible Playbook được viết theo cấu trúc YAML, một cú pháp dễ đọc, dễ viết hơn so với JSON, XML. Dưới đây là ví dụ về YAML:
---
# An employee record
name: Example Developer  
job: Developer  
skill: Elite  
employed: True  
foods:  
    - Apple
    - Orange
    - Strawberry
    - Mango
languages:  
    ruby: Elite
    python: Elite
    dotnet: Lam
Xem thêm về YAML syntax. Bắt đầu file yaml bằng ---. Sử dụng indent là 2 space.

Ví dụ
Đây là file webservers.yml, 1 playbook cho dịch vụ apache. Playbook này có 1 play, dùng cho hệ điều hành Redhat, CentOS
---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
  handlers:
    - name: restart apache
      service: name=httpd state=restarted
Giải thích:

  • hosts: xác định đối tượng sẽ thực thi playbook này.
  • vars: các biến dùn trong play, trong ví dụ này các biến sẽ được dùng để cấu hình apache
  • tasks: liệt kê các task cần thực hiện
  • name: tên của task
  • yum, template, service: các module sử dụng
  • notify: giống như trigger, để gọi đến 1 task khác khi task hiện tại thực hiện thành công.
  • handlers: khai báo các task notify
1 play gồm danh sách các task được thực thi theo thứ tự từ trên xuống. Nếu xảy ra lỗi ở task nào thì host đang thực thi sẽ bị dừng lại mà không ảnh hưởng đến các host khác.
Có thể viết tách dòng với các tham số truyền vào module
- name: ensure apache is at the latest version
  yum:
    pkg: httpd
    state: latest
Chạy playbook:
ansible-playbook webserver.yml 
Ví dụ 1 playbook có nhiều play:
---
- hosts: webservers
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf

- hosts: databases
  tasks:
  - name: ensure postgresql is at the latest version
    yum: name=postgresql state=latest
  - name: ensure that postgresql is started
    service: name=postgresql state=running
Cấu trúc 1 playbooks chuẩn:
 production                # inventory file for production servers  
stage                     # inventory file for stage environment

group_vars/  
   group1                 # here we assign variables to particular groups
   group2                 # ""
host_vars/  
   hostname1              # if systems need specific variables, put them here
   hostname2              # ""

library/                  # if any custom modules, put them here (optional)  
filter_plugins/           # if any custom filter plugins, put them here (optional)

site.yml                  # master playbook  
webservers.yml            # playbook for webserver tier  
dbservers.yml             # playbook for dbserver tier

roles/  
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""
Trong đó:

  • production: giống file /etc/ansible/hosts, liệt kê group, host
  • group_vars/*: đặt các biến chung cho cùng 1 nhóm, ví dụ [webservers] có biến listen_port: 80
  • host_vars/*: đặt các biến riêng cho từng host
  • roles/*: đặt các role, ví dụ các host trong [webservers] gọi đến role webtier

Lợi ích:

  • Tách biệt các hệ thống, 1 hệ thống là 1 project riêng biệt
  • Việc tách role giúp dễ dàng quản lý, phát triển
  • Tái sử dụng tốt, chỉ cần sửa thông tin host, vars
Ví dụ:
lamp_simple/  
├── group_vars
│   ├── all
│   └── dbservers
├── hosts
├── LICENSE.md
├── README.md
├── roles
│   ├── common
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       └── ntp.conf.j2
│   ├── db
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       └── my.cnf.j2
│   └── web
│       ├── handlers
│       │   └── main.yml
│       ├── tasks
│       │   ├── copy_code.yml
│       │   ├── install_httpd.yml
│       │   └── main.yml
│       └── templates
│           └── index.php.j2
└── site.yml
Bạn có thể xem thêm các ví dụ khác tại ansible examples

Configuration Management

Configuration Management (CM) là gì? Tại sao phải dùng tới CM? Hạn chế của nó cũng như ứng dụng trong Cloud Computing. Chúng ta sẽ cùng trả lời các câu hỏi trên trong bài viết về Configuration Management.

Configuration Management là gì?

Configuration management (CM) là công cụ thực hiện việc thay đổi trạng thái hiện tại của hệ thống sang trạng thái được xác định trước. Hay nói cách khác, là công cụ hỗ trợ, cấu hình, cài đặt hệ thống một cách tự động.

Configuration management tools

Có rất nhiều công cụ như Ansible, Chef, Puppet, Saltstack ... Loạt bài viết này sẽ không tập trung vào việc so sánh các công cụ CM mà chỉ hướng dẫn bạn cách cài đặt và sử dụng Ansible.

Tại sao lại cần Configuration management?

Ví dụ một ngày sếp bạn vào và bảo bạn triển khai 1 hệ thống LAMP stack gồm 2 server, 1 web và 1 database. OK không vấn đề gì, chỉ cần yum/apt, sửa config apache, php, mysql,.. bạn hoàn thành công việc.

Rồi một ngày khác sếp bạn yêu cầu bạn mở rộng triển khai sang n webserver, m database với cấu hình keepalive, HA, replication database loằng ngoằng... "Anh đùa em?". Không !! Nhưng bạn vẫn hoàn thành công việc.

Lại một ngày khác, sếp bạn vào và nói: "Chú dựng cho anh 1 hệ thống tương tự như vậy nữa nhé. Số lượng server tăng gấp đôi". Và bạn đã khóc

Giờ thì bạn đã hiểu tại sao lại có Ansible, Saltstack rồi chứ ... :D

Lợi ích của configuration management


  • Giúp thực hiện công việc triển khai hệ thống đơn giản và thuận tiện.
  • Hạn chế những công đoạn lặp lại, tiết kiệm thời gian
  • Có thể sử dụng lại cho những hệ thống tương tự.
  • Linh hoạt, mềm dẻo trong quản lý.

So sánh với shell script (Linux)

Thế shell script thì sao ? Tôi vẫn dùng shell script để triển khai hệ thống. Có vấn đề gì đâu ?

Đúng, shell script vẫn tốt. Nhưng hãy tưởng tượng bạn có 10 server, bạn phải download script trên từng server rồi thực thi script. Tiếp tục, ví dụ 10 server đó của bạn có Ubuntu, CentOS, thì chí ít bạn lại phải có 2 version shell script, như apt >< yum, gói Apache trên Ubuntu là apache2, trên CentOS là httpd... Rồi thì version hệ điều hành khác nhau, như Ubuntu 12.04, 14.04, CentOS thì 5, 6, 7. Bạn cần chục version khác nhau của shell script? (hoặc bạn phải if/else mệt nghỉ). Việc maintaince code rất khó khăn.

Với những công cụ như Ansible, Chef... hỗ trợ sẵn việc xác định distro, phiên bản cũng như sử dụng những cấu trúc linh hoạt, dễ đọc như yaml, jinja2 giúp đỡ rất nhiều cho người quản trị để xây dựng kịch bản hệ thống, maintaince code cũng như tái sử dụng.

Có hạn chế gì không ?

Mặc dù rất tốt nhưng CM không phải là vạn năng. Nếu không phải triển khai 1 hệ thống đủ lớn, hoặc chỉ phải thực hiện trên 1, 2 server thì thực sự không cần thiết dùng đến CM. Viết ra kịch bản có khi tiêu tốn nhiều thời gian hơn việc bạn thực hiện nó bằng lệnh.

Trong những tình huống như hệ thống gặp sự cố hay troubleshooting thì CM không có nhiều tác dụng. Đó là những tình huống cần sự cẩn thận, tránh những sai sót không đáng có.

CM với Cloud Computing

Cloud computing mang đến cho bạn khả năng tạo các server ảo hóa một cách nhanh chóng. Chỉ 1 nút bấm, bạn đã có 10 đến hàng trăm cloud server sẵn sàng phục vụ. Với tốc độ phát triển chóng mặt cùng với cạnh tranh quyết liệt trong việc cung cấp dịch vụ trên Internet, những yêu cầu của sếp như ví dụ trên sẽ xảy ra thường xuyên với những deadline ngắn hạn. Là nhà cung cấp dịch vụ trên nền điện toán đám mây, VCCloud hiểu rằng việc tự động hóa các thao tác cài đặt, cấu hình, triển khai và mở rộng với CM sẽ giúp tiết kiệm rất nhiều thời gian và tiền bạc.

Thứ Sáu, 26 tháng 2, 2016

How to Install Nginx on Ubuntu 14.04 LTS

Nginx is a free, open source, high-performance web server. Need HTTP and HTTPS but don’t want to run Apache? Then nginx may be your next go-to, at least for Linux.

Pre-Flight Check

  • These instructions are intended specifically for installing nginx on Ubuntu 14.04 LTS.
  • I’ll be working from a Liquid Web Self Managed Ubuntu 14.04 server, and I’ll be logged in as root.

Step #1: Install nginx

First, you’ll follow a simple best practice: ensuring the list of available packages is up to date before installing anything new.
sudo apt-get -y update
Then it’s a matter of just running one command for installation via apt-get:

sudo apt-get -y install nginx

Step #2: Find Your IP Address; Visit Your Site

Once the installation is complete the nginx service should automatically start and begin listening on port 80
Find your server’s IP address run the following command:
ip addr show eth0 | grep inet
In this case we are assuming that eth0 is configured with the primary public IP of your server. Your result may look similar to:

inet xxx.xxx.xxx.xxx/22 brd yyy.yyy.yyy.yyy scope global eth0
Where xxx.xxx.xxx.xxx is the IP address of your server.
Verify that nginx is running by visiting http://xxx.xxx.xxx.xxx. For example: http://1.2.3.4.
You should receive a page similar to:

Step #3: Manage the nginx Service

Start the nginx Service:
service nginx start
Stop the nginx Service:

service nginx stop
Restart the nginx Service:

service nginx restart
Check the Status of the nginx Service:

service nginx status
Assure that nginx starts at boot:

update-rc.d nginx defaults
When running the last command you may receive:

System start/stop links for /etc/init.d/nginx already exist.
The above error simply means that nginx is already configured to start when the server boots.