如何解决识别 ECS 实例的硬编码 DNS 记录
我有一个需要部署的 docker 镜像,同时保持一致的 DNS 记录。最重要的是,我想要一个硬编码的实例数量(例如,2)。我喜欢 ECS 的易用性以及 ECS 代理保持正常运行时间,但负载均衡器对于单个实例来说太过分了。到目前为止,我只是创建了一个最小/最大/期望为 1
的 ASG,因此没有任何冲突问题。
反对在自动缩放组中对实例进行编号的争论非常激烈(here 就是一个例子),这是有道理的,但我认为这是一个非常可靠的用例,无法避免。
>我已经成功地修改了 meltwater/terraform-aws-asg-dns-handler,为 ASG 中的单个 ECS 实例提供了一个硬编码的 DNS 记录(比如 instance-1.example.com
),尽管它不是很漂亮。为了让两个实例正常工作(instance-1.example.com
和 instance-2.example.com
),我想我有两个选择:
- 创建一个 hacky 解决方案来读取我的 Lambda 函数中现有的 Route53 记录,以“确定性地”决定在 ASG 生命周期挂钩中为我的实例分配哪个索引(this 可能是一个好的开始)
- 创建两个 ECS 集群,每个集群都有一个实例,并使用两个单独的 Lambda 函数
对我来说,这些都不是非常可靠的选择,所以我想知道是否有更好的方法以类似 ECS 的方式部署单个 Docker 容器,我可以将 DNS 记录附加到。
就上下文而言,“两个 ECS 集群”方法可以正常工作,但我将执行三到四次,因此我最终会在其他几个集群之上使用 8 个 ECS 集群,这就是至少可以说不方便。
解决方法
如果您使用 Auto Scaling 组和带有用户数据的启动配置或模板...这是我在用户数据中添加的内容,以便在新的任何时候自动保持 Route53 DNS 记录最新实例旋转起来,带有一个计数器。希望这可以帮助!
## --------------------------------------------------------------------------------------------------------------- ##
## --- AUTO SCALING LOGIC for user-data -------------------------------------------------------------------------- ##
## --------------------------------------------------------------------------------------------------------------- ##
## --- Get ip addresses of existing app DNS Entries (that point to app nodes,not load balancer) ----- ##
## --- Get this ip address --------------------------------------------------------------------------------------- ##
## --- If this IP Address matches any in existing list,do not create a new DNS record --------------------------- ##
## --- If this IP Address does not match any in existing list,create a new DNS record --------------------------- ##
## --------------------------------------------------------------------------------------------------------------- ##
region="us-east-1"
hosted_zone="ROUTE53-HOSTED-ZONE-ID"
vpc="vpc-ID"
r53_domain="example.com"
asg_desired="2"
application="app"
echo "USING EC2 INSTANCE META DATA TO OBTAIN IP ADDRESS ..."
echo "IF YOU ARE NOT USING DEFAULT AMZN INSTANCE,USE ifconfig OR ANOTHER METHOD TO OBTAIN THIS INSTANCE IP ..."
# CHOOSE THE PRIVATE (local-ipv4) OR PUBLIC IP DEPENDING ON USE CASE
#this_ip=`curl http://169.254.169.254/latest/meta-data/local-ipv4`
this_ip=`curl http://169.254.169.254/latest/meta-data/public-ipv4`
echo $this_ip > /tmp/this-ip.txt
# FILTER BASED ON UNIQUE TAGS FOR YOUR TARGETED INSTANCE(S)
# THIS IS USING Application Tag.
aws --region $region ec2 describe-instances --query "Reservations[*].Instances[? Tags[? (Key=='Application') && Value=='$application']].PublicIpAddress" --output text >> /tmp/existing-ec2-ips.txt
counter=1
until [ $counter -gt $asg_desired ]
do
aws --region $region route53 list-resource-record-sets --hosted-zone-id $hosted_zone --query "ResourceRecordSets[?Name == 'instance-$counter.$r53_domain.'].ResourceRecords" --output text >> /tmp/existing-ips.txt
aws --region $region route53 list-resource-record-sets --hosted-zone-id $hosted_zone --query "ResourceRecordSets[?Name == 'instance-$counter.$r53_domain.']" --output text >> /tmp/existing-records.txt
((counter++))
done
diff /tmp/existing-ips.txt /tmp/this-ip.txt
echo "Does this instance IP exist in a $application route53 record?"
this_ip_result=`grep $this_ip /tmp/existing-ips.txt | wc -l`
if [[ $this_ip_result -gt 0 ]]
then
echo "Yes,this instance IP already exists in a $application route53 record."
echo "Nothing left to do"
else
echo "No,this instance IP does not exist in a $application route53 record."
echo "Adding route53 record... "
counter=1
until [ $counter -gt $asg_desired ]
do
grep -L instance-$counter.$r53_domain /tmp/existing-records.txt > /tmp/instance-$counter.$r53_domain.txt
if [ -s /tmp/instance-$counter.$r53_domain.txt ]
then
echo "instance-$counter.$r53_domain does not exist... Adding!"
aws --region $region route53 change-resource-record-sets --hosted-zone-id $hosted_zone --change-batch '{ "Comment": "Auto Scaling Creating Record Set","Changes": [ { "Action": "CREATE","ResourceRecordSet": { "Name": "instance-'$counter'.'$r53_domain'","Type": "A","TTL": 120,"ResourceRecords": [ { "Value": "'"$this_ip"'" } ] } } ] }'
else
echo "Updating Record Set!"
echo "Updating Route53 Records with the following IPs ..."
diff /tmp/existing-ec2-ips.txt /tmp/existing-ips.txt | grep ">" | sed 's/> //g'
ip_update=`diff /tmp/existing-ec2-ips.txt /tmp/existing-ips.txt | grep ">" | sed 's/> //g'`
record_update=`grep -B 1 $ip_update /tmp/existing-records.txt | grep $application | awk '{print $1}' | awk 'FNR == 1 {print}'`
aws --region $region route53 change-resource-record-sets --hosted-zone-id $hosted_zone --change-batch '{ "Comment": "Auto Scaling Updating Record Set","Changes": [ { "Action": "UPSERT","ResourceRecordSet": { "Name": "'"$record_update"'","ResourceRecords": [ { "Value": "'"$this_ip"'" } ] } } ] }'
fi
((counter++))
done
fi