Terraform-provider-aws: Obtenha o IP privado da instância iniciada pelo grupo de escalonamento automático

Criado em 13 jun. 2017  ·  50Comentários  ·  Fonte: hashicorp/terraform-provider-aws

_Esta edição foi originalmente aberta por @coolgooze como hashicorp/terraform#11713. Ele foi migrado aqui como parte da divisão do provedor . O corpo original da edição está abaixo._


ASG
recurso "aws_autoscaling_group" "REDIS_ASG" {
nome = "${var.environment}-REDIS_ASG"
launch_configuration = "${aws_launch_configuration.redis_launch_conf.name}"
#availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]
vpc_zone_identifier = ["${data.aws_subnet.PrivateDBSubnetAZ1.id}","${data.aws_subnet.PrivateDBSubnetAZ2.id}","${data.aws_subnet.PrivateDBSubnetAZ3.id}"]
min_size = 1
max_size = 1
capacidade_desejada = 1
health_check_grace_period = 600
health_check_type = "EC2"
force_delete = "falso"
terminação_policies = ["OldestInstance"]
marcação {
chave = "Nome"
value = "${var.environment}-int-redis"
propagate_at_launch = true
}
}

estou tentando criar um registro A
recurso "aws_route53_record" "redis" {
zone_id = "${data.aws_route53_zone.dns.zone_id}"
name = "redis-${var.environment}.${data.aws_route53_zone.dns.name}"
tipo = "A"
tt = "60"
registros = ["${aws_autoscaling_group.REDIS_ASG.private_ip}"]
}

Saída-

  • O recurso 'aws_autoscaling_group.REDIS_ASG' não tem o atributo 'private_ip' para a variável 'aws_autoscaling_group.REDIS_ASG.private_ip'
enhancement servicautoscaling

Comentários muito úteis

Não sou contra esse recurso _em geral_, mas tenho opiniões sobre como ele deve ser implementado. Também serei franco e direi que é improvável que nós (HashiCorp) cheguemos a esse recurso em breve, mas agradecemos contribuições se alguém puder pegá-lo.

Sobre como implementar:

  • O endpoint DescribeAutoScalingGroups retorna uma lista de ASGs (consultamos pelo nome específico, para obter apenas um, se existir)
  • O AutoScalingGroup tem um atributo que lista suas instâncias
  • Essa lista contém informações de instância para cada instância, mas são informações incompletas. Os endereços IP da instância (públicos ou privados) não estão incluídos aqui

Portanto, o problema aqui em resumo é que os endereços IP não são retornados por padrão e você precisa fazer algumas chamadas de API adicionais para obtê-los. Para configurações grandes, essas chamadas de API extras são adicionadas rapidamente, portanto, por padrão, não devemos incluir Endereços IP de instância no estado de Grupos de AutoScaling . Reconheço que é um recurso útil, mas também acho que não será usado com frequência, portanto, por padrão, não devemos consumir todas essas chamadas de API.

Dito isso, acredito/proponho que possamos oferecer suporte a essa funcionalidade com uma fonte de dados:

  • data.aws_autoscaling_group.group (singular) não deve ser confundido com data.aws_autoscaling_groups (plural)
  • esta fonte de dados deve fornecer mais informações sobre o ASG específico (em oposição a data.aws_autoscaling_groups que apenas retorna nomes)
  • deve fornecer um atributo opcional, embora padrão false , como get_instance_properties para instruir a fonte de dados a procurar atributos de instância:

Alternativamente, poderíamos expandir a fonte de dados data.aws_autoscaling_groups , mas acho que prefiro a separação.

Para obter o(s) endereço(s) IP da(s) Instância(s), precisamos chamar DescribeInstances para cada uma. Felizmente, podemos usar um EC2Filter e filtrar por requester-id , neste caso, o ID de grupo de AutoScaling, para que não precisemos agrupar os IDs de instância da saída DescribeASG e, em seguida, alimentá-los na chamada DescribeInstances .

