资讯动态

terraform-provider-aws 实战:用 aws_eip 为 EC2 绑定弹性 IP 部署 nginx Web 服务

发布时间:2026/9/17 2:38:58 来源:尧图企业网站定制
terraform-provider-aws 实战用 aws_eip 为 EC2 绑定弹性 IP 部署 nginx Web 服务【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws导读本文围绕 terraform-provider-aws 仓库中的 EIP 示例 展开完整讲解如何用 Terraform 创建一个绑定弹性 IPElastic IPEIP的 EC2 实例、为其配置安全组并自动安装 nginx。读完本文你将掌握aws_eip、aws_instance、aws_security_group三个核心资源的组合使用方式、terraform apply -var与terraform.tfvars两种传参方法以及从源码层面理解 EIP 的分配、关联、解绑与释放生命周期。示例目标与整体架构该示例位于 examples/eip其核心目标非常聚焦启动一台 EC2 Web 服务器安装 nginx同时创建一个安全组最后通过绑定在实例上的 Elastic IP 在浏览器中访问 nginx 欢迎页。整个示例由以下文件组成文件作用main.tf定义aws_eip、aws_security_group、aws_instance三个资源variables.tf声明aws_region、aws_amis、key_name三个变量outputs.tf输出实例内网 IP 与 EIP 公网 IPuserdata.sh实例启动时执行的脚本更新 apt 并安装 nginxterraform.template.tfvars变量值模板复制为terraform.tfvars后使用README.md示例说明与运行步骤资源间的依赖关系为aws_eip.default通过instance aws_instance.web.id引用 EC2 实例aws_instance.web通过security_groups [aws_security_group.default.name]引用安全组并通过user_data file(userdata.sh)注入安装脚本。Terraform 会根据这些引用自动构建依赖图保证先建实例、后绑定 EIP。核心资源逐文件解析1. main.tfEIP 安全组 EC2 实例main.tf 要求 Terraform 版本不低于 0.12required_version 0.12并指定 provider 使用var.aws_region作为目标区域。Elastic IP 资源是本文的主角resource aws_eip default { instance aws_instance.web.id domain vpc }两个关键配置项的含义如下instance要绑定的 EC2 实例 ID。示例直接引用aws_instance.web.idTerraform 会等待实例创建完成后才执行 EIP 绑定。domain vpc声明 EIP 属于 VPC 域。这是当前环境下的必选项——从源码 ec2_eip.go 可以看到Read操作会先通过eipID(d.Id()).IsVPC()判断 ID 是否以eipalloc-前缀开头否则直接报错随着 EC2-Classic 退役standardEC2-Classic域的 EIP 已不再受支持见 ec2_eip.go 的Delete逻辑同样如此。安全组开放了 SSH22 端口与 HTTP80 端口的入站流量并允许所有出站流量resource aws_security_group default { name eip_example description Used in the terraform # SSH access from anywhere ingress { from_port 22 to_port 22 protocol tcp cidr_blocks [0.0.0.0/0] } # HTTP access from anywhere ingress { from_port 80 to_port 80 protocol tcp cidr_blocks [0.0.0.0/0] } # outbound internet access egress { from_port 0 to_port 0 protocol -1 cidr_blocks [0.0.0.0/0] } }需要说明的是0.0.0.0/0意味着对公网完全开放示例仅用于演示生产环境应将其收敛为可信来源 IP 段。EC2 实例选用t2.micro按区域查找 AMI注入 SSH 密钥与 user_dataresource aws_instance web { instance_type t2.micro ami var.aws_amis[var.aws_region] key_name var.key_name security_groups [aws_security_group.default.name] user_data file(userdata.sh) # Force IMDSv2. metadata_options { http_tokens required } tags { Name eip-example } }示例额外启用了IMDSv2 强制模式metadata_options.http_tokens required这是 AWS 为缓解 SSRF 类安全风险推出的实例元数据服务新版本属于安全加固实践。实例还被打上Name eip-example标签便于在控制台识别。2. variables.tf区域、AMI 与密钥变量variables.tf 声明了三个变量aws_region目标 AWS 区域默认us-east-1。aws_amis按区域映射的 AMI ID使用Ubuntu Jammy 22.04amd64镜像示例内置了us-east-1与us-west-2两个区域的值。若在其他区域部署需要自行替换为对应区域的 Ubuntu 22.04 AMI。key_nameSSH 密钥对名称无默认值必须由用户提供。该密钥对需提前在 AWS 控制台的 EC2 Key Pairs 页面创建并下载私钥。3. outputs.tf获取内网 IP 与 EIPoutputs.tf 定义了两个输出output address { value aws_instance.web.private_ip } output elastic_ip { value aws_eip.default.public_ip }address实例的私网 IPaws_instance.web.private_ip。elastic_ip弹性 IP 的公网地址aws_eip.default.public_ip这正是 README 中用于浏览器访问的地址。4. userdata.sh启动即装 nginxuserdata.sh 是实例首次启动时由 cloud-init 执行的脚本内容极简#!/bin/bash -v apt-get update -y apt-get install -y nginx /tmp/nginx.log脚本先刷新 apt 软件源再安装 nginx安装日志写入/tmp/nginx.log。nginx 安装完成后默认监听 80 端口配合安全组放行的 HTTP 入站规则用户即可通过 EIP 直接访问默认欢迎页。注意 nginx 安装需要一到几分钟README 也特别提醒要Give couple of mins for userdata to install nginx。5. terraform.template.tfvars变量值模板terraform.template.tfvars 提供了变量值示例key_name terraform-aws-provider-example该文件刻意命名为模板而非生效文件避免包含真实密钥信息被误提交。使用时复制为terraform.tfvars并修改为自己的密钥对名称即可。运行步骤从 apply 到浏览器访问按照 README 的说明完整运行流程如下配置 AWS Provider按官方文档方式配置 AWS 凭证与区域环境变量或共享凭证文件均可。示例中的 provider 块已指定region var.aws_region凭证则来自本机 AWS 配置。初始化与预览terraform init terraform plan -var key_name{your_key_name}直接传参执行README 推荐的第一种方式terraform apply -var key_name{your_key_name}或使用 tfvars 文件先把模板复制为生效文件并修改cp terraform.template.tfvars terraform.tfvars # 编辑 terraform.tfvars将 key_name 改为你的密钥对名称 terraform applyREADME 明确指出这是Alternatively to using-var的替代方案——两种方式效果等价后者避免了每个命令都要重复书写-var。等待并验证apply 完成后等待约两分钟让 user_data 完成 nginx 安装然后查看输出terraform output elastic_ip在浏览器中输入输出的 EIP 地址即可看到 nginx 欢迎页。清理资源示例结束后建议执行terraform destroy会按依赖顺序释放 EIP、终止实例并删除安全组避免持续计费。源码级深挖aws_eip 的完整生命周期要真正理解这个示例值得深入 internal/service/ec2/ec2_eip.go 看看aws_eip资源在 Provider 内部是如何实现的。该资源定义在resourceEIP()函数中ec2_eip.go文件头部的SDKResource(aws_eip, nameEIP)注释表明它由 SDKv2 实现且Tags(identifierAttributeid)说明 EIP 支持标签管理。完整的 Schema 属性一览源码 ec2_eip.go 定义的属性远多于示例用到的两个理解全貌有助于扩展使用属性类型说明address可选ForceNewBYOIP 自有 IP 地址用于导入已拥有的公网 IPallocation_id只读EIP 分配 IDeipalloc-xxx创建后自动填充arn只读EIP 的 ARN形如arn:aws:ec2:region:account:elastic-ip/allocation-idassociate_with_private_ip可选关联到 ENI 时指定的私网 IPassociation_id只读EIP 与实例/ENI 的关联 IDeipassoc-xxxcarrier_ip/customer_owned_ip只读Wavelength 区域/本地运营商网络场景下的 IPcustomer_owned_ipv4_pool可选客户自有 IP 池 IDdomain可选ForceNew默认自动vpc或standardEC2-Classic 退役后实际仅支持vpcinstance可选要绑定的 EC2 实例 ID示例正是用它实现关联ipam_pool_id可选ForceNew从 IPAM 地址池分配时指定的池 IDnetwork_border_group可选ForceNew网络边界组用于边缘位置分配network_interface可选要关联的 ENI 网络接口 IDprivate_dns/public_dns只读自动生成的私网/公网 DNS 名private_ip/public_ip只读私网/公网 IP 地址ptr_record只读反向 DNS 解析记录public_ipv4_pool可选ForceNew公网 IPv4 地址池 ID含amazon默认池tags/tags_all可选/只读资源标签此外资源还定义了超时Read默认 15 分钟、Update默认 5 分钟、Delete默认 3 分钟ec2_eip.go。生命周期与底层 AWS API 调用Create分配 关联resourceEIPCreate首先构造ec2.AllocateAddressInputec2_eip.go依次把address、customer_owned_ipv4_pool、domain、ipam_pool_id、network_border_group、public_ipv4_pool映射进请求调用AllocateAddress完成分配随后以返回的AllocationId作为资源 ID通过tfresource.RetryWhenNotFound轮询等待分配结果可见。若配置了instance或network_interface还会调用associateEIP执行关联并对errCodeInvalidAllocationIDNotFound做重试以应对 EC2 的最终一致性延迟。Read读取回填resourceEIPRead先校验 VPC 域再调用findEIPByAllocationID查询Address最终由resourceEIPFlattenec2_eip.go把 API 返回值逐字段写入状态包括allocation_id、association_id、domain、instance、private_ip、public_ip、public_dns、private_dns、ipam_pool_id等。值得注意的一个细节如果用户用 IP 而非 allocation ID 导入 EIPRead 阶段会把 ID 统一改写为 allocation IDec2_eip.go保证状态始终以分配 ID 为唯一主键。Update重新关联resourceEIPUpdate监听associate_with_private_ip、instance、network_interface的变化。发生变更时先通过disassociateEIP解绑旧关联再按新值调用associateEIP重新绑定ec2_eip.go。Delete解绑 释放resourceEIPDelete先解绑实例/ENI 关联再调用ReleaseAddress释放地址若地址来自 IPAM 池还会轮询等待池分配记录消失ec2_eip.go。辅助函数associateEIPec2_eip.go与disassociateEIPec2_eip.go是关联/解绑逻辑的核心前者调用AssociateAddress后持续等待关联状态变为可见并对 pending instance 这类瞬时错误自动重试后者调用DisassociateAddress并把InvalidAssociationIDNotFound视为幂等成功。仓库中对应的测试文件 ec2_eip_test.go 覆盖了 EIP 的基础创建、关联切换等场景生成测试用例模板可见 testdata/tmpl/ec2_eip_basic.gtpl。常见问题与注意事项密钥对不存在key_name必须是当前区域已创建的密钥对否则 EC2 实例创建会失败这也正是示例强制要求通过-var或 tfvars 提供该变量的原因。非默认区域部署内置 AMI 仅覆盖us-east-1与us-west-2其他区域需要先替换 variables.tf 中aws_amis映射否则会出现 AMI not found 类错误。等待 nginx 就绪user_data 脚本在实例首次启动后才执行安装通常需要一两分钟访问前请耐心等待。必须使用 VPC 域随着 EC2-Classic 退役domain只能使用vpc从源码看Provider 在 Read/Delete 阶段都会对非 VPC 域 EIP 直接报错。公网完全开放示例安全组对0.0.0.0/0开放 SSH 与 HTTP仅为演示便捷实际使用应收紧来源 IP。小结通过 EIP 示例 你可以看到一条完整的 Terraform 实践链路用aws_security_group定义网络访问边界用aws_instance结合 user_data 完成应用自动化安装再用aws_eip把公网弹性 IP 稳定绑定到实例之上。结合 ec2_eip.go 的源码实现你还能清楚掌握 EIP 从AllocateAddress分配到AssociateAddress关联、再到DisassociateAddress与ReleaseAddress释放的完整生命周期从而在自己的基础设施代码中更准确地使用这个资源。【免费下载链接】terraform-provider-awsThe AWS Provider enables Terraform to manage AWS resources.项目地址: https://gitcode.com/GitHub_Trending/te/terraform-provider-aws创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价