Terraform 重新部署 EC2 实例

Posted

技术标签:

【中文标题】Terraform 重新部署 EC2 实例【英文标题】:Terraform redeploys EC2 instance 【发布时间】:2021-12-08 05:25:28 【问题描述】:

我相信这是一个简单的解决方法。我正在 AWS 中使用 Terraform,部署 VPC、子网、安全组(这看起来像问题)以及单个 EC2 实例。

症状

当第一次使用terraform apply 进行部署时,一切都按预期创建,但是,立即跟进另一个terraform applyterraform plan 表明EC2 实例发生了更改,需要重新部署EC2 实例。底层 Terraform 代码没有变化。

再次应用后,EC2 实例将按照terraform plan 的报告重新部署。

我希望在运行其他 terraform apply 命令时不要重新部署每个 EC2 实例。我不确定这是否可能,但我确定这是否很容易我只是在文档中丢失了。

地形文件

vpc.tf

# Create a VPC
resource "aws_vpc" "vpcSandbox" 
  cidr_block = var.vpcSandboxCIDR
  tags = 
    Name      = "vpcSandbox"
    Terraform = "True"
  


# Create DHCP Options for VPC
resource "aws_vpc_dhcp_options" "dhcpOptSandbox" 
  domain_name         = var.searchDomain
  domain_name_servers = ["208.67.220.220", "208.67.222.222"]

  tags = 
    Name      = "dhcpOptSandbox"
    Terraform = "True"
  


# Associated DHCP Options for VPC
resource "aws_vpc_dhcp_options_association" "dhcpOptAssocSandbox" 
  vpc_id          = aws_vpc.vpcSandbox.id
  dhcp_options_id = aws_vpc_dhcp_options.dhcpOptSandbox.id


# Create all Subnets
resource "aws_subnet" "sub-sandbox1a" 
  vpc_id            = aws_vpc.vpcSandbox.id
  availability_zone = "us-east-1a"
  cidr_block        = "10.11.1.0/24"
  tags = 
    Terraform = "True"
  

resource "aws_subnet" "sub-sandbox1b" 
  vpc_id            = aws_vpc.vpcSandbox.id
  availability_zone = "us-east-1b"
  cidr_block        = "10.11.2.0/24"
  tags = 
    Terraform = "True"
  

resource "aws_subnet" "sub-sandbox1c" 
  vpc_id            = aws_vpc.vpcSandbox.id
  availability_zone = "us-east-1c"
  cidr_block        = "10.11.3.0/24"
  tags = 
    Terraform = "True"
  

resource "aws_subnet" "sub-sandbox1d" 
  vpc_id            = aws_vpc.vpcSandbox.id
  availability_zone = "us-east-1d"
  cidr_block        = "10.11.4.0/24"
  tags = 
    Terraform = "True"
  

resource "aws_subnet" "sub-sandbox1e" 
  vpc_id            = aws_vpc.vpcSandbox.id
  availability_zone = "us-east-1e"
  cidr_block        = "10.11.5.0/24"
  tags = 
    Terraform = "True"
  

resource "aws_subnet" "sub-sandbox1f" 
  vpc_id            = aws_vpc.vpcSandbox.id
  availability_zone = "us-east-1f"
  cidr_block        = "10.11.6.0/24"
  tags = 
    Terraform = "True"
  


# Create Internet Gateway for VPC
resource "aws_internet_gateway" "gwSandbox" 
  vpc_id = aws_vpc.vpcSandbox.id

  tags = 
    Name      = "gwSandbox"
    Terraform = "True"
  


# Adding some routes to the sandbox VPC
resource "aws_route" "default-v4-sandbox" 
  route_table_id         = aws_vpc.vpcSandbox.default_route_table_id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.gwSandbox.id

resource "aws_route" "default-v6-sandbox" 
  route_table_id              = aws_vpc.vpcSandbox.default_route_table_id
  destination_ipv6_cidr_block = "::/0"
  gateway_id                  = aws_internet_gateway.gwSandbox.id

安全组.tf

