+69

Terraform Series - Bài 10 - CI/CD with Terraform Cloud and Zero-downtime deployments

Link bài viết gốc - Bài 10 - CI/CD với Terraform Cloud và triển khai Zero-downtime

Giới thiệu

Chào các bạn tới với series về Terraform, ở bài trước chúng ta đã tìm hiểu về Remote Backend với Terraform Cloud. Ở bài này chúng ta sẽ tìm hiểu cách sử dụng Terraform Cloud để xây dựng CI/CD cho infrastructure của ta. Sau đó chúng ta sẽ tìm hiểu một thuộc tính của Terraform mà giúp ta thực hiện Zero-downtime deployments.

image.png

CI/CD with Terraform Cloud

Như ta đã nói ở bài trước, khi ta tạo một workspaces trên Terraform Cloud thì sẽ có ba cách sử dụng là:

  • Version control system workflow.
  • CLI-driven workflow.
  • API-driven workflow.

Với CLI-driven workflow giúp ta trong việc xây dựng Remote Backend, còn Version control system workflow (VCS) sẽ giúp ta trong việc xây dựng luồng CI/CD.

Với Terraform Cloud VCS, việc xây dựng CI/CD rất dễ dàng, tất cả những gì chúng ta cần làm là tạo một github repository, kết nối repository đó tới Terraform Cloud, sau đó ta chỉ việc đẩy code lên github và Terraform Cloud sẽ thực hiện toàn bộ luồng CI/CD cho ta.

Create github repository

Oke, trước tiên các bạn tạo một repository trên github, đây là repository của mình cho ví dụ này https://github.com/hoalongnatsu/terraform-cloud-vcs-example. Sau đó đăng nhập vào Terraform Cloud, cách đăng ký tài khoản và cấu hình aws credentials các bạn xem ở bài trước, màn hình sau khi đăng nhập vào Terraform Cloud.

image.png

Create VCS Workspace

Ở trang Workspaces ta bấm New Workspaces, sau đó chọn Version control workflow.

image.png

Bước tiếp theo, chỗ Connect to a version control provider, các bạn bấm vào icon Github.

image.png

Sau khi bạn bấm vào icon Github và kết nối tới github của bạn, nó sẽ dẫn ta qua bước thứ ba là chọn repository, các bạn chọn repository mà các bạn tạo cho ví dụ này, repo của mình tên là terraform-cloud-vcs-example.

image.png

Sau đó nó sẽ dẫn ta qua bước cuối cùng, các bạn điền Workspace Name vào và bấm tạo workspace.

image.png

Đợi một chút để terraform cloud setup và bạn sẽ thấy workspace của ta hiện chữ Configuration uploaded successfully .

image.png

Oke, vậy là ta đã tạo workspace xong, bây giờ ta chỉ cần viết code và push nó lên github, Terraform Cloud VCS sẽ chạy và tạo infrastructure cho ta.

Implement CI/CD

Các bạn thêm 3 file sau vào repo.

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}
variable "region" {
  type = string
  default = "us-west-2"
}
provider "aws" {
  region = var.region
}

data "aws_ami" "ami" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }

  owners = ["099720109477"]
}

resource "aws_instance" "ansible_server" {
  ami           = data.aws_ami.ami.id
  instance_type = "t3.micro"
}

Commit code và push lên github.

git add .
git commit -m "init code"
git push

Sau đó ta quay lại UI của Terraform Cloud, các bạn bấm vào Action chọn Start new run.

image.png

Ta sẽ thấy Terraform Cloud in ra cho ta plan step, thay vì chạy câu lệnh CLI và thấy tất cả resource của ta in ta trên terminal. Thì Terraform Cloud sẽ in resource của ta trên UI, rất trực quan và dễ hiểu.

image.png

Kéo xuống phía dưới ta sẽ thấy có chỗ để chúng ta bấm apply. Ta có thể cấu hình bước này là auto luôn, nhưng đối với môi trường production ta không nên cho phép nó auto apply. Các bạn bấm Confirm & Apply.

image.png

Nhập vào comment, và bấm Confirm Plan.

image.png

Terraform Cloud sẽ trigger quá trình apply.

image.png

Đợi nó chạy xong.

image.png

Lúc này các bạn lên AWS Console thì sẽ thấy EC2 của ta đã được tạo.

Update resource

Bây giờ ta sẽ cập nhật lại instance_type của EC2 và push code lên lại github.

resource "aws_instance" "ansible_server" {
  ami           = data.aws_ami.ami.id
  instance_type = "t3.small" // t3.micro -> t3.small
}
git commit -am "update instance type"
git push

Lúc này bạn sẽ thấy Terraform Cloud tự động phát hiện code của ta đã thay đổi và trigger lại plan step mới.

image.png

Các bạn bấm Confirm & Apply.

image.png

Sau khi nó chạy xong ta sẽ thấy EC2 của ta được update lại với instance type mới.

Destroy resource

Khi xài Terraform Cloud để destroy cũng khá đơn giản. Các bạn bấm vào Settings, chọn Destruction and Deletion.

image.png

Sau đó ta chọn Delete from Terraform Cloud.

