【问题标题】:Terraform aws_instance - changing volume_sizeTerraform aws_instance - 更改 volume_size
【发布时间】:2021-07-16 12:44:53
【问题描述】:

我正在尝试为我的 ami ami-0d013c5896434b38a 增加根卷的大小 - 我正在使用 terraform 来配置它。

澄清一下 - 我只有 1 个实例。而且我想确保如果我需要增加磁盘空间,我不必先破坏机器。弹性 (EC2) 是我相信它是可行的理由。

有人知道这是否可行吗?是的,我可以简单地做terraform plan 并做一个试运行,但只是仔细检查。

【问题讨论】:

  • 您是否尝试过进行更改?计划显示了什么?

标签: amazon-web-services amazon-ec2 terraform


【解决方案1】:

我正在运行 terraform 1.0.1,并且想将我的 volume_size 从 20gb 更改为 30gb。

运行后terraform apply

[...]
# aws_instance.typo3_staging_1 will be updated in-place
~ resource "aws_instance" "staging_1" {
    id                          = "i-0eb2f8af6c8ac4125"
    tags                        = {
    "Name" = "Staging 1"
    "Team" = "DevOps"
  }
  # (28 unchanged attributes hidden)

  ~ root_block_device {
      tags                  = {}
    ~ volume_size           = 20 -> 30
    # (8 unchanged attributes hidden)
  }
  # (4 unchanged blocks hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
[...]

我看到 terraform 不会破坏系统。现在一个简单的“是”改变音量。约 33 秒后,root_block_device 已更改。

在 ec2 上的登录显示没有任何更改。 df 显示旧的 20GB 大小的根分区。但是一个简单的sudo reboot 将磁盘空间增加了 10gb,而不会破坏当前系统。该实例上的所有 docker 容器都按预期运行。完美。

我对此类 aws_instance 的 terraform 资源配置是:

resource "aws_instance" "staging_1" {

  instance_type = "t3.medium"
  ebs_optimized = true

  ami                    = "ami-001183208be54f75c"
  key_name               = aws_key_pair.master_key.key_name
  subnet_id              = aws_subnet.web_development_private_a.id
  vpc_security_group_ids = [aws_security_group.ec2_staging.id]

  root_block_device {
    volume_size = 30 # in GB <<----- I increased this!
    volume_type = "gp3"
    encrypted   = true
    kms_key_id  = data.aws_kms_key.customer_master_key.arn
  }

  # This is for T3 only (doesn't apply to M5/R5/...)
  # standard: Baseline of 20% or 30% CPU. Short bursts of 100% CPU are possible, but under a budget. Throttled, if budget is 0.
  # unlimited: Always 100% CPU possible, but costs are higher, if over burst budget.
  credit_specification {
    cpu_credits = "unlimited"
  }

  metadata_options {
    http_endpoint = "enabled"
    http_tokens   = "required"
  }

  lifecycle {
    prevent_destroy = true
  }

  tags = {
    Name = "Staging 1"
    Team = "DevOps"
  }
  volume_tags = {
    Name = "Staging 1"
    Team = "DevOps"
  }
}

【讨论】:

    【解决方案2】:

    它可以通过AWS Console or AWS CLI 实现,但不能通过 Terraform,基于快速测试。

    将 aws_instance 定义(如下面的定义)中的 volume_size 参数从 10 更改为 20 会导致实例的销毁/重新创建。使用 terraform 0.15.0

    如果您需要继续使用 Terraform 管理实例,请考虑以下选项:(1) 在 Terraform(aws 控制台或 CLI)之外执行修改,以及 (2) 将修改后的资源重新导入 terraform。

    在答案的第二部分中,我描述了一个简单的示例,该示例将通过控制台修改的 aws_instance 的状态重新导入 Terraform。 免责声明:在非生产环境中进行适当测试后,您需要自担风险。仔细阅读terraform import 命令文档中的警告

    在 Terraform 中测试 EBS 修改 - 需要替换实例

    resource "aws_instance" "testebs" {
      availability_zone           = local.aznames[0]
      ami                         = data.aws_ami.ubuntu.id
      instance_type               = "t2.micro"
      associate_public_ip_address = true
      key_name                    = "zzzzzzzz"
      ebs_block_device {
        device_name = "/dev/sda1"
        volume_size = 20
      }
    }
    

    我粘贴在完整配置和 terraform 计划的输出下方。 ami 是 eu-west-1 的最新 ubuntu 20.04,而不是原始问题中的那个。

    文件 ebstest.tf

    terraform {
      required_version = "~> 0.15.0"
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 3.0"
        }
      }
    }
    
    provider "aws" {
      region  = "eu-west-1"
      profile = "xxxxxxx"
    }
    
    data "aws_ami" "ubuntu" {
      most_recent = true
      filter {
        name = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
      }
      filter {
        name   = "virtualization-type"
        values = ["hvm"]
      }
    
      filter {
        name   = "root-device-type"
        values = ["ebs"]
      }
      owners = ["099720109477"] # Canonical
    }
    
    data "aws_availability_zones" "available" {
      state = "available"
    }
    locals {
      aznames = data.aws_availability_zones.available.names
    }
    
    resource "aws_instance" "testebs" {
      availability_zone           = local.aznames[0]
      ami                         = data.aws_ami.ubuntu.id
      instance_type               = "t2.micro"
      associate_public_ip_address = true
      key_name                    = "zzzzzzzz"
      ebs_block_device {
        device_name = "/dev/sda1"
        volume_size = 20
      }
      tags = {
        Name = "testebs-${local.aznames[0]}"
      }
    }
    

    地形计划的输出:

    $ terraform plan
    aws_instance.testebs: Refreshing state... [id=i-0e1fededb2e432a98]
    
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
    -/+ destroy and then create replacement
    
    Terraform will perform the following actions:
    
      # aws_instance.testebs must be replaced
    -/+ resource "aws_instance" "testebs" {
          ~ arn                          = "arn:aws:ec2:eu-west-1:xxxxxxxxxxxxx:instance/i-0e1fededb2e432a98" -> (known after apply)
          ~ cpu_core_count               = 1 -> (known after apply)
          ~ cpu_threads_per_core         = 1 -> (known after apply)
          - disable_api_termination      = false -> null
          - ebs_optimized                = false -> null
          - hibernation                  = false -> null
          + host_id                      = (known after apply)
          ~ id                           = "i-0e1fededb2e432a98" -> (known after apply)
          ~ instance_state               = "running" -> (known after apply)
          ~ ipv6_address_count           = 0 -> (known after apply)
          ~ ipv6_addresses               = [] -> (known after apply)
          - monitoring                   = false -> null
          + outpost_arn                  = (known after apply)
          + password_data                = (known after apply)
          + placement_group              = (known after apply)
          ~ primary_network_interface_id = "eni-0a923724fec1e76ce" -> (known after apply)
          ~ private_dns                  = "ip-172-31-13-57.eu-west-1.compute.internal" -> (known after apply)
          ~ private_ip                   = "172.31.13.57" -> (known after apply)
          ~ public_dns                   = "ec2-3-250-102-86.eu-west-1.compute.amazonaws.com" -> (known after apply)
          ~ public_ip                    = "3.250.102.86" -> (known after apply)
          ~ secondary_private_ips        = [] -> (known after apply)
          ~ security_groups              = [
              - "default",
            ] -> (known after apply)
          ~ subnet_id                    = "subnet-192e767f" -> (known after apply)
            tags                         = {
                "Name" = "testebs-eu-west-1a"
            }
          ~ tenancy                      = "default" -> (known after apply)
          ~ vpc_security_group_ids       = [
              - "sg-d7dc5a9a",
            ] -> (known after apply)
            # (7 unchanged attributes hidden)
    
          - credit_specification {
              - cpu_credits = "standard" -> null
            }
    
          + ebs_block_device { # forces replacement
              + delete_on_termination = true
              + device_name           = "/dev/sda1"
              + encrypted             = (known after apply)
              + iops                  = (known after apply)
              + kms_key_id            = (known after apply)
              + snapshot_id           = (known after apply)
              + throughput            = (known after apply)
              + volume_id             = (known after apply)
              + volume_size           = 20
              + volume_type           = (known after apply)
            }
          - ebs_block_device { # forces replacement
              - delete_on_termination = true -> null
              - device_name           = "/dev/sda1" -> null
              - encrypted             = false -> null
              - iops                  = 100 -> null
              - snapshot_id           = "snap-0f4b18aebb4264157" -> null
              - tags                  = {} -> null
              - throughput            = 0 -> null
              - volume_id             = "vol-01eade74ebeba666f" -> null
              - volume_size           = 10 -> null
              - volume_type           = "gp2" -> null
            }
    
          ~ enclave_options {
              ~ enabled = false -> (known after apply)
            }
    
          + ephemeral_block_device {
              + device_name  = (known after apply)
              + no_device    = (known after apply)
              + virtual_name = (known after apply)
            }
    
          ~ metadata_options {
              ~ http_endpoint               = "enabled" -> (known after apply)
              ~ http_put_response_hop_limit = 1 -> (known after apply)
              ~ http_tokens                 = "optional" -> (known after apply)
            }
    
          + network_interface {
              + delete_on_termination = (known after apply)
              + device_index          = (known after apply)
              + network_interface_id  = (known after apply)
            }
    
          ~ root_block_device {
              ~ delete_on_termination = true -> (known after apply)
              ~ device_name           = "/dev/sda1" -> (known after apply)
              ~ encrypted             = false -> (known after apply)
              ~ iops                  = 100 -> (known after apply)
              + kms_key_id            = (known after apply)
              ~ tags                  = {} -> (known after apply)
              ~ throughput            = 0 -> (known after apply)
              ~ volume_id             = "vol-01eade74ebeba666f" -> (known after apply)
              ~ volume_size           = 10 -> (known after apply)
              ~ volume_type           = "gp2" -> (known after apply)
            }
        }
    
    Plan: 1 to add, 0 to change, 1 to destroy.
    

    通过 AWS 控制台测试修改并从 terraform 导入资源(参见上面的免责声明/警告)。

    1. 按照答案的上一部分创建具有 10G 卷的实例。
    2. Modify EBS volume 在 AWS 控制台中大小为 20G。 (没有在操作系统级别扩展音量——读者练习:D)
    3. 列出状态文件中的 Terraform 项目并选择要删除其 状态 的 aws_instance 资源
    $ terraform state list
    data.aws_ami.ubuntu
    data.aws_availability_zones.available
    aws_instance.testebs
    
    1. 删除 aws_instance 资源的状态 (terraform state rm)。
    $ terraform state rm aws_instance.testebs
    Removed aws_instance.testebs
    Successfully removed 1 resource instance(s).
    
    1. 使用 terraform import,使用修改后的 ec2 实例的 instance-id 导入 aws_resource
    $ terraform import aws_instance.testebs  i-xxxxxxxxxxxxxxxx
    aws_instance.testebs: Importing from ID "i-xxxxxxxxxxxxxxxx"...
    aws_instance.testebs: Import prepared!
      Prepared aws_instance for import
    aws_instance.testebs: Refreshing state... [id=i-xxxxxxxxxxxxxxxx]
    
    Import successful!
    
    The resources that were imported are shown above. These resources are now in your Terraform state and will henceforth be managed by Terraform.
    
    1. 验证 terraform 是否可以正确管理导入的实例(通过 terraform 修改实例并验证行为)

    【讨论】:

    • 我认为我的问题是我已经有一个 EC2 实例正在运行 - 所以如果我添加 ebs_block_device 它会破坏它 - 我在这里没有太多选择,因为我需要使用 Terraform。
    • 如果您的整体环境和策略允许,一个选项是通过控制台修改 EBS 大小,并使用“terraform import”将完整的 aws 资源导入到新配置中。我已经用导入示例修改了上面的答案。
    • 在添加 root_block_device{} 块并适当设置 volume_size 时,它​​对我有用。它也适用于 Terraform 0.12.x。之后需要手动增加根分区和文件系统大小:docs.aws.amazon.com/AWSEC2/latest/UserGuide/…
    • 这是旧东西。最近的 terraform 版本不再破坏实例。
    【解决方案3】:

    ebs_block_device -(可选)一个或多个配置块以及附加 EBS 块设备以附加到实例。块设备配置仅适用于资源创建。

    因此,根据文档,ebs_block_device 只能在创建资源期间应用。在您的情况下,它是一个需要重新创建的 EC2 实例。

    【讨论】:

    • OP 实际上是在询问 root_block_device,而不是 ebs_block_device。使用最近的 terraform 版本,您可以在不破坏任何内容的情况下调整根目录的大小。
    猜你喜欢
    • 2019-06-28
    • 2021-12-10
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 2021-11-13
    • 2018-07-09
    • 2020-02-21
    相关资源
    最近更新 更多