Terraform如何获取aws_lb的IP地址
Posted
技术标签:
【中文标题】Terraform如何获取aws_lb的IP地址【英文标题】:Terraform how to get IP address of aws_lb 【发布时间】:2019-11-04 21:33:42 【问题描述】:问题
是否有办法在 Terraform 创建 aws_lb 时获取 aws_lb 资源的分配 IP 地址?
和AWS documentation - NLB - To find the private IP addresses to whitelist一样,我们可以找到ELB关联的IP地址。
-
打开 Amazon EC2 控制台https://console.aws.amazon.com/ec2/。
在导航窗格中,选择网络接口。
在搜索字段中,输入您的网络负载均衡器的名称。
每个负载平衡器子网有一个网络接口。
在每个网络接口的详细信息选项卡上,复制地址
主要私有 IPv4 IP。
背景
为了能够设置安全组以将 ELB IP 地址列入白名单,因为网络负载均衡器不能没有安全组,如 Network Load Balancers don't have Security Groups。
考虑过aws_network_interface,但由于错误而无法使用。
错误:找不到匹配的网络接口
另外我认为数据源假设资源已经存在,不能用于 Terraform 创建的资源。
【问题讨论】:
【参考方案1】:在 Terraform 中仅使用 HCL 的更优雅的解决方案:
data "aws_network_interface" "lb"
for_each = var.subnets
filter
name = "description"
values = ["ELB $aws_lb.example_lb.arn_suffix"]
filter
name = "subnet-id"
values = [each.value]
resource "aws_security_group" "lb_sg"
vpc_id = var.vpc_id
ingress
from_port = 0
to_port = 0
protocol = "tcp"
cidr_blocks = formatlist("%s/32", [for eni in data.aws_network_interface.lb : eni.private_ip])
description = "Allow connection from NLB"
来源:https://github.com/terraform-providers/terraform-provider-aws/issues/3007
希望这会有所帮助。
【讨论】:
这真是太棒了!我非常喜欢这个。 这是高级别的!【参考方案2】:使用外部提供商
使用 Python/boto3 从外部提供程序调用获取 NLB IP。
nlb_private_ips.tf
variable "nlb_name"
variable "vpc_id"
variable "region"
data "external" "get_nlb_ips"
program = ["python", "$path.module/get_nlb_private_ips.py"]
query =
aws_nlb_name = "$var.nlb_name"
aws_vpc_id = "$var.vpc_id"
aws_region = "$var.region"
output "aws_nlb_ip_decoded"
value = "$jsondecode(data.external.get_nlb_ips.result.private_ips)"
output "aws_nlb_ip_encoded"
value = "$data.external.get_nlb_ips.result.private_ips"
get_nlb_private_ips.py
import boto3
import json
import sys
def json_serial(obj):
"""JSON serializer for objects not serializable by default json code
Args:
obj: object to serialize into JSON
"""
_serialize =
"int": lambda o: int(o),
"float": lambda o: float(o),
"decimal": lambda o: float(o) if o % 1 > 0 else int(o),
"date": lambda o: o.isoformat(),
"datetime": lambda o: o.isoformat(),
"str": lambda o: o,
return _serialize[type(obj).__name__.lower()](obj)
def pretty_json(dict):
"""
Pretty print Python dictionary
Args:
dict: Python dictionary
Returns:
Pretty JSON
"""
return json.dumps(dict, indent=2, default=json_serial, sort_keys=True, )
def get_nlb_private_ips(data):
ec2 = boto3.client('ec2', region_name=data['aws_region'])
response = ec2.describe_network_interfaces(
Filters=[
'Name': 'description',
'Values': [
"ELB net/AWS_NLB_NAME/*".format(
AWS_NLB_NAME=data['aws_nlb_name'])
]
,
'Name': 'vpc-id',
'Values': [
data['aws_vpc_id']
]
,
'Name': 'status',
'Values': [
"in-use"
]
,
'Name': 'attachment.status',
'Values': [
"attached"
]
]
)
# print(pretty_json(response))
interfaces = response['NetworkInterfaces']
# ifs = list(map(lamba index: interfaces[index]['PrivateIpAddresses'], xrange(len(interfaces))))
# --------------------------------------------------------------------------------
# Private IP addresses associated to an interface (ENI)
# Each association has the format:
#
# "Association":
# "IpOwnerId": "693054447076",
# "PublicDnsName": "ec2-52-88-47-177.us-west-2.compute.amazonaws.com",
# "PublicIp": "52.88.47.177"
# ,
# "Primary": true,
# "PrivateDnsName": "ip-10-5-1-205.us-west-2.compute.internal",
# "PrivateIpAddress": "10.5.1.205"
# ,
# --------------------------------------------------------------------------------
associations = [
association for interface in interfaces
for association in interface['PrivateIpAddresses']
]
# --------------------------------------------------------------------------------
# Get IP from each IP association
# --------------------------------------------------------------------------------
private_ips = [
association['PrivateIpAddress'] for association in associations
]
return private_ips
def load_json():
data = json.load(sys.stdin)
return data
def main():
data = load_json()
"""
print(data['aws_region'])
print(data['aws_vpc_id'])
print(data['aws_nlb_name'])
"""
ips = get_nlb_private_ips(data)
print(json.dumps("private_ips": json.dumps(ips)))
if __name__ == '__main__':
main()
使用 aws_network_interfaces 数据源
创建 aws_lb 之后。
data "aws_network_interfaces" "this"
filter
name = "description"
values = ["ELB net/$aws_lb.this.name/*"]
filter
name = "vpc-id"
values = ["$var.vpc_id"]
filter
name = "status"
values = ["in-use"]
filter
name = "attachment.status"
values = ["attached"]
locals
nlb_interface_ids = "$flatten(["$data.aws_network_interfaces.this.ids"])"
data "aws_network_interface" "ifs"
count = "$length(local.nlb_interface_ids)"
id = "$local.nlb_interface_ids[count.index]"
output "aws_lb_network_interface_ips"
value = "$flatten([data.aws_network_interface.ifs.*.private_ips])"
【讨论】:
只是检查,但如果负载均衡器是在创建这些数据源的同时进行的,那将不起作用,对吧?【参考方案3】:@user1297406 的解决方案导致异常。 data.aws_network_interface.lb is tuple with 2 elements.
正确的语法是:
data "aws_network_interface" "lb"
count = length(var.vpc_private_subnets)
filter
name = "description"
values = ["ELB $aws_alb.lb.arn_suffix"]
filter
name = "subnet-id"
values = [var.vpc_private_subnets[count.index]]
resource "aws_security_group_rule" "lb_sg"
from_port = 0
protocol = "TCP"
to_port = 0
type = "ingress"
cidr_blocks = formatlist("%s/32", data.aws_network_interface.lb.*.private_ip)
【讨论】:
以上是关于Terraform如何获取aws_lb的IP地址的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Terraform 公开具有公共 IP 地址的 Azure Kubernetes 集群
引用 IP 地址生成配置文件时的 Terraform 循环依赖问题