Acredito que essa nova fonte de dados manteria essas informações de instância em TypeSet de instâncias. Infelizmente você não pode referenciar diretamente o valor em um conjunto com coisas como element(set, count) . Então, se você quiser uma lista de endereços IP, podemos querer pegar os resultados da chamada DescribeInstances e agregar todos os ips públicos em um campo calculado public_ips e ips privados em private_ips .

Então, no final, a saída dessa fonte de dados seria assim:

  • informações asg
  • conjunto de instâncias
  • lista de ips públicos
  • lista de ips privados

Como isso soa?

```hcl
recurso "autoscaling_group" "exemplo" {
[...]
}

data "autoscaling_group" "example_ips" {
autoscaling_id = "${aws_autoscaling_group.example.id}"
# Busca informações da instância
# Recupera informações da instância
# Recupera public_ip's
# Recupera private_ip's
get_instance_properties = true
}

resource "aws_route53_record" "service-record" {
zona_id = ""
contagem = 2
name = "service-lb-${format("%03d", count.index + 1)}.mydomain.com"
tipo = "A"
tt = "60"
registros = ["${element(data.aws_autoscaling_group.example_ips.private_ips, count.index)}"]
}

Todos 50 comentários

Eu só precisava disso hoje. Eu adoraria que isso fosse uma coisa real.

Eu corri para uma necessidade para isso hoje. Eu adoraria que isso existisse. Alguma atualização sobre o pedido?

Olá – Você pode descrever o caso de uso aqui? Estou curioso para saber por que você deseja o IP direto de qualquer instância que esteja em um grupo de dimensionamento automático, em vez de se conectar por meio de um balanceador de carga.

Se não me engano, uma vantagem específica de um ASG é garantir que você tenha um certo número de instâncias disponíveis e em execução, não que uma delas exista em um determinado IP.

Se o recurso ASG exportasse um IP privado e, no lado da AWS, o ASG alterasse as instâncias por qualquer motivo, esse IP poderia ficar obsoleto até seu próximo plano e aplicação, certo? Nesse caso, pode haver uma janela de tempo em que seu registro A o direciona para um IP incorreto, correto? Onde, como se o registro A apontasse para um IP atribuído a um balanceamento de carga, o rollover aconteceria automaticamente.

Estou curioso para saber como expor isso seria usado de maneira confiável e estável. Obrigado!

@catsby Você está correto ao dizer que o IP seria obsoleto e o Terraform precisaria ser executado para atualizar o registro A anexado ao registro Route53.

Temos casos de uso em que temos um conjunto de servidores que executam tarefas diferentes. Tudo é controlado no fantoche e no Terraform. Agora temos um módulo que constrói uma contagem (normalmente). O que queríamos fazer era colocá-los em um ASG para ter autocura no caso de um nó falhar. No entanto, não podemos avançar com os testes porque não há saída de ips privados ou uma lista de nós.

Iniciamos um efeito há algum tempo para remover o endereço IP das configurações e trocar para nomes DNS. Seria a cereja do bolo se pudéssemos construir uma maneira de autocurar esses servidores em caso de falha da instância aws usando ASG.

+1

Outro caso de uso
https://github.com/terraform-community-modules/tf_aws_bastion_s3_keys

Isso configura um bastião em um grupo de escalonamento automático min=max=desired=1. O raciocínio por trás disso é relançar automaticamente o bastião se ele cair. Sem isso, no entanto, tenho que verificar depois para ver qual ip o bastião realmente recebeu.

Seria muito útil ter esse recurso. Os usuários podem executar tipos de cargas de trabalho únicas com uma lista de IPs conhecidos para o ASG em um null_resource. +1 para mim também.

@catsby Veja meu comentário na edição fechada migrada aqui: https://github.com/hashicorp/terraform/issues/11713

Repetir:

Muito útil, fornecerá a mesma funcionalidade que o CloudFormation. Podemos simplesmente esperar que o ASG termine de criar todas as instâncias e reporte com ips privados, ids de instância etc.

Também ninguém diz que ASG tem que estar relacionado a um ELB, no nosso caso temos as instâncias por trás do HAProxy então precisamos saber seus IP's.

Isso está aberto desde fevereiro, é realmente tão difícil de resolver?

@catsby Outro exemplo, quero criar registros DNS do Route53 e verificações de integridade após o lançamento de instâncias:

# Host-specific A records for both load-balancers
resource "aws_route53_record" "service-record" {
   zone_id = "<my-zone-id>"
   count = 2
   name = "service-lb-${format("%03d", count.index + 1)}.mydomain.com"
   type = "A"
   ttl = "60"
   records = ["${element(aws_instance.lb-service.*.public_ip, count.index)}"]
}

# Health checks for each of the load balancers
resource "aws_route53_health_check" "service-healthcheck" {
  ip_address = "${element(aws_instance.lb-service.*.public_ip, count.index)}"
  count = 2
  port = 50000
  type = "HTTP"
  resource_path = "/health"
  failure_threshold = "5"
  request_interval = "30"
  tags = {
    Name = "service-${format("%03d", count.index + 1)}.production"
  }
}

# Group consisting of 2 alias records to the host records, with associated health checks, having weighted routing
resource "aws_route53_record" "service-group" {
   zone_id = "<my-zone-id>"
   count = 2
   name = "service.mydomain.com"
   type = "A"
   weighted_routing_policy = {
      weight = "50"
   }
   health_check_id = "${element(aws_route53_health_check.service-healthcheck.*.id, count.index)}"
   set_identifier = "service${format("%03d", count.index + 1)}"
   alias {
     name = "${element(aws_route53_record.service-record.*.fqdn, count.index)}"
     zone_id = "<my-zone-id>"
     evaluate_target_health = true
   }
}

Quando as instâncias são executadas via ASG, não há como fazer isso. Somos forçados a mover esse código para os dados do usuário, o que é um grande PITA.

+1

alguma atualização disso?

Não sou contra esse recurso _em geral_, mas tenho opiniões sobre como ele deve ser implementado. Também serei franco e direi que é improvável que nós (HashiCorp) cheguemos a esse recurso em breve, mas agradecemos contribuições se alguém puder pegá-lo.

Sobre como implementar:

  • O endpoint DescribeAutoScalingGroups retorna uma lista de ASGs (consultamos pelo nome específico, para obter apenas um, se existir)
  • O AutoScalingGroup tem um atributo que lista suas instâncias
  • Essa lista contém informações de instância para cada instância, mas são informações incompletas. Os endereços IP da instância (públicos ou privados) não estão incluídos aqui

Portanto, o problema aqui em resumo é que os endereços IP não são retornados por padrão e você precisa fazer algumas chamadas de API adicionais para obtê-los. Para configurações grandes, essas chamadas de API extras são adicionadas rapidamente, portanto, por padrão, não devemos incluir Endereços IP de instância no estado de Grupos de AutoScaling . Reconheço que é um recurso útil, mas também acho que não será usado com frequência, portanto, por padrão, não devemos consumir todas essas chamadas de API.

Dito isso, acredito/proponho que possamos oferecer suporte a essa funcionalidade com uma fonte de dados:

  • data.aws_autoscaling_group.group (singular) não deve ser confundido com data.aws_autoscaling_groups (plural)
  • esta fonte de dados deve fornecer mais informações sobre o ASG específico (em oposição a data.aws_autoscaling_groups que apenas retorna nomes)
  • deve fornecer um atributo opcional, embora padrão false , como get_instance_properties para instruir a fonte de dados a procurar atributos de instância:

Alternativamente, poderíamos expandir a fonte de dados data.aws_autoscaling_groups , mas acho que prefiro a separação.

Para obter o(s) endereço(s) IP da(s) Instância(s), precisamos chamar DescribeInstances para cada uma. Felizmente, podemos usar um EC2Filter e filtrar por requester-id , neste caso, o ID de grupo de AutoScaling, para que não precisemos agrupar os IDs de instância da saída DescribeASG e, em seguida, alimentá-los na chamada DescribeInstances .

Acredito que essa nova fonte de dados manteria essas informações de instância em TypeSet de instâncias. Infelizmente você não pode referenciar diretamente o valor em um conjunto com coisas como element(set, count) . Então, se você quiser uma lista de endereços IP, podemos querer pegar os resultados da chamada DescribeInstances e agregar todos os ips públicos em um campo calculado public_ips e ips privados em private_ips .

Então, no final, a saída dessa fonte de dados seria assim:

  • informações asg
  • conjunto de instâncias
  • lista de ips públicos
  • lista de ips privados

Como isso soa?

```hcl
recurso "autoscaling_group" "exemplo" {
[...]
}