image.png

Nhập vào tên và bấn delete.

image.png

Nếu các bạn bấm Delete workspace thì resource của ta đã bị xóa đi. Nhưng lúc này các bạn chưa xóa vội nhé, ta sẽ để nó lại để làm ví dụ tiếp theo.

Zero-downtime deployment

Đối với EC2 của ta, khi ta thay đổi giá trị ami.

resource "aws_instance" "ansible_server" {
  ami           = data.aws_ami.ami.id // change here
  instance_type = "t3.small"
}

Vì ami của EC2 là một force-new attributes (ami, user_data), nên khi ta tiến hành quá trình apply thì resource EC2 hiện tại sẽ bị destroy và một thằng mới sẽ được tạo ra. Đây là hành động mặc định của Terraform đối với các resource mà có force-new attributes bị thay đổi. Điều này có thể dẫn tới hệ thống của ta bị downtime trong một khoảng thời gian dài.

image.png

Để tránh downtime trong trường hợp này, terraform cung cấp cho một meta argument tên là create_before_destroy.

Use create_before_destroy

Đây là một meta argument giúp ta giải quyết được vấn đề zero-downtime deployment khi ta thay đổi force-new attributes của một resource.

Thay vì Terraform sẽ hành động như mặc định là xóa resource trước rồi tạo resource mới sau, thì Terraform sẽ hành động ngược lại là sẽ tạo resource trước, kiểm tra resource đó được tạo xong rồi thì nó mới tiến hành xóa resource cũ.

Ta sử dụng thuộc tính create_before_destroy như sau, cập nhật lại main.tf

resource "aws_instance" "ansible_server" {
  ami           = data.aws_ami.ami.id
  instance_type = "t3.small"

  lifecycle {
    create_before_destroy = true
  }
}

Ta thêm một block là lifecycle, trong đó ta sẽ khai báo thuộc tính create_before_destroy là true. Ok bây giờ bạn commit code và đẩy lên github, confirm cho Terraform Cloud apply, quan sát trên AWS Console chỗ EC2 thì ta sẽ thấy lúc này một con EC2 mới sẽ được tạo ra trước sau đó con cũ mới bị xóa đi.

Considering when use create_before_destroy

Thuộc tính create_before_destroy có thể rất thuận tiện, nhưng ta cần nên lưu ý một điều là không phải lúc nào ta cũng có thể sử dụng thuộc tính này cho resource được, vì sẽ có một vài resource bị conflict.

Ví dụ như là đối với AWS thì S3 bucket là unique tên toàn bộ hệ thống của AWS, nên nếu ta dùng thuộc tính create_before_destroy với S3 thì nó sẽ bị lỗi, vì lúc này S3 bucket mới sẽ được tạo ra trước, nhưng bucket name của nó sẽ giống y như thằng cũ nên ta sẽ gặp lỗi ngay.

Vì lý do trên nên ta cần xem xét cẩn thận khi dùng create_before_destroy, ta phải xác định rõ resource nào ta có thể dùng create_before_destroy cho nó còn resource nào thì không thể dùng.

No zero-downtime deployment

Tuy gọi là zero-downtime deployment, nhưng không phải lúc nào ta cũng có thể thực hiện việc này hoàn toàn được. Vì zero-downtime deployment là một vấn đề cần rất nhiều thứ để giải quyết và chỉ có thể áp dụng được với một số resource, như là cập nhật lại các resource mà chứa application, chứ không phải lúc nào ta cũng có thể áp dụng được zero-downtime deployment cho toàn bộ resource trong hệ thống của ta được.

Ví dụ đơn giản nhất là dịch vụ database của AWS là RDS, khi ta thay đổi instance_type của nó thì ta không thể sử dụng thuộc tính create_before_destroy để thực hiện zero-downtime deployment được, vì lúc này RDS của ta nó đâu có bị xóa và tạo lại đâu, nó chỉ cập nhật lại instance_type và bị downtime mà thôi.

Tất nhiên là cũng sẽ có cách để triển khai zero-downtime deployment cho database được, nhưng quá trình thực hiện sẽ rất phức tạp và cần kết hợp nhiều công cụ khác nhau chứ không thể chỉ dùng Terraform được.

Ở bài tiếp theo mình sẽ nói về một khái niệm mà có thể giúp ta thực hiện zero-downtime deployment cho database được, là blue/green deployment. Và cũng sẽ làm một ví dụ về blue/green deployment cho autoscaling group, đây là một trong những cách để giảm thiểu thời gian downtime cho hệ thống.

Kết luận

Vậy là ta đã tìm hiểu xong về cách thực hiện CI/CD với Terraform Cloud, và một cách đơn giản để thực hiện zero-downtime deployment cho resource của ta. Nếu có thắc mắc hoặc cần giải thích rõ thêm chỗ nào thì các bạn có thể hỏi dưới phần comment. Hẹn gặp mọi người ở bài tiếp theo ta sẽ tìm hiểu về Blue/Green Deployment.

DevOps VN

Học DevOps tại các trung tâm uy tín.

Kiến thức dinh dưỡng IT.

Ủng hộ trang tại đây.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí