Terraform: 인스턴스가 "연결 가능"할 때까지 기다립니다
Terraform: 인스턴스가 "연결 가능"할 때까지 기다립니다
나는 A와 A가 있는 테라폼 코드를 가지고 있다:
resource "aws_instance" "example" {
ami = data.aws_ami.server.id
instance_type = "t2.medium"
key_name = aws_key_pair.deployer.key_name
tags = {
name = "example"
}
vpc_security_group_ids = [aws_security_group.main.id]
}
resource "null_resource" "example" {
provisioner "local-exec" {
command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -T 300 -i ${aws_instance.example.public_dns}, --user centos --private-key files/id_rsa playbook.yml"
}
}
작동하지만 가끔 버그가 있습니다(아마도 인스턴스가 보류 상태일 때). 내가 테라폼을 다시 실행할 때 - 그것은 예상대로 작동합니다.
질문:. 인스턴스가 실행 중이고 SSH 연결을 수락할 때만 local-exec을 실행하려면 어떻게 해야 합니까?
는 현재 리소스가 완료될 때까지만 대기하고 AWS API가 상태에 있음을 반환할 때까지만 대기합니다. OS를 시작한 후 프로비저닝 단계에서 SSH 연결을 수락할 수 있는 인스턴스까지는 상당한 차이가 있습니다.
이를 처리하는 한 가지 방법은 인스턴스가 준비될 때까지 대기할 수 있는 기능이 있으므로 먼저 인스턴스에서 프로비저닝 프로그램을 사용하는 것입니다. 이를 처리하기 위해 기존 코드를 변경하면 다음과 같습니다:
resource "aws_instance" "example" {
ami = data.aws_ami.server.id
instance_type = "t2.medium"
key_name = aws_key_pair.deployer.key_name
tags = {
name = "example"
}
vpc_security_group_ids = [aws_security_group.main.id]
}
resource "null_resource" "example" {
provisioner "remote-exec" {
connection {
host = aws_instance.example.public_dns
user = "centos"
private_key = file("files/id_rsa")
}
inline = ["echo 'connected!'"]
}
provisioner "local-exec" {
command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -T 300 -i ${aws_instance.example.public_dns}, --user centos --private-key files/id_rsa playbook.yml"
}
}
먼저 개인 키를 사용하는 사용자로 인스턴스의 공용 DNS 주소에 연결하려고 시도합니다. 연결되면 인스턴스에 대해 Ansible을 실행하는 기존 프로비저닝 프로그램으로 이동하기 전에 간단한 명령으로 실행됩니다.
SSH를 통해 연결하는 것만으로는 인스턴스를 프로비저닝하기에 충분하지 않을 수 있습니다. Ansible 스크립트가 패키지 관리자와 상호 작용하려고 하면 실행 중인 인스턴스의 사용자 데이터 스크립트가 잠겨 있을 수 있습니다. 이 경우 먼저 완료될 때까지 기다리는 스크립트를 원격으로 실행해야 합니다. 예제 스크립트는 다음과 같습니다:
#!/bin/bash
while [ ! -f /var/lib/cloud/instance/boot-finished ]; do
echo -e "\033[1;36mWaiting for cloud-init..."
sleep 1
done
다음은 이 문제에 대한 Ansible별 솔루션입니다. 이 코드를 플레이북에 추가합니다(역할을 사용하는 경우 pre_task 절도 있습니다)
- name: will wait till reachable
hosts: all
gather_facts: no # important
tasks:
- name: Wait for system to become reachable
wait_for_connection:
- name: Gather facts for the first time
setup:
인스턴스가 외부에 노출되지 않고(대부분의 프로젝트에서 시간의 약 90%) SSM 에이전트가 대상 인스턴스에 설치되어 있는 경우(새로운 AWS AMI가 함께 제공됨) SSM을 사용하여 인스턴스를 조사할 수 있습니다. 다음은 몇 가지 샘플 코드입니다:
instanceId=$1
echo "Waiting for instance to bootstrap ..."
tries=0
responseCode=1
while [[ $responseCode != 0 && $tries -le 10 ]]
do
echo "Try # $tries"
cmdId=$(aws ssm send-command --document-name AWS-RunShellScript --instance-ids $instanceId --parameters commands="cat /tmp/job-done.txt # or some other validation logic" --query Command.CommandId --output text)
sleep 5
responseCode=$(aws ssm get-command-invocation --command-id $cmdId --instance-id $instanceId --query ResponseCode --output text)
echo "ResponseCode: $responseCode"
if [ $responseCode != 0 ]; then
echo "Sleeping ..."
sleep 60
fi
(( tries++ ))
done
echo "Wait time over. ResponseCode: $responseCode"
AWS CLI가 로컬로 설치되어 있다고 가정하면 인스턴스에 대해 작업하기 전에 이 null_resource가 필요합니다. 저 같은 경우에는 AMI를 만들고 있었어요.
resource "null_resource" "wait_for_instance" {
depends_on = [
aws_instance.my_instance
]
triggers = {
always_run = "${timestamp()}"
}
provisioner "local-exec" {
command = "${path.module}/scripts/check-instance-state.sh ${aws_instance.my_instance.id}"
}
}
provisioner "local-exec" { command = "aws ec2 wait instance-status-ok --instance-ids ${self.id}" }