data "autoscaling_group" "example_ips" {
autoscaling_id = "${aws_autoscaling_group.example.id}"
# Busca informações da instância
# Recupera informações da instância
# Recupera public_ip's
# Recupera private_ip's
get_instance_properties = true
}

resource "aws_route53_record" "service-record" {
zona_id = ""
contagem = 2
name = "service-lb-${format("%03d", count.index + 1)}.mydomain.com"
tipo = "A"
tt = "60"
registros = ["${element(data.aws_autoscaling_group.example_ips.private_ips, count.index)}"]
}

@catsby Eu amo isso e ajudaria muito.

@catsby linda!

qualquer atualização sobre isso, na real necessidade desta solução.

Isso foi analisado? uma rolha completa sobre o que sou obrigado a fazer.

alguma atualização disso?

Isso seria incrível de ter!

Isso seria glorioso! Já que o Lambda acionado pelo CloudWatchEvent é uma bagunça!

Precisa desse também

Alguém encontra solução ou solução para este problema? Isso é completamente uma rolha para o que eu preciso fazer.

+1

+1

+1

+1

+1

+1

+1

+1

Aqui estão algumas soluções que eu implemento:

  1. Use o módulo terraform-aws-modules/autoscaling/aws para lançar meus ASG's
    Marque o ASG e use a fonte de dados aws_instance para pesquisar as instâncias com base nas tags. Então faça o que eu preciso fazer com os dados

  2. Ao usar um ASG para um Bastion Host. Eu crio um iam_instance_profile para o ASG que permite que a própria instância atualize seu próprio registro route53 ao inicializar usando um script de configuração de inicialização.

