+24

Terraform Series - Bài 15 - Automating Terraform with Jenkins

Link bài viết gốc: Bài 15 - Xây dựng CI/CD với Jenkins

Chào các bạn tới với series về Terraform, ở bài trước chúng ta đã nói về cách sử dụng Terraform với Gitlab CI. Ở bài này chúng ta sẽ tìm hiểu về cách sử dụng Terraform với Jenkins để thiết lập CI/CD cho infrastructure trên AWS.

image.png

Jenkins là một công cụ CI/CD rất phổ biến và được nhiều người sử dụng.

Prepare the environment

Trước khi ta tiến hành viết code cho Terraform và file CI/CD, ta sẽ cần chuẩn bị các thứ sau để Terraform có thể chạy được trong Jenkins.

Github repository

Ở bài này mình chỉ tập trung hướng dẫn Jenkins xài với Terraform thế nào, nên mình sẽ không hướng dẫn cách cấu hình tự động trigger CI/CD với Jenkins và Github nhé, các bạn có thể đọc ở bài này How To Set Up Continuous Integration With Git and Jenkins?.

Ta tạo một github repository để chứa source code, sau đó ta kết nối Jenkins với repository này để chạy CI/CD. Source code mà mình sẽ dùng ở bài này https://github.com/hoalongnatsu/terraform-series-jenkins-example, các bạn nhớ tạo public repo nha.

Sau đó các bạn tạo project ở trên Jenkins, đặt tên nó là terraform-jenkins, chọn kiểu Pipeline.

image.png

Bấm qua tab Pipeline và các bạn điền vào như bên dưới.

image.png

Sau đó bạn bấm save.

AWS Credentials

Tiếp theo vì ta xài Terraform với AWS nên ta cần cấu hình AWS Credentials ở trên Jenkins cho Terraform. Các bạn theo hướng dẫn này để tạo IAM user với quyền AdministratorAccess: Creating your first IAM admin user and user group.

Sau đó các bạn tạo secret key cho IAM user ở trên và quay trở lại Jenkins. Ở menu Jenkins chọn Manage Jenkins -> Manage Credentials.

image.png

Ở mục Stores scoped to Jenkins chọn Jenkins.

image.png

Chọn Global credentials.

image.png

Chọn Add Credentials, tiếp đó nó sẽ hiện form cho ta thêm Credentials vào.

image.png

  1. Ở trường Kind các bạn chọn Secret text.
  2. Trường Scope các bạn để mặc định.
  3. Trường Secret các bạn điền vào giá trị của của AWS_ACCESS_KEY_ID.
  4. Trường ID là tên của secret, ta đặt tên cho nó là aws-secret-key-id.
  5. Trường Description các bạn nhập gì cũng được.

Tương tự các bạn tạo một Secret text khác để chứa giá trị của AWS_SECRET_ACCESS_KEY và đặt tên cho nó là aws-secret-access-key.

image.png

S3 Backend

Tiếp theo ta sẽ tạo S3 Backend để lưu trữ terraform state thay vì dùng cache của Jenkins, nếu các bạn muốn hiểu kĩ hơn về S3 Backend thì đọc Bài 7 - Terraform Backend: S3 Standard Backend nhé.

Clone repo sau https://github.com/hoalongnatsu/terraform-series, di chuyển tới bai-14/s3-backend, ta chạy các câu sau để tạo S3 Backend.

terraform init
terraform apply -auto-approve

Khi terraform chạy xong, nó sẽ in ra cho ta các giá trị cần dùng cho S3 Backend.

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

Outputs:

config = {
  "bucket" = "terraform-series-s3-backend"
  "dynamodb_table" = "terraform-series-s3-backend"
  "region" = "us-west-2"
  "role_arn" = "arn:aws:iam::112337013333:role/Terraform-SeriesS3BackendRole"
}

Copy lại các giá trị này nhé 😁.

Integrate Terraform with Jenkins

Để chạy Terraform trong Jenkins thì ta có một vài cách là:

  1. Cài Terraform lên trên build agent.
  2. Sử dụng Docker container.
  3. Sử dụng Terraform plugin.

Ta sẽ sử dụng cách thứ ba trong bài này, di chuyển tới Manage Jenkins -> Manage Plugins, tìm Terraform Plugin và bấm install.

image.png

