Giới thiệu
Ở bài trước chúng ta đã nói về cách sử dụng Terraform với Gitlab CI. Trong bài này chúng ta sẽ tìm hiểu về cách xây dựng CI/CD cho Terraform với Jenkins.
Jenkins là một công cụ CI/CD rất phổ biến và được nhiều người sử dụng.
Chuẩn bị
Trước khi ta tiến hành viết code cho Terraform và tệp tin CI/CD, ta sẽ cần chuẩn bị các thứ sau để Terraform có thể chạy được trong Jenkins.
Github
Ở bài này mình chỉ hướng dẫn xài Jenkins với Terraform thế nào. Chi tiết hơn 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ế độ Public) để chứa source code và kết nối tới Jenkins. Source code sử dụng ở bài này Terraform Jenkins Example. Tiếp theo tạo Project ở trên Jenkins với tên terraform-jenkins
, chọn kiểu Pipeline.
Bấm qua mục Pipeline và điền vào như bên dưới:
Bấm lưu.
AWS Credentials
Vì ta xài Terraform với AWS nên ta cần cấu hình AWS Credentials ở trên Jenkins cho Terraform. 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 đó tạo Secret Key cho IAM User ở trên. Ở mục Jenkins chọn Manage Jenkins -> Manage Credentials.
Ở mục Stores scoped to Jenkins chọn Jenkins.
Chọn Global credentials.
Chọn Add Credentials.
- Ở trường Kind chọn Secret Text
- Trường Scope để mặc định
- Trường Secret điền vào giá trị của của
AWS_ACCESS_KEY_ID
- Trường ID là tên của Secret, đặt tên cho nó là
aws-secret-key-id
- Trường Description nhập gì cũng được
Tương tự tạo 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
.
S3 Backend
Tiếp theo ta sẽ tạo S3 Backend để lưu trữ Terraform State, xem kĩ hơn về S3 Backend ở này này Sử dụng S3 Standard Backend vào dự án. Tải Repo sau về Terraform Series, di chuyển tới bai-14/s3-backend
và chạy các câu lệnh sau:
terraform init
terraform apply -auto-approve
Khi terraform chạy xong các giá trị của S3 Backend sẽ được hiển thị.
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"
}
Sao chép lại các giá trị này 😁.
Kết hợp với Terraform
Để chạy Terraform trong Jenkins ta có các cách sau:
- Cài Terraform lên trên Build Agent
- Sử dụng Docker Container
- 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.
Sau đó truy cập Manage jenkins -> Global Tool Configuration, kiếm phần Terraform và cấu hình nó như sau:
Tiếp theo ta tiến hành xây dựng luồng CI/CD.
CI/CD
Tạo một tệp tin 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 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"
}
}
Sửa lại <ACCOUNT_ID>
với ID của bạn. Tiếp theo ta tạo Jenkinsfile
:
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 thì ta dùng thuộc tính:
tools {
terraform 'terraform'
}
Đây là Global Tool 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:
environment {
AWS_ACCESS_KEY_ID = credentials('aws-secret-key-id')
AWS_SECRET_ACCESS_KEY = credentials('aws-secret-access-key')
}
Hàm Credentials được dùng để lấy giá trị của Secret Text mà ta đã tạo. 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ó có thêm thuộc tính input
:
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 xem trước các resource nào sẽ được tạo ra. Ta đẩy code lên Github, truy cập vào Jenkins để thực thi CI/CD. Đây là giao diện pipeline cũ của Jenkins.
Bấm vào Open Blue Ocean để chuyển qua giao diện mới vì nó đẹp hơn, các bạn có thể dùng giao diện cũ nếu chưa quen.
Bấm Run để nó thực thi Job.
Bấm vào Job để xem logs.
Phần Apply Resources
nó ở trạng thái chờ, sau khi xem phần plan
xong thấy ổn thì ta 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. Theo mình thì việc lựa chọn công cụ CI/CD nào phụ thuộc vào công ty và bạn có quen thuộc với nó không. Chứ đừng đọc mấy bài phân tích trên mạng, nó rất lan man mà cũng không rút ra được kết luận gì.
Nếu bài viết có gì sai hoặc cần cập nhật thì liên hệ Admin.
Tham gia nhóm chat của DevOps VN tại Telegram.
Kém tiếng Anh và cần nâng cao trình độ giao tiếp: Tại sao bạn học không hiệu quả?