创建 AWS EC2 实例时 userdata 的一些知识

我们在初始一个 AWS EC2 实例时,可以通过 user data 让 EC2 第一次启动后做些事情,可以放置 shell script 或 cloud-init 指令。在控制台设置 user data 可用明文文本,由 awscli 创建时可使用一个文件,或者通过 API 用 base64 编码的内容。

下面是 user data 被执行时需知晓的一些知识

  1. 是脚本时必须以 #! 开始,俗称 Shebang, 如 #!/bin/bash
  2. user data是以 root 身份执行,所以不要用 sudo, 当然创建的目录或文件的 owner 也是 root,需要 ec2-user 用户访问的话需要 chmod 修改文件权限,或者直接用 chown ec2-user:ec2-user -R abc 修改文件的所有者()
  3. 脚本不能交互,有交互时必须想办法跳过用户输入,如 apt install -y xzy, 带个  -y 标记
  4. 如果脚本中需访问 AWS 资源,权限由 Instance Profile 所指定的 IAM role 决定
  5. user data 中的脚本会被存储在  /var/lib/cloud/instances/<instance-id>/user-data.txt 文件中,因此也可以从这里验证 user data 是否设置正确。或者在 EC2 实例上访问 http://169.254.169.254/latest/user-data 也能看到 user data 的内容。并且在 EC2 实例初始化后不被删除,所以以此实例为基础来创建一个新的 AMI 需把它删除了
  6. user data 的大小限制为 16 KB, 指 base64 编码前的大小
  7. cloud-init 的输出日志在 /var/log/cloud-init-output.log, 它会捕获 cloud-init 控制台的输出内容

user data 的内容通常在创建好实例后,还得等一会才完全生效,马上用 SSH 登陆新创建后的实例一般还看不到效果,有可能得等分把钟。

下面是在一个选择了 Ubuntu 18.04 镜像的 EC2 实例的 user data 样例 -- 用来安装 Python 3.9, 并创建虚拟环境, 安装 Python 组件

脚本的内容会存储在 EC2 实例上,但它执行的控制台输出却没地方找,如果脚本执行过程中有问题就难以诊断了,这里有个办法可记录下 user data 中脚本执行的控制台输出,需在 user data 中加上一行,最后把调试也打开

对,你没有看错,上面的 exec > >(... 两个大括号之间有空格

这样就能在实例的 /var/log/user-data.log 中看到所有 user data 中脚本执行的控制台输出了,错在哪一步也就能有的放矢的修正。

比如本人有一次发现 user data 中的脚本没发生作用,就查看 /var/log/user-data.log 中的内容发现错误信息

E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?

原来是还有一个进程也在执行 apt,继而 Google 到 apt-daily.service 启动的时候在干那事,查看它的日志

$ journalctl -u apt-daily.service
-- Logs begin at Thu 2021-09-09 07:38:01 UTC, end at Sat 2021-09-18 17:29:41 UTC. --
Sep 18 17:23:21 lin-0aff3d81.mstarext.com systemd[1]: Starting Daily apt download activities...
Sep 18 17:23:46 lin-0aff3d81.mstarext.com systemd[1]: Started Daily apt download activities.

所以在 user data 需要避开它,我们的 user data 可以加一个  sleep 30 进行延迟执行,30 不够的话就 sleep 60

已启动 EC2 实例的 user data 只允许在实例停止后被修改,但修改后的内容并不会在重启后得到执行,只不过是更新了一下文件 /var/lib/cloud/instances/<instance-id>/user-data.txt 中内容,无用功,难道是在掩盖现场?

How can I utilize user data to automatically run a script with every restart of my Amazon EC2 Linux instance?(user data 设计为只在第一次初始化 EC2 实例时起作用,有人曲折的方式让实例每次重启时也执行 user data 中的内容,个人觉得没多大意义,每次启动执行何不做成一个服务呢?)

关于 cloud-init 指令式的 user data

要在 user data 中放置 cloud-init 指令, 需在 user data 的第一行写上 #cloud-config。cloud-init 的用户可比脚本复杂了,它能做一些更高级的事情。这里就不深究,暂时还感觉不到非得用 cloud init 指令不成的境地,下面只看一个节选自官方的例子

它是 YAML 文件格式,比起用脚本可难看多了, runcmd 中一会用 sh 加中括号参数的形式,一会又直接 shell 脚本。个人认为上面的 sudo 是不需要的。

cloud-init 指令应该与系统中的 cloud-init 命令是相关的,EC2 实例中可以看到一个配置文件 /etc/cloud/cloud.cfg.

#cloud-config 形式的执行输出到控制台的内容会写到 /var/log/cloud-init-out.log 文件中,希望它记录下更多 cloud-init 执行时调试信息的话,在 user data 的  cloud-init 指令中加上一句

链接:

  1. Work with instance user data
  2. Logging user-data Script Output on EC2 Instances
  3. Run commands on your Linux instance at launch
  4. How to Fix 'E: Could not get lock /var/lib/dpkg/lock/log' Error in Ubuntu Linux
  5. How can I utilize user data to automatically run a script with every restart of my Amazon EC2 Linux instance?

本文链接 https://yanbin.blog/launch-aws-ec2-instance-userdata-knowledge/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

1 Comment
Inline Feedbacks
View all comments
trackback

[…] EC2 的 Linux 实例,所以之前写过的一篇关于 UserData 的日志 创建 AWS EC2 实例时 userdata 的一些知识 默认就是讲的有关 Linux 实例的 UserData。本文补充上 Windows 的 EC2 实例 UserData […]