Tìm hiểu tính năng Terraform `taint`

Tìm hiểu tính năng Terraform taintCuongquach.com | Khi bạn sử dụng Terraform để quản lý các resource hạ tầng Cloud hay On-Premise. Bạn sẽ bắt gặp một tính năng được hỗ trợ bởi Terraform mang tên : taint .

terraform-taint-la-gi

Youtube Video

Terraform taint là gì ?

Terraform taint là một tính năng của chương trình Terraform được sử dụng để đánh dấu trạng thái của các resource trong file state quản lý bởi Terraform là tainted . Khi resource có trạng thái này sẽ được xoá bỏ và khởi tạo mới trong những lần apply kế tiếp.

Tính năng này sẽ không thay đổi hạ tầng mà Terraform quản lý, mà chỉ chỉnh sửa thông tin trạng thái resource trong file state . Khi resource ở trạng thái tainted, thì khi bạn chạy terraform plan để kiểm tra các sự thay đổi trong resource cấu hình sẽ thấy thông tin yêu cầu xoá và tạo mới.

Lưu ý, là với các resource có sử dụng thông tin phụ thuộc (dependency) thì khi một resource bị tainted và tạo mới lại thì resource phụ thuộc cũng sẽ bị xoá và tạo mới chung.

Các trường hợp sử dụng Terraform taint

  • Sử dụng taint để rolling deploy Auto Scaling Group của AWS cho Web Service chẳng hạn, vì Terraform không có hỗ trợ cơ chế rolling change cho ASG.
  • Rebuild lại một số resource mà không cần phải destroy toàn bộ các resource trong thư mục cấu hình.

Cú pháp:

terraform taint [options] address

Trong đó, phần address sẽ là địa chỉ định danh của resource trong file terraform.tfstate , có thể là ví dụ như dưới :

  • aws_instance.foo
  • aws_instance.bar[1]
  • aws_instance.baz[\”key\”]
  • module.foo.module.bar.aws_instance.qux

Lab thực hành Terraform taint

Giả sử mình tạo resource AWS VPC, PublicSubnet, Internet Gateway, RouteTable thuộc VPC đó.

# mkdir /opt/lab-vpc-tf/
# vi main.tf
provider "aws" {
  region = "ap-southeast-1"
}

data "aws_security_group" "default" {
  name   = "default"
  vpc_id = module.vpc.vpc_id
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.48.0"

  name = "simple-vpc-cuongquach-lab"

  cidr = "10.0.0.0/16"

  azs            = ["ap-southeast-1a"]
  public_subnets = ["10.0.101.0/24"]

  enable_ipv6        = false
  enable_nat_gateway = false
  single_nat_gateway = false
}

# export AWS_ACCESS_KEY_ID="xxxx"
# export AWS_SECRET_ACCESS_KEY="xxxx"
# export AWS_DEFAULT_REGION="ap-southeast-1"
# terraform init
#  terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
 <= read (data resources)

Terraform will perform the following actions:

  # data.aws_security_group.default will be read during apply
  # (config refers to values not yet known)
 <= data "aws_security_group" "default"  {
      + arn         = (known after apply)
      + description = (known after apply)
      + id          = (known after apply)
      + name        = "default"
      + tags        = (known after apply)
      + vpc_id      = (known after apply)
    }

  # module.vpc.aws_internet_gateway.this[0] will be created
  + resource "aws_internet_gateway" "this" {
      + arn      = (known after apply)
      + id       = (known after apply)
      + owner_id = (known after apply)
      + tags     = {
          + "Name" = "simple-vpc-cuongquach-lab"
        }
      + vpc_id   = (known after apply)
    }

  # module.vpc.aws_route.public_internet_gateway[0] will be created
  + resource "aws_route" "public_internet_gateway" {
      + destination_cidr_block     = "0.0.0.0/0"
      + destination_prefix_list_id = (known after apply)
      + egress_only_gateway_id     = (known after apply)
      + gateway_id                 = (known after apply)
      + id                         = (known after apply)
      + instance_id                = (known after apply)
      + instance_owner_id          = (known after apply)
      + local_gateway_id           = (known after apply)
      + nat_gateway_id             = (known after apply)
      + network_interface_id       = (known after apply)
      + origin                     = (known after apply)
      + route_table_id             = (known after apply)
      + state                      = (known after apply)

      + timeouts {
          + create = "5m"
        }
    }

  # module.vpc.aws_route_table.public[0] will be created
  + resource "aws_route_table" "public" {
      + id               = (known after apply)
      + owner_id         = (known after apply)
      + propagating_vgws = (known after apply)
      + route            = (known after apply)
      + tags             = {
          + "Name" = "simple-vpc-cuongquach-lab-public"
        }
      + vpc_id           = (known after apply)
    }

  # module.vpc.aws_route_table_association.public[0] will be created
  + resource "aws_route_table_association" "public" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # module.vpc.aws_subnet.public[0] will be created
  + resource "aws_subnet" "public" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "ap-southeast-1a"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "10.0.101.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = true
      + owner_id                        = (known after apply)
      + tags                            = {
          + "Name" = "simple-vpc-cuongquach-lab-public-ap-southeast-1a"
        }
      + vpc_id                          = (known after apply)
    }

  # module.vpc.aws_vpc.this[0] will be created
  + resource "aws_vpc" "this" {
      + arn                              = (known after apply)
      + assign_generated_ipv6_cidr_block = false
      + cidr_block                       = "10.0.0.0/16"
      + default_network_acl_id           = (known after apply)
      + default_route_table_id           = (known after apply)
      + default_security_group_id        = (known after apply)
      + dhcp_options_id                  = (known after apply)
      + enable_classiclink               = (known after apply)
      + enable_classiclink_dns_support   = (known after apply)
      + enable_dns_hostnames             = false
      + enable_dns_support               = true
      + id                               = (known after apply)
      + instance_tenancy                 = "default"
      + ipv6_association_id              = (known after apply)
      + ipv6_cidr_block                  = (known after apply)
      + main_route_table_id              = (known after apply)
      + owner_id                         = (known after apply)
      + tags                             = {
          + "Name" = "simple-vpc-cuongquach-lab"
        }
    }

