简体   繁体   English

使用 cloud-init 和实例标签在 EC2 上设置主机名?

[英]Set hostname on EC2 using cloud-init and instance tags?

Is there a way to use the values from instance tags to set the hostname on an EC2 instance, using cloud-init in user-data?有没有办法使用实例标签中的值在用户数据中使用 cloud-init 来设置 EC2 实例上的主机名?

Something like this?是这样的吗?

#cloud-config
preserve_hostname: false
hostname: my-custom-hostname
fqdn: my-custom-hostname.local
manage_etc_hosts: true

Except using an instance tag, such a "Name" or "hostname".除了使用实例标签,例如“名称”或“主机名”。 I've seen some examples using Jinja templates, which seems to be along the right lines.我看过一些使用 Jinja 模板的示例,它们似乎是正确的。 But I'm not sure if/how to reference the instance tags in the user-data/cloud-init.但我不确定是否/如何在用户数据/云初始化中引用实例标签。 If this makes more sense to bake into the AMI, I don't mind that - it doesn't have to be user-data.如果这对融入 AMI 更有意义,我不介意 - 它不一定是用户数据。 However, I currently am running a hostmod.sh shell script at instance launch that reads the tags, and sets the hostname.但是,我目前正在实例启动时运行hostmod.sh shell 脚本,该脚本读取标签并设置主机名。

## template: jinja
preserve_hostname: false
hostname: {% tags.hostname %}
fqdn: {% tags.hostname %}.local
manage_etc_hosts: true

One idea that worked for me was use shell parameter expansion (I think that's the right term).对我有用的一个想法是使用 shell 参数扩展(我认为这是正确的术语)。 I am still maintaining my own script, baked into my AMI, but I prefer the template-like approach versus my previous script that used sed to modify the /etc/hosts file.我仍在维护自己的脚本,嵌入到我的 AMI 中,但我更喜欢类似模板的方法,而不是我之前使用 sed 修改/etc/hosts文件的脚本。

#!/bin/bash

# Get Name tag from AWS instance metadata
ec2id=$(curl http://169.254.169.254/latest/meta-data/instance-id)
hostname=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$ec2id" "Name=key,Values=Name" --region us-east-1 | awk '/"Value":/ {print $2}' | tr -d '",')
fqdn="${hostname}.local"

# Write a new hosts file using variable expansion
cat >/etc/hosts <<EOF
# The following lines are desirable for IPv4 capable hosts
127.0.0.1 ${fqdn} ${hostname}
127.0.0.1 localhost.localdomain localhost
127.0.0.1 localhost4.localdomain4 localhost4
# The following lines are desirable for IPv6 capable hosts
::1 ${fqdn} ${hostname}
::1 localhost.localdomain localhost
::1 localhost6.localdomain6 localhost6
EOF

I run the script via cloud-init defined in user data:我通过用户数据中定义的 cloud-init 运行脚本:

#cloud-config
runcmd:
  - bash /usr/local/bin/hostmod.sh

I also tried creating the entire script within user data via cloud-config.我还尝试通过 cloud-config 在用户数据中创建整个脚本。 This works as well, but I split the file out to make it easier to manage separately in Ansible.这也可以,但我将文件拆分出来以便在 Ansible 中单独管理。

#cloud-config
write_files:
  - path: /usr/local/bin/hostmod.sh
    permissions: 0744
    owner: root
    content: |
      #!/bin/bash

      ec2id=$(curl http://169.254.169.254/latest/meta-data/instance-id)
      hostname=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$ec2id" "Name=key,Values=Name" --region us-east-1 | awk '/"Value":/ {print $2}' | tr -d '",')
      fqdn="${hostname}.local"

      cat >/etc/hosts <<EOF
      # The following lines are desirable for IPv4 capable hosts
      127.0.0.1 ${fqdn} ${hostname}
      127.0.0.1 localhost.localdomain localhost
      127.0.0.1 localhost4.localdomain4 localhost4
      # The following lines are desirable for IPv6 capable hosts
      ::1 ${fqdn} ${hostname}
      ::1 localhost.localdomain localhost
      ::1 localhost6.localdomain6 localhost6
      EOF

runcmd:
  - bash /usr/local/bin/hostmod.sh

This obviously doesn't change the hostname, which is a bit more platform dependent.这显然不会改变主机名,这更依赖于平台。 That is why I preferred to use cloud-init from the start.这就是为什么我从一开始就喜欢使用 cloud-init。 I may later add a similar template for updating the hostname.我稍后可能会添加一个类似的模板来更新主机名。

This script will allow you to update the Amazon Linux (v1) hostname configured in /etc/sysconfig/network - both parts are necessary to correctly configure the hostname.此脚本将允许您更新在/etc/sysconfig/network中配置的 Amazon Linux (v1) 主机名 - 这两个部分都是正确配置主机名所必需的。

#! /bin/bash
#
export EC2_AVAIL_ZONE=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone` 
export EC2_REGION="`echo \"$EC2_AVAIL_ZONE\" | sed 's/[a-z]$//'`"
export ec2id=$(curl http://169.254.169.254/latest/meta-data/instance-id )
export ec2name=$(aws ec2 describe-tags --filters "Name=resource-id,Values=$ec2id" "Name=key,Values=Name" --region $EC2_REGION | awk '/"Value":/ {print $2}' | tr -d '",')
#
hostname ${ec2name}
cat > /etc/sysconfig/network << EOF
NETWORKING=yes
HOSTNAME=${ec2name}
NOZEROCONF=yes
EOF 

I know this is from a few years back and there's a reasonable solution listed, but tags are now available (since jan'22) in the metadata as well ( https://aws.amazon.com/about-aws/whats-new/2022/01/instance-tags-amazon-ec2-instance-metadata-service/ ) ie curl http://169.254.169.254/latest/meta-data/tags/instance/Name我知道这是几年前的事情,并且列出了一个合理的解决方案,但是元数据中现在也可以使用标签(自 1 月 22 日起)( https://aws.amazon.com/about-aws/whats-new /2022/01/instance-tags-amazon-ec2-instance-metadata-service/ ) 即 curl http://169.254.169.254/latest/meta-data/tags/instance

Cheers //A干杯//一个

To expand @mack answer, a simple working script to read a tag hostname is:要扩展@mack 答案,读取标签hostname的简单工作脚本是:

#!/bin/bash
export TAG_HOSTNAME=$(curl -s http://169.254.169.254/latest/meta-data/tags/instance/hostname)
hostnamectl set-hostname "$TAG_HOSTNAME"

Note that you have to turn on making the instance metadata tags available to the EC2 instance, either via console:请注意,您必须通过控制台打开使实例元数据标签对 EC2 实例可用:

右键单击实例以启用实例标签

Or with Terraform, like this:或者使用 Terraform,像这样:

resource "aws_instance" "somevm" {
  ...
  metadata_options {
    http_endpoint          = "enabled"
    instance_metadata_tags = "enabled"
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM