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.
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-approve
Khi 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/.git
Thư 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 --recursive
Bâ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.css
Thì 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
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ả?