Plan: 6 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

# terraform apply -auto-approve

Giờ chúng ta sẽ taint một Terraform resource đã được tạo.

# terraform taint -lock=true "module.vpc.aws_subnet.public[0]"
Resource instance module.vpc.aws_subnet.public[0] has been marked as tainted.

Lúc này nếu bạn coi file terraform.tfstate sẽ thấy cấu hình của resource aws_subnet.public index 0 có trạng thái là tainted.

...
{
  "module": "module.vpc",
  "mode": "managed",
  "type": "aws_subnet",
  "name": "public",
  "each": "list",
  "provider": "provider.aws",
  "instances": [
    {
      "index_key": 0,
      "status": "tainted",
...

Khi bạn chạy terraform plan sau khi taint sẽ thấy resource aws_subnet.public được yêu cầu xoá (destroy) và khởi tạo lại mới (create). Tương ứng với resource khác phụ thuộc module.vpc.aws_route_table_association.public sẽ bị liên đới do phụ thuộc.

# terraform plan
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.vpc.aws_route_table_association.public[0] must be replaced
-/+ resource "aws_route_table_association" "public" {
      ~ id             = "rtbassoc-0cc7a80a98940d3b7" -> (known after apply)
        route_table_id = "rtb-091b17ee78cd57e67"
      ~ subnet_id      = "subnet-0f1f64f4832440f95" -> (known after apply) # forces replacement
    }

  # module.vpc.aws_subnet.public[0] is tainted, so must be replaced
-/+ resource "aws_subnet" "public" {
      ~ arn                             = "arn:aws:ec2:ap-southeast-1:764510719561:subnet/subnet-0f1f64f4832440f95" -> (known after apply)
        assign_ipv6_address_on_creation = false
        availability_zone               = "ap-southeast-1a"
      ~ availability_zone_id            = "apse1-az2" -> (known after apply)
        cidr_block                      = "10.0.101.0/24"
      ~ id                              = "subnet-0f1f64f4832440f95" -> (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
        map_public_ip_on_launch         = true
      ~ owner_id                        = "764510719561" -> (known after apply)
        tags                            = {
            "Name" = "simple-vpc-cuongquach-lab-public-ap-southeast-1a"
        }
        vpc_id                          = "vpc-0a9ede37fb00766ee"
    }

Plan: 2 to add, 0 to change, 2 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Đơn giản dễ hiểu phải không nào .

Nguồn: https://cuongquach.com/

Previous articleCấu hình quy định phiên bản Terraform và Terraform Provider
Next articleEbook 11 điều cần biết khi thuê dịch vụ kiểm thử Pentest (PDF)
Bạn đang theo dõi website "https://cuongquach.com/" nơi lưu trữ những kiến thức tổng hợp và chia sẻ cá nhân về Quản Trị Hệ Thống Dịch Vụ & Mạng, được xây dựng lại dưới nền tảng kinh nghiệm của bản thân mình, Quách Chí Cường. Hy vọng bạn sẽ thích nơi này !