# Create security groups for test server
resource "aws_security_group" "sandbox" 
  name        = "sandbox"
  description = "Allow SSH inbound traffic from Trusted Internet Addresses and all Outbound Traffic"
  vpc_id      = aws_vpc.vpcSandbox.id
  tags = 
    Name      = "sandbox"
    Terraform = "True"
  


resource "aws_security_group_rule" "workHQOfficeInbound" 
  type        = "ingress"
  from_port   = 0
  to_port     = 0
  protocol    = "-1"
  cidr_blocks = [var.workOfficeWAN]
  security_group_id = aws_security_group.sandbox.id


resource "aws_security_group_rule" "tgs_office_inbound" 
  type              = "ingress"
  from_port         = 0
  to_port           = 65535
  protocol          = "-1"
  cidr_blocks       = [var.devOfficeWAN]
  security_group_id = aws_security_group.sandbox.id


resource "aws_security_group_rule" "alloutbound" 
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  ipv6_cidr_blocks  = ["::/0"]
  security_group_id = aws_security_group.sandbox.id

ec2.tf

## Adding a test server
# Create a new Keypair
resource "aws_key_pair" "deployer" 
  key_name   = "deployer-key"
  public_key = var.certDeployerPub
  tags = 
    Name      = "deployer"
    Terraform = "True"
  


# Creating an interface for the test server
resource "aws_network_interface" "int-tc-amazlinux" 
  subnet_id = aws_subnet.sub-sandbox1a.id
  # private_ips = ["172.16.10.100"]

  tags = 
    Name      = "int-tc-amazlinux"
    Terraform = "True"
  


# Adding a test Server
resource "aws_instance" "tc-amazlinux01" 
  ami                         = "ami-0e341fcaad89c3650"
  instance_type               = "t4g.small"
  key_name                    = aws_key_pair.deployer.key_name
  subnet_id                   = aws_subnet.sub-sandbox1a.id
  associate_public_ip_address = "true"
  security_groups = [
    aws_security_group.sandbox.id
  ]

  tags = 
    Name      = "tc-amazlinux01"
    Terraform = "True"
  

输出

以下是运行 terraform apply 后紧跟另一个 terraform plan 的输出示例,无需对 terraform 文件进行任何修改。

为了篇幅,这里是: https://pastebin.com/raw/2Ly0NmVr

【问题讨论】:

提醒您将此问题保留为 MCVE,您真正需要的只是 plan 输出的最后一部分。根据输出,您的 SG 在apply 之后被分离,因此需要重新创建实例。这可能是由于人工干预、某种后配置后 API 响应验证等原因而发生的。您需要对 SG 的问题进行故障排除。 从这个问题来看:github.com/hashicorp/terraform-provider-aws/issues/6942 你应该改用'vpc_security_group_ids'而不是'security_groups' 【参考方案1】:

这可能是因为您的安全组不正确

应该是这样的:

resource "aws_instance" "tc-amazlinux01" 
  ami                         = "ami-0e341fcaad89c3650"
  instance_type               = "t4g.small"
  key_name                    = aws_key_pair.deployer.key_name
  subnet_id                   = aws_subnet.sub-sandbox1a.id
  associate_public_ip_address = "true"
  vpc_security_group_ids = [
    aws_security_group.sandbox.id
  ]

  tags = 
    Name      = "tc-amazlinux01"
    Terraform = "True"
  

【讨论】:

以上是关于Terraform 重新部署 EC2 实例的主要内容,如果未能解决你的问题,请参考以下文章

新AMI发布时,Terraform重新创建EC2实例

AWS - ECS - 如何在现有 ECS(带有 1 个 EC2)实例上重新部署更新的 Docker 映像?

无法与我的 EC2 实例建立 Internet 连接 [使用 terraform 部署,并为 ACL、安全组、Internet GW 打开了 80 个 http 端口]

如何使用 Terraform 部署和重新部署应用程序?

使用Terraform部署代码和管理配置

使用terraform“数据”时如何重新转动多个对象?