Espero que isto ajude

+1

+1

Existe atualmente alguma solução alternativa disponível?

Dessa forma, me permitiu obter ips de nós de trabalho:

data "aws_instances" "workers" {
  instance_tags {
    Name = "lexsys-eks-asg"
  }
}

output "private-ips" {
  value = "${data.aws_instances.workers.private_ips}"
}

output "public-ips" {
  value = "${data.aws_instances.workers.public_ips}"
}
Outputs:

private-ips = [
    10.0.0.75,
    10.0.1.87
]
public-ips = [
    52.44.215.211,
    54.153.70.110
]

Claro, essa solução alternativa tem as limitações, mas funcionou para mim.

@catsby Um caso de uso é para configuração de cluster. Em tal cenário, queremos poder fornecer apenas as chaves SSH das instâncias para pessoas que desejam testar um cluster como kafka, zookeeper, elasticsearch etc, sem precisar fornecer acesso ao console da AWS. Se o terraform pudesse simplesmente gerar o endereço IP privado, os solucionadores de problemas teriam uma lista de endereços IP para fazer login simplesmente com suas chaves SSH e sem exigir acesso ao Console AWS.

+1

@catsby Sim, outro caso de uso é ao criar um cluster kubernetes por meio de um asg. você precisa do ip privado do mestre para alimentar os trabalhadores. Existe alguém que conhece um trabalho em torno disso?