Sau đó các bạn truy cập Manage jenkins -> Global Tool Configuration, kiếm phần Terraform và cấu hình nó như sau.

image.png

Ta đã chuẩn bị hết tất cả những thứ cần thiết, tiếp theo ta sẽ tiến hành viết code Terraform và CI/CD nào.

Implement CI/CD

Tạo một folder và một file tên là main.tf.

terraform {
  backend "s3" {
    bucket         = "terraform-series-s3-backend"
    key            = "terraform-jenkins"
    region         = "us-west-2"
    encrypt        = true
    role_arn       = "arn:aws:iam::<ACCOUNT_ID>:role/Terraform-SeriesS3BackendRole"
    dynamodb_table = "terraform-series-s3-backend"
  }
}

provider "aws" {
  region = "us-west-2"
}

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" "server" {
  ami           = data.aws_ami.ami.id
  instance_type = "t3.micro"

  lifecycle {
    create_before_destroy = true
  }

  tags = {
    Name = "Server"
  }
}

output "public_ip" {
  value = aws_instance.server.public_ip
}

Để cấu hình S3 Backend thì ta config như sau.

terraform {
  backend "s3" {
    bucket         = "terraform-series-s3-backend"
    key            = "terraform-jenkins"
    region         = "us-west-2"
    encrypt        = true
    role_arn       = "arn:aws:iam::<ACCOUNT_ID>:role/Terraform-SeriesS3BackendRole"
    dynamodb_table = "terraform-series-s3-backend"
  }
}

Đây là các giá trị được in ra từ bai-14/s3-backend ở trên, các bạn nhớ sửa <ACCOUNT_ID> thành account id của các bạn thì nó mới chạy được nhé.

Tiếp theo ta tạo Jenkinsfile để định nghĩa các đoạn script mà CI/CD sẽ thực thi.

pipeline {
  agent any

  tools {
    terraform 'terraform'
  }

  environment {
    AWS_ACCESS_KEY_ID     = credentials('aws-secret-key-id')
    AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key')
  }

  stages {
    stage('Init Provider') {
      steps {
        sh 'terraform init'
      }
    }
    stage('Plan Resources') {
      steps {
        sh 'terraform plan'
      }
    }
    stage('Apply Resources') {
      input {
        message "Do you want to proceed for production deployment?"
      }
      steps {
        sh 'terraform apply -auto-approve'
      }
    }
  }
}

Để sử dụng terraform trong pipeline, ta dùng thuộc tính:

tools {
  terraform 'terraform'
}

Đây là global tool mà ta đã cấu hình ở trên khi cài Terraform Plugin. Và để sử dụng AWS Credentials ta dùng hai thộc tính sau:

environment {
  AWS_ACCESS_KEY_ID     = credentials('aws-secret-key-id')
  AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key')
}

Hàm credentials sẽ được dùng để lấy giá trị của Secret text mà ta đã tạo ở trên. Các đoạn code còn lại là để chạy Terraform, gồm có bước init, plan và deploy.

Đoạn code phần deploy sẽ khác một chút, nó sẽ có thêm thuộc tính input như sau :

input {
  message "Do you want to proceed for production deployment?"
}

Ta sử dụng thuộc tính này để làm tính năng manual approve. Ta sẽ không cho CI/CD tự động chạy terraform apply, mà ta cần review các resource nào sẽ được tạo ra trước (ở phần plan), nếu ta ok thì ta mới bấm confirm để nó apply.

Oke, giờ ta push code lên github. Sau đó ta truy cập vào Jenkins để trigger CI/CD nào 😁. Đây là giao diện pipeline cũ của Jenkins.

image.png

Các bạn bấm vào Open Blue Ocean để chuyển qua giao diện mới, vì mình thấy nó đẹp hơn thôi :))))), các bạn có thể dùng giao diện cũ.

image.png

Đây là giao diện mới của Jenkins, các bạn bấm Run để nó trigger Job nào.

image.png

Bấm vào Job để xem logs.

image.png

Như bạn thấy thì phần Apply Resources nó sẽ ở trạng thái chờ, sau khi review phần plan xong thấy ok thì các bạn bấm Proceed.

Kiểm tra AWS Console bạn sẽ thấy EC2 đã được tạo ra bằng CI/CD thành công 😁.

Kết luận

Vậy là ta đã tìm hiểu xong cách sử dụng Terraform với Jenkins. 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.

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í