amazon-web-services - Set Public IP information using remote-exec for a set of instances
问题描述
I am planning to create puppet infrastructure on AWS with a server node and agent nodes. To be able to install the puppet server and puppet agent packages, it is required to add the IP's to the hosts file on each of the nodes as below
[puppet master ip] puppetmaster puppet
[puppet client ip] puppetclient
I understand that remote-exec runs after the resource is created. But i want it to run after all the resources are created so that i can get the information about the master and client IP's together. So, i used a null resource to execute the remote-exec provisioner after the instances are created. But I am running into an issue
- it says
This object does not have an attribute named "public_ip"
I have tried using id instead of public_ip and it complains that this object does not have an attribute named "id"
- I keep master IP constant and loop over only the agent IP's to be able to put them both into the /etc/hosts file for each of the instance. Is my approach correct in the remote-exec part?
here is the full code
provision_ec2.tf
resource "aws_key_pair" "puppet" {
key_name = "puppet"
public_key = file("puppet.pub")
}
# Provision Puppet Server
resource "aws_instance" "puppet_instances" {
for_each = toset(local.expanded_names)
ami = var.ami
instance_type = var.instance_type
key_name = aws_key_pair.puppet.key_name
security_groups = ["${aws_security_group.puppet-server.name}"]
tags = {
Name = each.value
}
}
resource "null_resource" "provisioner" {
count = "${var.total_count}"
triggers = {
master_ip = "${element(aws_instance.puppet_instances.*.public_ip, count.index)}"
}
connection {
host = "${element(aws_instance.puppet_instances.*.public_ip, count.index)}"
type = "ssh"
user = "ubuntu"
private_key = file("puppet")
}
# set hostname
provisioner "remote-exec" {
inline = [
"sudo echo ${element(aws_instance.puppet_instances.*.public_ip,0)} puppetmaster puppet>>/etc/hosts",
"sudo echo ${element(aws_instance.puppet_instances.*.public_ip, count.index)} puppetclient>>/etc/hosts"
]
}
}
locals {
expanded_names = flatten([
for name, count in var.host_name : [
for i in range(count) : format("%s-%02d", name, i+1)
]
])
}
variables.tf
# Set the instances type. For puppet, choose instance with minimum 2GB RAM
variable "instance_type" {
default = "t2.small"
}
# Set the region in which the instances will be provisioned. Default region is N.Virgina
variable "aws_region" {
default = "us-east-1"
}
# Sepcify the AMI to be used
variable "ami" {
default = "ami-09e67e426f25ce0d7"
}
# Set the hostnames for the instances as per the count
variable "host_name" {
type = map(number)
default = {
"Puppet-Server" = 1
"Puppet-Agent" = 3
}
}
variable "total_count" {
default = 4
}
security_groups.tf
# Create Security Groups
resource "aws_security_group" "puppet-server" {
name = "puppet-server-SG"
description = "Security Group for puppet master instance"
ingress {
from_port = "0"
to_port = "0"
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = "0"
to_port = "0"
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "puppet-server-SG"
}
}
I am out of ideas on how to achieve this.
解决方案
Since you are using for_each
, you should use values
first. So it should be:
master_ip = element(values(aws_instance.puppet_instances)[*].public_ip, count.index)
推荐阅读
- azure-functions - 使用 Azure 函数和服务总线的 MassTransit 异常处理和错误队列
- magento - Magento 2.4 header.phtml 文件问题
- asp.net - 隐藏 Gridview 直到加载数据表
- c# - Selenium - 如何等待元素的文本不再为空?
- kubernetes - 查找应用于 Kubernetes 集群的命令历史记录
- c - 如何在C中返回布尔值?
- laravel - Gitlab ci错误:bash:composer:找不到命令
- arrays - 使用数组进行二进制十进制转换
- python - 如何将字符串拆分为列表中的不同部分?
- sql - 带有 PARTITION 的 COUNT() 生成不一致的结果