Thursday, 7 July 2016

Terraform, một công cụ để làm Infrastructure as Code


Bạn đã nghe về "Infrastructure as Code" chưa ? Bạn có biết Terraform không? Có thể có ,có thể không nhưng dù sao hãy đọc bài viết này. Tôi sẽ viết về chúng trong sự hiểu biết của mình, và nếu bạn thấy thú vị chúng ta có thể thảo luận cùng nhau.

Infrastructure as Code là một phương pháp trong đó bạn sẽ viết các đoạn mã để xây dựng hạ tầng cho sản phẩm của mình. Hạ tầng cho sản phẩm bao gồm các thành phần chính :


  •  hệ thống mạng           :  đảm bảo việc truy cập vào ra thông suốt và an toàn
  •  hệ thống tính toán     :  cung cấp tài nguyên tính toán cho các ứng dụng, tiến trình xử lý
  •  hệ thống lưu trữ         :  cung cấp tài nguyên, giải pháp lưu trữ dữ liệu và thông tin
  •  hệ thống email, DNS  : cung cấp dịch vụ liên quan tới email, DNS
  •  hệ thống giám sát      :  theo dõi và cảnh báo hoạt động của hệ thống


Có nhiều cách để xây dựng cơ sở hạ tầng cho sản phẩm như : mua Server đặt ở các trung tâm dữ liệu, thuê mua VPS VMs, tự xây dựng trung tâm dữ liệu của mình, sử dụng dịch vụ cloud computing của Google (GCP), của Amazon (AWS), của Microsoft (Azure) ...


Vậy Terraform thì có liên quan gì đến mấy thứ ở trên? Terraform là một công cụ nguồn mở giúp thực hiện "Infrastructure as Code" thuận tiện và dễ dàng hơn, viết bằng ngôn ngữ Go khởi xướng bởi Hashicorp. Terraform GitHub Repository

Với tính năng linh hoạt Terraform có thể làm việc với nhiều hãng và nền tảng cung cấp dịch vụ hạ tầng khác nhau như : Atlas, Heroku, AWS, GCP, OpenStack, DigitalOcean, ... tham khảo thêm tại đây.

Terraform so sánh với một số công cụ khác :

* Chef, Puppet, Ansible : các công cụ này có chức năng provision cho các máy đã tồn tại, nhiệm vụ chính của Terraform là provision các máy và cách chúng được sắp đặt và liên kết với nhau.
* CloudFormation : chức năng tương tự nhưng chỉ dùng cho AWS, Terraform có thể làm việc với nhiều hãng và nền tảng khác nhau như đã nói ở phía trên.
* Boto, fog : đây là các thư viện ở mức thấp giúp người dùng tương tác với APIs của các Providers, Terraform cung cấp cho người dùng các syntax ở mức cao, dễ sử dụng hơn.
Bạn có thể xem thêm chi tiết ở đây.

Chúng ta hãy tìm hiểu chi tiết bằng một ví dụ đơn giản, xây dựng hạ tầng cho một sản phẩm trên nền tảng AWS gồm có 1 EC2 instance đặt ở Public subnet, 1 RDS instance đặt ở Private subnet.



Các bước cơ bản cần thực hiện :

B1: Cài đặt TerraformAWS credential cho phép xác thực khi tương tác với các API của AWS để thực hiện các yêu cầu

B2 :Clone từ ví dụ từ github (hoặc bạn có thể tự viết sau khi đã thành thạo) về một thư mục trên máy chẳng hạn như terraform-example. Terraform sử dụng các Terraform configurations files với đuôi .tf để người dùng thiết lập các mô tả cho hạ tầng của mình,  trong ví dụ này sẽ gồm có :

* main.tf : file này chứa các đoạn mã để tạo tài nguyên theo mong muốn. Ví dụ đoạn mã dưới đây của terraform sẽ tạo một EC2 instance với loại instance là m1.small, sau đó cài đặt và bật nginx trên instance đó.

resource "aws_instance" "web" { 
# The connection block tells our provisioner how to
# communicate with the resource (instance)
connection {
# The default username for our AMI
user = "ubuntu"
# The connection will use the local SSH agent for authentication.
instance_type = "m1.small" 
# Lookup the correct AMI based on the region
# we specified 
ami = "${lookup(var.aws_amis, var.aws_region)}" 
# The name of our SSH keypair we created above. 
key_name = "${aws_key_pair.auth.id}"
# Our Security group to allow HTTP and SSH access 
vpc_security_group_ids = ["${aws_security_group.default.id}"] 
# We're going to launch into the same subnet as our ELB. In a production
# environment it's more common to have a separate private subnet for
# backend instances.
subnet_id = "${aws_subnet.default.id}" 
# We run a remote provisioner on the instance after creating it.
# In this case, we just install nginx and start it. By default,
# this should be on port 80
provisioner "remote-exec" {
inline = [
"sudo apt-get -y update",
"sudo apt-get -y install nginx",
"sudo service nginx start"
]
}
}

* variables.tf : file này chứa các biến được sử dụng trong file main.tf ở phía trên, bạn có thể truyền giá trị cho các biến này cũng như thiết lập giá trị mặc định. Đoạn mã dưới định nghĩa một biến là aws_region với giá trị mặc định là "us-west-2".

variable "aws_region" {
description = "AWS region to launch servers."
default = "us-west-2"
}

* outputs.tf : file này chứa các giá trị sẽ được truyền ra ngoài giúp cho các modules khác có thể sử dụng giá trị này truyền cho biến của mình. Đoạn mã dưới sẽ đưa ra địa chỉ public dns của instance vừa tạo ở trên.

output "address" {
value = "${aws_instance.web.public_dns}"
}

* Trong quá sử dụng terraform, sẽ có thêm 2 files được sinh ra để lưu trạng thái hiện tại của các tài nguyên đã được tạo :

terraform.tfstate
terraform.tfstate.backup

Source code cho ví dụ này bạn có thể tìm thấy ở đây.

B3 : Chạy lệnh $ terraform plan để kiểm tra và hiển thị trước những tài nguyên sẽ được tạo.
B4 : Chạy lệnh $ terraform apply để bắt đầu tạo tài nguyên từ các file .tf mô tả ở trên.

Cuối cùng, nếu muốn xoá toàn bộ tài nguyên vừa được tạo ở trên chúng ta có thể dùng lệnh $terraform destroy, hãy cẩn thận với môi trường thật khi thực hiện lệnh này ;)

