如何使用 Cloud Init 挂载未格式化的 EBS 卷
How To Use Cloud Init To mount an unformatted EBS volume
上下文
我正在为 jenkins 使用 https://wiki.jenkins.io/display/JENKINS/Amazon+EC2+Plugin,它允许我在 AWS EC2 中动态配置新的云实例作为构建从属。
我正在启动 ami-d834aba1
(亚马逊 Linux 2017.09.1)。
该插件也支持提供用户数据和块设备映射,目前我在阅读后提供这样的配置https://cloudinit.readthedocs.io/en/latest/
用户数据
#cloud-config
repo_update: true
repo_upgrade: all
package_upgrade: true
bootcmd:
- [ cloud-init-per, once, mkfs, -t, ext4, /dev/nvme1n1 ]
fs_setup:
- cmd: mkfs -t %(filesystem)s -L %(label)s %(device)s
label: jenkins
filesystem: 'ext4'
overwrite: false
device: '/dev/nvme1n1'
mounts:
- [ /dev/nvme1n1, /jenkins, "ext4", "defaults,nofail", "0", "2" ]
users:
- default
- name: jenkins
homedir: /jenkins
lock_passwd: true
ssh_authorized_keys:
- a-key
块设备映射
/dev/sdd=:100:true:gp2::encrypted
期望的行为
该实例将启动并附加一个新的 100GB 加密 EBS 卷,该卷将被格式化为 ext4
并安装在 /jenkins
作为 jenkins 用户的主目录。
观察到的行为
实例启动,100GB 的加密 EBS 卷被创建并附加到 EC2 实例(在 AWS 控制台中显示为正在使用和附加)。然而,
1) df -h
不显示文件系统。
2)
cat /etc/fstab
/dev/nvme1n1 /jenkins ext4 defaults,nofail,comment=cloudconfig 0 2
确实显示了它
3) sudo file -s /dev/nvme1n1
/dev/nvme1n1: data
将卷显示为 data
格式而不是 ext4
4) 由于文件系统不是 ext4,sudo mount-a 失败。
手动破解
如果我在启动后手动 SSH 到机器并且 运行:
sudo mkfs -t ext4 /dev/nvme1n1
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 26214400 4k blocks and 6553600 inodes
Filesystem UUID: 7a434f7a-c048-4c3d-8098-b810e2ff8f84
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
然后sudo mount -a
好像挂载了卷。
问题
有没有办法让设备自动格式化挂载?我尝试使用和不使用
bootcmd:
- [ cloud-init-per, once, mkfs, -t, ext4, /dev/nvme1n1 ]
理想情况下,它会在用户创建之前发生,因为新用户的主目录将位于这个新装载上。
如果实例停止并且 started/restarted 我不希望在启动时再次重新格式化而丢失所有数据。
我不知道如何使用默认 AMI 和云初始化脚本实现这一点。
我已经通过基于我想要的具有加密 EBS 卷的 AMI 创建我自己的 AMI 解决了这个问题。现在我只是通过 ID 启动这个 AMI,而不用担心格式化 EBS、附加、安装等。
它更简单,需要的配置更少。然而,最大的缺点是当新的基本 AMI 出现时,我不能简单地将 AMI ID 更新为最新的。我需要自己创建一个新的基础 AMI。
不理想,但它有效。如果有人知道如何做到这一点 "properly" 我想了解更多信息。
亚马逊上的 cloud-init Linux 不 支持 fs_setup
模块。因此,您的磁盘未格式化。此外,主目录 /jenkins 是为用户创建的,并用作挂载点。这会隐藏主目录。
我建议:
bootcmd:
- test -z "$(blkid /dev/nvme1n1)" && mkfs -t ext4 -L jenkins /dev/nvme1n1
- mkdir -p /jenkins
mounts:
- [ "/dev/nvme1n1", "/jenkins", "ext4", "defaults,nofail", "0", "2" ]
runcmd:
- useradd -m -b /jenkins jenkins
神奇的x-systemd.makefs
fstab选项可以在cloud-init中使用。如果设备还没有文件系统,那么 systemd 挂载单元将在挂载前自动格式化为指定的文件系统(不要使用 auto
)。
注意:使用 mount
手动挂载不会触发格式化,而是通过 systemd 启动,直接启动(systemctl start mnt-foo.mount
),或通过单元依赖(参见 RequiresMountsFor
https://www.freedesktop.org/software/systemd/man/systemd.unit.html) 有效。
参见 https://www.freedesktop.org/software/systemd/man/systemd.mount.html。
您可以在启动 EC2 实例时使用用户数据脚本轻松地做到这一点。这是一个示例用户脚本:
# make a directory for a drive
sudo mkdir /data
# format disk
yes | sudo mkfs.ext4 /dev/sdb
# mount it
sudo mount /dev/sdb /data
# persist
uuid=$(sudo blkid /dev/sdb | sed -n 's/.*UUID=\"\([^\"]*\)\".*//p')
sudo bash -c "echo 'UUID=${uuid} /data ext4 defaults' >> /etc/fstab"
上下文
我正在为 jenkins 使用 https://wiki.jenkins.io/display/JENKINS/Amazon+EC2+Plugin,它允许我在 AWS EC2 中动态配置新的云实例作为构建从属。
我正在启动 ami-d834aba1
(亚马逊 Linux 2017.09.1)。
该插件也支持提供用户数据和块设备映射,目前我在阅读后提供这样的配置https://cloudinit.readthedocs.io/en/latest/
用户数据
#cloud-config
repo_update: true
repo_upgrade: all
package_upgrade: true
bootcmd:
- [ cloud-init-per, once, mkfs, -t, ext4, /dev/nvme1n1 ]
fs_setup:
- cmd: mkfs -t %(filesystem)s -L %(label)s %(device)s
label: jenkins
filesystem: 'ext4'
overwrite: false
device: '/dev/nvme1n1'
mounts:
- [ /dev/nvme1n1, /jenkins, "ext4", "defaults,nofail", "0", "2" ]
users:
- default
- name: jenkins
homedir: /jenkins
lock_passwd: true
ssh_authorized_keys:
- a-key
块设备映射
/dev/sdd=:100:true:gp2::encrypted
期望的行为
该实例将启动并附加一个新的 100GB 加密 EBS 卷,该卷将被格式化为 ext4
并安装在 /jenkins
作为 jenkins 用户的主目录。
观察到的行为
实例启动,100GB 的加密 EBS 卷被创建并附加到 EC2 实例(在 AWS 控制台中显示为正在使用和附加)。然而,
1) df -h
不显示文件系统。
2)
cat /etc/fstab
/dev/nvme1n1 /jenkins ext4 defaults,nofail,comment=cloudconfig 0 2
确实显示了它
3) sudo file -s /dev/nvme1n1
/dev/nvme1n1: data
将卷显示为 data
格式而不是 ext4
4) 由于文件系统不是 ext4,sudo mount-a 失败。
手动破解
如果我在启动后手动 SSH 到机器并且 运行:
sudo mkfs -t ext4 /dev/nvme1n1
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 26214400 4k blocks and 6553600 inodes
Filesystem UUID: 7a434f7a-c048-4c3d-8098-b810e2ff8f84
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
然后sudo mount -a
好像挂载了卷。
问题
有没有办法让设备自动格式化挂载?我尝试使用和不使用
bootcmd:
- [ cloud-init-per, once, mkfs, -t, ext4, /dev/nvme1n1 ]
理想情况下,它会在用户创建之前发生,因为新用户的主目录将位于这个新装载上。
如果实例停止并且 started/restarted 我不希望在启动时再次重新格式化而丢失所有数据。
我不知道如何使用默认 AMI 和云初始化脚本实现这一点。
我已经通过基于我想要的具有加密 EBS 卷的 AMI 创建我自己的 AMI 解决了这个问题。现在我只是通过 ID 启动这个 AMI,而不用担心格式化 EBS、附加、安装等。
它更简单,需要的配置更少。然而,最大的缺点是当新的基本 AMI 出现时,我不能简单地将 AMI ID 更新为最新的。我需要自己创建一个新的基础 AMI。
不理想,但它有效。如果有人知道如何做到这一点 "properly" 我想了解更多信息。
亚马逊上的 cloud-init Linux 不 支持 fs_setup
模块。因此,您的磁盘未格式化。此外,主目录 /jenkins 是为用户创建的,并用作挂载点。这会隐藏主目录。
我建议:
bootcmd:
- test -z "$(blkid /dev/nvme1n1)" && mkfs -t ext4 -L jenkins /dev/nvme1n1
- mkdir -p /jenkins
mounts:
- [ "/dev/nvme1n1", "/jenkins", "ext4", "defaults,nofail", "0", "2" ]
runcmd:
- useradd -m -b /jenkins jenkins
神奇的x-systemd.makefs
fstab选项可以在cloud-init中使用。如果设备还没有文件系统,那么 systemd 挂载单元将在挂载前自动格式化为指定的文件系统(不要使用 auto
)。
注意:使用 mount
手动挂载不会触发格式化,而是通过 systemd 启动,直接启动(systemctl start mnt-foo.mount
),或通过单元依赖(参见 RequiresMountsFor
https://www.freedesktop.org/software/systemd/man/systemd.unit.html) 有效。
参见 https://www.freedesktop.org/software/systemd/man/systemd.mount.html。
您可以在启动 EC2 实例时使用用户数据脚本轻松地做到这一点。这是一个示例用户脚本:
# make a directory for a drive
sudo mkdir /data
# format disk
yes | sudo mkfs.ext4 /dev/sdb
# mount it
sudo mount /dev/sdb /data
# persist
uuid=$(sudo blkid /dev/sdb | sed -n 's/.*UUID=\"\([^\"]*\)\".*//p')
sudo bash -c "echo 'UUID=${uuid} /data ext4 defaults' >> /etc/fstab"