虽然各种云的虚拟机都推荐使用 SSH 密钥登录,但是还是有很多人喜欢使用密码登录,而且有的时候需要通过 console 来登录系统。那么如何更好的设置、修改虚拟机的密码呢?本文以 OpenStack 为例,介绍如何设置及修改虚拟机密码。
1、内置密码
这是最简单的,制作镜像的时候直接给 root 账号配置一个密码。但是问题也不言而喻,所有的示例都有相同的默认密码,如果用户忘记修改密码,其它人很容易的就能扫到你的机器,从而登录你的机器。
2、启动时通过 libvirt 进行密码注入
这种方法是在 nova.conf里面开始如下配置:
[libvirt]
inject_password = false
inject_key = false
inject_partition = -2
在虚拟机启动的时候,通过 --admin-pass 传入一个指定的密码。但是这个方法也有一系列的问题:
● 不支持 Boot from volume
● 代码层面上,如果注入失败,没有任何错误信息报出来。
● libvirt 注入对物理机来说并不安全,有安全隐患。
● 密码并没有持久化(存入数据库),也不应该做持久化,在 evacuate 或 unshelve 的时候,这些密码信息会被丢掉。
所以这个方法也不推荐使用,更详细的信息,可能参看另一篇文章《rbd 是否支持注入》。
3、通过 metadata api 注入
cloud-init 这个服务是从 AWS 学来的。它安装在虚拟机中,在启动虚拟机时,做一些初始化工作,如:硬盘分区自动扩展、SSH Public Key 注入、用户创建等。用户甚至可以注入一些 shell 脚本到虚拟机中运行。在自动化方面起到很大的作用。Heat 的实现就依赖于 cloud-init 服务。
在 OpenStack 上,cloud-init 应该从 http://169.254.169.254 去拿到所需要的信息,而这个服务是通过 iptables 转到了 neutron-metadata-agent 服务上。
通过 cloud-init 注入也有几种方式,下面分别进行介绍。
脚本
因为在虚拟机启动的时候,是可以传入 shell 脚本的 user_data,所以可以在这个 shell 脚本里面修改 root 密码。
cat <<EOF > user_data.sh
#!/bin/sh
passwd root<<EOF
root_pass
root_pass
EOF
nova boot --user-data ./user_data.sh --image ...
cloud init configuration
user data 也可以是 cloud-init 支持的一个 yaml 结构文件,所以还可以通过如下方式改密码:
#cloud-config
password: password
chpasswd:
expire: False
这种方式要比「脚本」的方法优雅一些,推荐使用。而且cloud-init 本身功能很强大,值得深入挖掘。
config drive
默认情况下,metadata api 是通过 http://169.254.169.254 这个地址获取元数据信息。此外,nova 也支持使用 disk 的方式传入元数据。方便在网络环境不允许 metadata api 的情况下使用。性能也比 metadata api 好的多。
config drive 的开启方法是在 nova.conf 中配置:
[DEFAULT]
force_config_drive = true
或在启动虚拟机的时候,加上如下参数:
nova boot --config-drive true --image ...
开启 config drive 后,除了上面提到的「脚本」和「cloud init configuration」方式,还可以使用 nova 的 --admin-pass 参数。虽然这时密码是注入到了虚拟中,但是 cloud init 并不支持读取这里的密码,所以会失败。不过可以修改下 cloud init 支持这种方式。具体更多信息参看[参考文献1]。
4、通过 nova set-password
nova 还支持通过 libvirt 的 set-user-password 接口来修改正在运行的虚拟密码。这个接口本质上是通过 qemu-guest-agent 的 guest-set-user-password 接口来修改密码。所以对 libvirt 及 qemu-guest-agent 的版本都有要求。
libvirt > 1.2.16 # host
qemu-guest-agent[2] > 2.3 # linux guest
qemu-guest-agent[3] > 2.5 # window guest
现在看支持的 Guest 操作系统如下:
● CentOS 6 / CentOS 7
● Ubuntu 16.04 / Ubuntu 18.04
● Window XP 及之后所有的版本
值的一提的是 CentOS 6 虽然用的 qemu-guest-agent 版本是 qemu-guest-agent-0.12.1.2-2.491.el6_8.6.x86_64,但是红帽已经把相关 patch backport 了回头,所以也是支持。
使用方法如下:
● 做镜像的时候,安装 qemu-gest-agent 到虚拟机,并且开启随机启动。
● 上传镜像的时候,加上相关的 metadata 信息: glance image-create --property hw_qemu_guest_agent=yes
5、虚拟机自动生成加密密码
很早之前,nova 还支持了虚拟机生成密码,然后加密后传回 nova 的功能[参考文献4]。其原理如下:
1、虚拟机动态生成 root 的密码
2、把 root 密码通过 ssh public key 加密
3、把加密后的密码通过 POST /openstack/latest/password 接口传回 nova
4、用户通过nova get-password命令来拿到密码后的密码
5、用户使用自己的 ssh private key 进行密码揭密。
因为密钥对等加密原因,除了「1」「5」可以看到明文密码外,其它步骤里面都是加密的。所以这种方式可以说是最安全的方案。连云平台提供商都不能看到真正的密码。
不过这种方式只在 Windows 的 cloud init 版本 cloudbase-init 里面有实现[参考文献5]。Linux 版本的 cloud-init 并不支持。不过 Github 上面找到一个类似的实现[参考文献6],虽然只支持 RHEL 7, 但是有需要的话,可以参考修改下。
6、如果我忘记了虚拟机密码怎么办
● 如果你还有虚拟机的 ssh private key,可能通过 ssh 登录机器修改密码
● 如果你的虚拟机平台支持 nova set-password, 可以在线改
如果以上都不满足,就需要手动重置 root 密码,基本思路是在 Linux 启动的时候,进入一个不需要密码登录的环境,然后修改 root 密码,步骤如下:
1、通过 horizon, 打开对应虚拟机的 console 界面
2、软重启虚拟机,
3、在 grub 界面按字母e
4、找到 linux 一行,这一行中加入 init=/bin/bash, 并删掉 console=tty0 console=ttyS0,115200, 把 ro 改为 rw
5、按 ctrl + x 继续启动
6、这时你应试就可以直接登录到系统里面,通过 passwd 命令直接修改密码
7、硬重启操作系统 nova reboot --hard
以上言简意赅的介绍了几种如何设置及修改虚拟机密码的方法,感兴趣的OpenStacker可以亲身实践,同时在本文结尾提供了更多相关文献供参考。
参考文献:
[1] http://niusmallnan.com/_build/html/_templates/openstack/inject_passwd.html#cloud-init
[2]https://github.com/qemu/qemu/commit/215a2771a7b6b29037ee8deba484815d816b6fdd
[3]https://github.com/qemu/qemu/commit/259434b8067e1c61017e9a5b8667b6526b474ff2
[4] https://review.openstack.org/#/c/17274/
[5] https://github.com/openstack/cloudbase-init/blob/master/cloudbaseinit/metadata/services/httpservice.py
[6] https://github.com/vvaldez/openstack-password-reset
[0] https://zhangchenchen.github.io/2017/01/19/openstack-reset-instance-password
转载于:https://blog.51cto.com/99cloud/2094331