+1

+1

+1. Meu caso de uso envolve o Hashicorp Vault, que precisa ser inicializado antes de ser reconhecido como um nó íntegro pelo balanceador de carga.

+1

Alguma solução alternativa para o Google Cloud Platform? Tem o mesmo problema com google_compute_instance_group_manager .

@lexsys27 a pergunta é específica para quando as instâncias são criadas via aws_autoscaling_group

@KIVagant Receio que você precise esperar pacientemente como o resto de nós (desde fevereiro de 2017) para que isso seja incluído no terraform, meus prognósticos seriam em torno da versão 2.27 ... provavelmente :-)

@igoratencompass Eu uso aws_autoscaling_group para criar instâncias.

Eu etiqueto as instâncias no modelo e uso essa tag para recuperar IPs na seção data .

Vejo que não estava ciente desse recurso de módulo de dados.

https://github.com/terraform-providers/terraform-provider-aws/issues/511#issuecomment -401362499 é uma solução alternativa, mas tenha cuidado na página do documento

Observação: é altamente desencorajado o uso dessa fonte de dados para consultar instâncias efêmeras (por exemplo, gerenciadas por meio de grupo de dimensionamento automático), pois a saída pode mudar a qualquer momento e você precisará executar a aplicação novamente sempre que uma instância for ativada ou morrer.

Esta nota é outro motivo para implementar esta nova fonte de dados

você pode extrair todos os dados da instância com uma pesquisa rodada.

(exemplo supondo que algum asg chamado aws_autoscaling_group.one já esteja definido)

data "aws_instances" "nodes" {
  depends_on = [ "aws_autoscaling_group.one" ]

  instance_tags {
    Name = "some_unique_tag_in_your_asg"
  }
}

data "aws_instance" "asg-one-instances" {
  count = "${ var.asg_one_count }"
  depends_on = ["data.aws_instances.nodes"]
  instance_id = "${data.aws_instances.nodes.ids[count.index]}"
}

output "private-ips" {
  value = "${ data.aws_instance.asg-one-instances.*.private_ip }"
}

output "public-ips" {
  value = "${ data.aws_instance.asg-one-instances.*.public_ip }"
}

output "private-dnsnames" {
  value = "${ data.aws_instance.asg-one-instances.*.private_dns }"
}

output "public-dnsnames" {
  value = "${ data.aws_instance.asg-one-instances.*.public_dns }"
}

mas eu preferiria ter os dados da instância diretamente disponíveis nos atributos asg.

@syncroswitch o problema que vejo com isso é a variável asg_one_count . É um valor estático que irá/pode não corresponder ao estado real do ASG em execuções consecutivas, ou seja, o ASG cresceu ou diminuiu no tempo médio.

@syncroswitch @igoratencompass funciona para obter os endpoints e ips privados quando você inicia, que é o que é mais necessário.

Além disso, basta definir count = "${ var.asg_one_count }" para count = ${aws_autoscaling_group.one.desired_capacity}

Se as pessoas realmente precisam de ips dinâmicos, devem escrevê-lo em python, bash, go, etc e chamá-lo de terraform e usá-lo em vez da capacidade desejada, mas duvido que seja realmente necessário ou desejado a longo prazo.

Comecei com a configuração do @syncroswitch e terminei com uma solução alternativa mais simples:

data "aws_instances" "ecs_instances_meta" {
  instance_tags = {
    # Use whatever name you have given to your instances
    Name = var.ecs_cluster_name
  }
}

output "ecs-private-ips" {
  value = data.aws_instances.ecs_instances_meta.private_ips
}
Esta página foi útil?
0 / 5 - 0 avaliações