1) Prepare tools
1.1) Install terraform
Đầu tiên cần cài đặt terraform:
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" sudo apt-get update && sudo apt-get install terraform terraform -v
1.2) Install terragrunt
Giờ đến phần cài terragrunt:
bạn cần download: https://github.com/gruntwork-io/terragrunt/releases
wget https://github.com/gruntwork-io/terragrunt/releases/download/v0.38.7/terragrunt_linux_amd64 mv terragrunt_linux_amd64 terragrunt chmod u+x terragrunt mv terragrunt /usr/local/bin/terragrunt root@LP11-D7891:~/github/Terraform-Topics/terragrunt-ec2# terragrunt --version terragrunt version v0.38.7
Từ đó chúng ta đã cài thành công!
2) Provisioning EC2 by terragrunt
Để sử dụng được terragrunt bạn cần có 1 terraform module
mình sẽ tạo Ec2 thông qua terragrunt
https://registry.terraform.io/modules/terraform-aws-modules/ec2-instance/aws/latest
root@LP11-D7891:~/github/Terraform-Topics/terragrunt-ec2# cat dev/terragrunt.hcl terraform { source = "tfr:///terraform-aws-modules/ec2-instance/aws?version=4.0.0" } locals { env_vars = yamldecode( file("${find_in_parent_folders("common-environment.yaml")}"), ) } /*include { path = find_in_parent_folders() }*/ generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = <<EOF provider "aws" { profile = "default" region = "us-east-1" shared_credentials_files = ["/root/.aws/credentials"] } EOF } inputs = { ami = "ami-0767046d1677be5a0" instance_type = local.env_vars.locals.instance_type tags = { Name = "Terragrunt Tutorial: EC2" } }
Chỗ này là bạn sẽ source đến chỗ module:
terraform { source = "tfr:///terraform-aws-modules/ec2-instance/aws?version=4.0.0" }
Bạn define các environment thông qua yaml
ở đây mình muốn demo intance type
root@LP11-D7891:~/github/Terraform-Topics/terragrunt-ec2# cat common-environment.yaml locals: instance_type : "t2.micro"
Tiếp đến sử dụng khai báo locals để lấy các thông tin từ file common-environment.yaml
locals { env_vars = yamldecode( file("${find_in_parent_folders("common-environment.yaml")}"), ) }
Bạn có thể gen file bằng terragrunt:
provider.tf để authen với aws
generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = <<EOF provider "aws" { profile = "default" region = "us-east-1" shared_credentials_files = ["/root/.aws/credentials"] # access_key = "<insert_your_access_key>" # secret_key = "<insert_your_secret_key>" } EOF }
Vì chúng ta sử dụng module nên chúng ta sẽ có các input:
inputs = { ami = "ami-0767046d1677be5a0" instance_type = local.env_vars.locals.instance_type tags = { Name = "Terragrunt Tutorial: EC2" } }
OK giờ đi vào thử mục dev để chạy 1 vài câu lệnh
root@LP11-D7891:~/github/Terraform-Topics/terragrunt-ec2/dev# terragrunt init WARN[0000] No double-slash (//) found in source URL /terraform-aws-modules/ec2-instance/aws. Relative paths in downloaded Terraform code may not work. Initializing the backend... Initializing provider plugins... - Finding hashicorp/aws versions matching ">= 4.7.0"... - Installing hashicorp/aws v4.27.0... - Installed hashicorp/aws v4.27.0 (signed by HashiCorp) Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future. Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
terragrunt plan ... Plan: 1 to add, 0 to change, 0 to destroy. Changes to Outputs: + arn = (known after apply) + capacity_reservation_specification = (known after apply) + id = (known after apply) + instance_state = (known after apply) + ipv6_addresses = (known after apply) + outpost_arn = (known after apply) + password_data = (known after apply) + primary_network_interface_id = (known after apply) + private_dns = (known after apply) + private_ip = (known after apply) + public_dns = (known after apply) + public_ip = (known after apply) + tags_all = { + "Name" = "Terragrunt Tutorial: EC2" }
Bạn sẽ thấy là đang add thêm 1 cài j đó.
Có 1 chỗ này mình thấy terragrunt hơi ngáo!
khi mình chạy terragrunt apply thì nó chị nói là
ERRO[0007] Terraform invocation failed in /root/github/Terraform-Topics/terragrunt-ec2/dev/.terragrunt-cache/rD4h2xB9dby1GrIL6qYgf2gulHs/pfgqyj3TsBEWff7a1El6tYu6LEE prefix=[/root/github/Terraform-Topics/terragrunt-ec2/dev] ERRO[0007] 1 error occurred: * exit status 1
Thật là không biết bị lỗi gì?
phải chạy là terragrunt apply -auto-approve
thì mình mới biết là mình bị sai AMI
Sau khi chỉnh lại AMI thì đã tạo ngon
Mình có thao khảo 1 anh tây thì anh bảo các mà terragrunt việc khai báo biến dưới dạng YAML template có vẻ flexible hơn!
Đệch có vậy thôi à!
OK nếu có thời gian tìm hiểu mình sẽ giới thiệu thêm
Nếu bạn muốn xóa thì chạy terragrunt destroy -auto-approve
3) Remote state settings with Terragrunt
Bạn thấy đấy chúng ta cần lưu các file
https://terragrunt.gruntwork.io/docs/features/keep-your-remote-state-configuration-dry/#filling-in-remote-state-settings-with-terragrunt
generate "backend" { path = "backend.tf" if_exists = "overwrite_terragrunt" contents = <<EOF terraform { backend "s3" { bucket = "my-terraform-state" key = "${path_relative_to_include()}/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "my-lock-table" } } EOF }
Giải thích chỗ này ${path_relative_to_include()}
https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#path_relative_to_include
Nếu mà bạn run terragrunt.hcl trong folder là prod/mysql/terragrunt.hcl
Khi đó file terraform.tfstate trên S3 sẽ có đường dẫn như sau.
prod/mysql/terraform.tfstate
Explain về hình thực hoạt động
This instructs Terragrunt to create the file backend.tf
in the working directory (where Terragrunt calls terraform
) before it calls any of the Terraform commands, including init
. This allows you to inject this backend configuration in all the modules that includes the root file and have terragrunt
properly initialize the backend configuration with interpolated values.
Sau khi bạn đã cấu hinh terragrunt ở folder ngoài cùng xong bạn sẽ cần thêm lines này vào trong file terragrunt của các folder con.
include "root" { path = find_in_parent_folders() }
4) AWS authentication with Terragrunt
https://terragrunt.gruntwork.io/docs/features/aws-auth/#aws-credentials
Như link trên đã mô ta thì terragrunt sẽ auto load các AWS standard approach.
cách nhất mà bạn có thể sử dụng đó là dụng Environment
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
==> hiện tại mình sử dụng cách này để run bitbucket pipeline với terragrunt.
5) locals {} and get environment(env) then declare inside hcl file.
locals { aws_region = get_env("AWS_REGION") # environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) # branch = get_env("MODULE_BRANCH") } #https://registry.terraform.io/modules/terraform-aws-modules/dynamodb-table/aws terraform { source = "tfr:///terraform-aws-modules/dynamodb-table/aws?version=3.0.0" } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = <<EOF provider "aws" { region = "${local.aws_region}" } EOF }
6) Read value from other terragrunt file(.hcl)
Bạn sẽ thấy mình gọi nó ra
######file terragrunt-ec2/env.hcl ################## locals { ami = "ami-052efd3df9dad4825" } ######file terragrunt-ec2/dev/terragrunt.hcl ################## terraform { source = "tfr:///terraform-aws-modules/ec2-instance/aws?version=4.0.0" extra_arguments "common_vars" { commands = ["plan", "apply"] } } locals { env_vars_hcl = read_terragrunt_config(find_in_parent_folders("env.hcl")) env_vars = yamldecode( file("${find_in_parent_folders("common-environment.yaml")}"), ) } include "root" { path = find_in_parent_folders() } inputs = { ami = local.env_vars_hcl.locals.ami instance_type = local.env_vars.locals.instance_type tags = { Name = "Terragrunt Tutorial: EC2" } }
https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/
Mình vẫn chưa hiểu extra_arguments —> commands
Why do I use TerraGrunt?
Mình đọc được 1 vài command của facebook group
https://www.facebook.com/groups/devops.thuc.chien/permalink/2324966271018383/
Anh Le
Nếu resources ít + chỉ một vài environments thì em nghĩ cũng chưa cần Terragrunt. Em đã chia sẻ scale bên em cho anh rồi đó. Bên em dùng Terragrunt để đảm bảo infra cho các products được deploy giống nhau tầm 95%. Về lợi ích của Terragrunt thì lúc trước có 1 series trên Terragrunt blog mà em tìm lại không ra.
https://github.com/gruntwor…/knowledge-base/discussions/92: cái này có vẻ miêu tả rõ
https://transcend.io/blog/why-we-use-terragrunt/
Nhìn chung là DRY, mặc dù so với Terraform workspaces thì cần phải copy terragrunt.hcl files qua mỗi environments, nhưng phần inputs thì rất gọn. DRY cao nhất là nếu dùng https://terragrunt.gruntwork.io/docs/features/keep-your-terragrunt-architecture-dry/#using-include-to-dry-common-terragrunt-config gần như là tương tự Terraform workspaces (one code base for all environments)
Immutable infrastructure: có thể promote infra dần dần qua từng version để đảm bảo consistency. Cái này khá quan trọng khi bên em có 5 environments cho mỗi products. Cái nào chạy ổn ở dev/qa thì sẽ chạy được trên prod. https://blog.gruntwork.io/terragrunt-how-to-keep-your…
> One of the most important lessons we’ve learned from writing hundreds of thousands of lines of infrastructure code is that large modules should be considered harmful. That is, it is a Bad Idea to define all of your environments (dev, stage, prod, etc), or even a large amount of infrastructure (servers, databases, load balancers, DNS, etc), in a single Terraform module. Large modules are slow, insecure, hard to update, hard to code review, hard to test, and brittle (i.e., you have all your eggs in one basket).
Quote từ cái link trên.