Giới thiệu
Ở bài trước chúng ta đã tìm hiểu về cách lập trình trong Terraform. Ở bài này chúng ta sẽ làm một ví dụ thực tế với Terraform là triển khai một trang web lên S3 và học thêm một số hàm đơn giản.
Mục lục
- Tạo S3
- Hàm File
- Tải tệp tin lên S3 bằng Terraform
- Hàm Fileset
- Locals block
- Kết luận
- Bài viết cùng series “Chinh phục Terraform”
Tạo S3
Tạo thư mục mới và tạo một tệp tin main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.44.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
resource "aws_s3_bucket" "static" {
bucket = "terraform-series-bai3"
force_destroy = true
tags = local.tags
}
resource "aws_s3_bucket_acl" "static" {
bucket = aws_s3_bucket.static.id
acl = "public-read"
}
resource "aws_s3_bucket_website_configuration" "static" {
bucket = aws_s3_bucket.static.bucket
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
data "aws_iam_policy_document" "static" {
statement {
actions = ["s3:GetObject"]
resources = ["${aws_s3_bucket.static.arn}/*"]
principals {
type = "*"
identifiers = ["*"]
}
}
}
resource "aws_s3_bucket_policy" "static" {
bucket = aws_s3_bucket.static.id
policy = data.aws_iam_policy_document.static.json
}Chạy terraform init và terraform apply, sau đó bạn sẽ thấy S3 Bucket của ta trên AWS.
Ở tệp tin trên bạn sẽ thấy là phần policy nó hơi dài và nó là dạng chuỗi JSON nên tệp tin cấu hình của ta hơi khó nhìn, ta có thể tách phần Policy ra một tệp tin riêng, và dùng hàm trong Terrafrom để đọc Policy đó lên.
Hàm File
Hàm file sẽ giúp ta tải nội dung của một tệp tin nào đó vào bên trong Terraform. Tạo một tệp tin tên là s3_static_policy.json và sao chép đoạn JSON trên vào.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::terraform-series-bai3/*"
]
}
]
}Cập nhật lại main.tf.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.44.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
resource "aws_s3_bucket" "static" {
bucket = "terraform-series-bai3"
force_destroy = true
tags = local.tags
}
resource "aws_s3_bucket_acl" "static" {
bucket = aws_s3_bucket.static.id
acl = "public-read"
}
resource "aws_s3_bucket_website_configuration" "static" {
bucket = aws_s3_bucket.static.bucket
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
resource "aws_s3_bucket_policy" "static" {
bucket = aws_s3_bucket.static.id
policy = file("s3_static_policy.json")
}Như bạn thấy thì khi để Policy vào một tệp tin khác và dùng hàm file để tải lên thì tệp tin Terraform của ta nhìn gọn hơn nhiều. Chạy lại câu lệnh terraform apply.
terraform apply -auto-approveKhi ta dùng S3 ở chế độ Static Website, thì URL của trang web của ta sẽ có định dạng http://<bucket-name>.s3-website-<region>.amazonaws.com.
Ở bài này ta tạo Bucket có tên là terraform-series-bai3 và ở Region us-west-2 thì URL sẽ là http://terraform-series-bai3.s3-website-us-west-2.amazonaws.com. Tuy nhiên bây giờ nếu bạn truy cập vào thì sẽ không có gì cả, vì ta chưa để bất kì tệp tin nào lên trên S3.
Tiếp theo ta sẽ tiến hành tải tệp tin lên S3 Bucket để hosting trang web của ta. Các bạn tải source code ở đây Static Web, sau khi tải xong thì nhớ xóa tệp .git đi.
rm -rf static-web/.gitThư mục của ta hiện tại sẽ như sau.
.
├── main.tf
├── s3_static_policy.json
├── static-web
│ ├── README.md
│ ├── article-details.html
...
├── terraform.tfstateĐể tải tệp tin lên S3 thì ta sẽ dùng AWS CLI.
aws s3 cp static-web s3://terraform-series-bai3 --recursiveBây giờ bạn truy cập URL http://terraform-series-bai3.s3-website-us-west-2.amazonaws.com thì bạn sẽ thấy trang web của ta.
Rất đơn giản và khi làm thực tế thì ta nên sử dụng cách này, tuy nhiên hiện tại chúng ta đang học Terraform nên mình sẽ hướng dẫn các bạn sử dụng Terraform để tải tệp tin lên trên S3.
Tải tệp tin lên S3 bằng Terraform
Để tải tệp tin lên S3 thì ta sẽ dùng resource là aws_s3_object. Cập nhật lại tệp tin main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.44.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
resource "aws_s3_bucket" "static" {
bucket = "terraform-series-bai3"
force_destroy = true
tags = local.tags
}
resource "aws_s3_bucket_acl" "static" {
bucket = aws_s3_bucket.static.id
acl = "public-read"
}
resource "aws_s3_bucket_website_configuration" "static" {
bucket = aws_s3_bucket.static.bucket
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
resource "aws_s3_bucket_policy" "static" {
bucket = aws_s3_bucket.static.id
policy = file("s3_static_policy.json")
}
locals {
mime_types = {
html = "text/html"
css = "text/css"
ttf = "font/ttf"
woff = "font/woff"
woff2 = "font/woff2"
js = "application/javascript"
map = "application/javascript"
json = "application/json"
jpg = "image/jpeg"
png = "image/png"
svg = "image/svg+xml"
eot = "application/vnd.ms-fontobject"
}
}
resource "aws_s3_object" "object" {
for_each = fileset(path.module, "static-web/**/*")
bucket = aws_s3_bucket.static.id
key = replace(each.value, "static-web", "")
source = each.value
etag = filemd5("${each.value}")
content_type = lookup(local.mime_types, split(".", each.value)[length(split(".", each.value)) - 1])
}Tạm thời thì các bạn chưa cần hiểu code phần aws_s3_object, phần mình muốn giới thiệu ở đây là hàm fileset.
Hàm Fileset
Ví dụ ta có thư mục như sau:
.
├── index.html
├── index.cssThì khi ta dùng hàm fileset(path.module, "*") ta sẽ có được data set như sau:
{
"index.html": "index.html",
"index.css" : "index.css"
}Với giá trị key và value là tên của tệp tin. Ở trên ta dùng hàm fileset và aws_s3_object resource để tải toàn bộ tệp tin trong thư mục static-web lên trên S3.
Locals block
Bạn sẽ thấy có một block nữa tên là locals, đây là block giúp ta khai báo một giá trị local trong tệp tin Terraform và có thể sử dụng lại được nhiều lần. Cú pháp như sau:
Không giống như variable block, ta cần khai báo kiểu dữ liệu thì locals block ta sẽ gán thẳng giá trị cho nó. Ví dụ như sau:
locals {
one = 1
two = 2
name = "max"
flag = true
}Để truy cập giá trị local thì ta dùng cú pháp local.<KEY>, ví dụ:
local.oneỞ trên là một vài cú pháp thông dụng mà ta hay sử dụng khi làm việc với Terraform.
Kết luận
Vậy là ta đã tìm hiểu xong cách dùng Terraform để triển khai một trang web lên trên S3, như bạn thấy thì cũng khá đơn giản. Điểm cần nhớ ở bài này là ta nên sử dụng locals block để lưu giá trị và sử dụng lại nhiều lần. Ở bài tiếp theo ta sẽ tìm hiểu một vấn đề rất quan trọng là Module trong Terraform.
Tác giả @Quân Huỳnh
First AI Journey for DevOps:
- PromptOps: From YAML to AI
- The DevOps AI Advantage
- The AIOps Book