Bài viết giới thiệu tổng quát về khái niệm Infrastructure as Code và một công cụ để thực hiện nó, Terraform. Từ đó bạn có thể tìm hiểu sâu hơn về chúng để có thể áp dụng vào việc giải quyết các vấn đề về hạ tầng một cách linh hoạt và hiệu quả.

Cám ơn bạn đã đọc bài viết.

Monday, 11 April 2016

Continuous Integration with CloudFormation, Ansible, Jenkins, Docker, ECS

Có bao giờ bạn muốn code của mình sau khi viết xong được kiểm tra ngay tức thời với hệ thống đang chạy trên các môi trường test, stagging, thậm chí là trên production ? Làm thế nào để tăng tốc quá trình phát triển ứng dụng thông qua việc phát hiện lỗi càng sớm càng tốt ? Nếu câu trả lời là có, xin mời bạn tiếp tục theo dõi bài viết.

Bài viết sẽ đưa ra một ví dụ tổng quát về việc sử dụng các công cụ, dịch vụ phối hợp với nhau để thực hiện Continous Integration (CI) trong quá trình phát triển phần mềm.

Mô hình tổng quan gồm có những gì ?

CloudFormation : một dịch vụ của AWS hỗ trợ việc quản lý, xây dựng các tài nguyên trên Amazon Web Service (AWS) một các tự động thông qua các APIs và Json templates. Tham khảo thêm ở đây.

Chức năng : cung cấp các tài nguyên cần thiết trên AWS cho dự án, trong ví dụ này chúng ta sẽ cần :

  • 01 EC2 instance để cài đặt Jenkins (CI server)
  • 01 ELB xử lý việc cân bằng tải
  • 01 RDS instance cho lưu trữ dữ liệu
  • 01 ECS cluster để chạy, điều phối các docker containers
  • 01 ECR registry để lưu trữ các docker images




Ansible : một công cụ, ngôi sao đang lên, trong việc quản lý cấu hình tự động cho các machines. Tham khảo thêm tại đây.

Chức năng : cung cấp việc cài đặt và thiết lập môi trường cũng như các packages cần thiết cho CI server :
  • Nginx với chức năng reverse proxy cho jenkins
  • Jenkins với chức năng CI server
  • Docker với chức năng build docker image
  • Aws CLI tương tác với ECS, ECR qua dòng lệnh

Jenkins : CI server, một sản phẩm mã nguồn mở giúp tự động hóa các công việc building, deploying các phần mềm, dự án. Tham khảo thêm tại đây.

Chức năng : cung cấp hõ trợ cấu hình chạy unit test, build, deploy cho dự án.

Docker : một công cụ giúp đóng gói và phân phối ứng dụng dễ dàng, đa nền tảng. Tham khảo thêm tại đây.

Chức năng : đóng gói và phân phối các ứng dụng thông qua các docker images.

ECS : EC2 Container Service. Một dịch vụ của AWS thực hiện việc điều phối, quản lý, liên kết các docker container để làm việc hiệu quả. Tham khảo thêm tại đây.

Chức năng : cung cấp việc vận hành và điều phối các docker containers.

ECR : EC2 Container Registry. Một dịch vụ của AWS để lưu trữ các docker images, chức năng tương tự như DockerHub. Từ đấy các hệ thống có thể lấy docker image theo yêu cầu.

Vậy các bộ phận trên phối hợp với nhau như thế nào ?


  1. Engineer push code tới git repository
  2. Jenkins định kỳ kiểm tra và pull code mới về
  3. Jenkins chạy Unit test
  4. Jenkins chạy docker build để đóng gói ứng dụng vào docker image
  5. Jenkins pushs docker image tới ECR
  6. Jenkins trigger deploy tới ECS để lấy docker image mới từ ECR


Các bước trên được thực hiện tuần tự cho tới khi tất cả các bước được hoàn thành tạo nên một chu trình khép kín CI.

Như vậy chúng ta đã có một mô hình tổng quát về CI tích hợp các công cụ có sẵn AWS, Docker, Jenkins, Ansible. Việc tích hợp CI sẽ đẩy nhanh quá trình phát hiện lỗi thông qua việc tự động hóa. Giúp cho người viết mã có thể sớm sửa lỗi, góp phần tăng tốc quá trình đưa những cập nhật mới của ứng dụng tới người dùng.

Chi tiết từng bước sẽ được tác giả tiếp tục cập nhật ở các bài viết tiếp theo. Rất mong nhận được ý kiến của bạn đọc

Bucket list của tôi

Trong tiếng anh có một thuật ngữ "bucket list", được định nghĩa như này: -  a number of experiences or achievements that a person ...