文章目录
- [解决Ubuntu执行sudo时 unable to resolve host 报错问题](#解决Ubuntu执行sudo时 unable to resolve host 报错问题)
-
- 一、背景与问题现象
- 二、根因分析
-
- [1. sudo 警告的根因](#1. sudo 警告的根因)
- [2. 为什么 hosts 会被覆盖](#2. 为什么 hosts 会被覆盖)
- 三、处理思路总览
- 四、操作步骤
-
- [步骤 1:确认并开启 manage_etc_hosts](#步骤 1:确认并开启 manage_etc_hosts)
- [步骤 2:先备份(重要)](#步骤 2:先备份(重要))
- [步骤 3:把业务域名写入模板文件](#步骤 3:把业务域名写入模板文件)
-
- [为什么不用手动加 `127.0.1.1 ip-172-1-7-33`?](#为什么不用手动加
127.0.1.1 ip-172-1-7-33?)
- [为什么不用手动加 `127.0.1.1 ip-172-1-7-33`?](#为什么不用手动加
- [步骤 4:立即重新渲染 hosts](#步骤 4:立即重新渲染 hosts)
- 五、结果验证
-
- [1. 查看生成后的 /etc/hosts](#1. 查看生成后的 /etc/hosts)
- [2. 验证命令](#2. 验证命令)
- 六、长期收益与维护规范
-
- [⚠️ 维护红线](#⚠️ 维护红线)
- 七、总结
解决Ubuntu执行sudo时 unable to resolve host 报错问题
本文记录了一次在 Ubuntu(cloud-init 环境)上排查
sudo: unable to resolve host警告,并通过 cloud-init 模板机制规范化管理/etc/hosts的完整过程,包含前因后果与排查思路。
一、背景与问题现象
服务器为运行在云上的 Ubuntu 实例(由 cloud-init 管理),主机名类似 ip-172-1-7-33。在执行 sudo 命令时,出现如下告警:
sudo: unable to resolve host ip-172-1-7-33: Name or service not known
同时还有一个诉求:需要在 /etc/hosts 中长期维护若干业务域名的静态解析,例如内部管理后台、SOC 平台等。
遇到的核心矛盾
在 cloud-init 管理的机器上,如果直接手动编辑 /etc/hosts:
- 重启后配置会丢失------cloud-init 会用模板重新覆盖生成该文件。
因此,直接 vim /etc/hosts 加几行并不是可靠的长期方案。
二、根因分析
1. sudo 警告的根因
sudo 在执行时会尝试解析当前主机名。如果 /etc/hosts 里没有一条能匹配当前主机名(hostname 输出值)的记录,解析失败,就会报 unable to resolve host。
解决方向:确保 /etc/hosts 中存在一条把主机名映射到本地回环地址的记录,通常是:
127.0.1.1 <fqdn> <hostname>
2. 为什么 hosts 会被覆盖
/etc/cloud/cloud.cfg 中存在配置项 manage_etc_hosts。它有几种取值:
| 取值 | 行为 |
|---|---|
false / 不配置 |
cloud-init 不管理 hosts,手动改动会保留(但也失去自动维护主机名的能力) |
true |
cloud-init 每次启动都用模板 /etc/cloud/templates/hosts.debian.tmpl 重新生成 /etc/hosts |
localhost |
只确保 localhost 相关记录,其余不动 |
关键决策 :我们选择开启 manage_etc_hosts: true。这样带来两个好处:
- cloud-init 会通过模板变量
{``{hostname}}/{``{fqdn}}自动填入当前主机名,从根本上、且"自愈式"地消除 sudo 警告。 - 业务域名写入模板后,重启也不会丢失。
代价是:必须改用模板管理 hosts,不能再直接手改 /etc/hosts。
三、处理思路总览
开启 manage_etc_hosts: true
│
├─► 备份原始文件(hosts / cloud.cfg / 模板)
│
├─► 把业务域名写入模板文件(而非 /etc/hosts)
│
├─► 用 cloud-init 立即重新渲染 hosts
│
└─► 验证:sudo 无警告 + 主机名可解析 + 业务域名可解析
核心原则:改模板,不改 hosts。
四、操作步骤
步骤 1:确认并开启 manage_etc_hosts
编辑 /etc/cloud/cloud.cfg,确保存在:
yaml
manage_etc_hosts: true
步骤 2:先备份(重要)
在改动任何系统文件前,务必备份:
bash
sudo cp /etc/hosts /etc/hosts.bak.$(date +%F)
sudo cp /etc/cloud/cloud.cfg /etc/cloud/cloud.cfg.bak.$(date +%F)
sudo cp /etc/cloud/templates/hosts.debian.tmpl /etc/cloud/templates/hosts.debian.tmpl.bak.$(date +%F)
步骤 3:把业务域名写入模板文件
编辑模板文件(不是 /etc/hosts):
bash
sudo vim /etc/cloud/templates/hosts.debian.tmpl
在模板末尾追加业务域名。注意:模板里已经存在 127.0.1.1 {``{fqdn}} {``{hostname}} 这一行,因此无需再手动加主机名记录,只需追加 cloud-init 无从知晓的业务域名:
jinja
# 模板中原有(保持不动)------会自动渲染出主机名
127.0.1.1 {{fqdn}} {{hostname}}
127.0.0.1 localhost
# ==== 以下为手动追加的业务域名 ====
# 业务后台
172.1.7.162 admin.xx.com
# SOC 平台
172.1.7.200 biz-unit.aa.yy.com
172.1.7.200 api.bb.yy.com
为什么不用手动加 127.0.1.1 ip-172-1-7-33?
这是本次排查中一个关键认知点:
- 模板里的
127.0.1.1 {``{fqdn}} {``{hostname}}是 Jinja 模板变量,渲染时会被 cloud-init 自动替换成当前主机名。 - 如果写死
127.0.1.1 ip-172-1-7-33,一旦主机名变化(例如实例更换 IP 后主机名自动变更),写死的记录就对不上,sudo 警告会重新出现。 - 用
{``{hostname}}/{``{fqdn}}则永远匹配当前主机名,真正做到自愈。
| 模板变量 | 渲染结果(示例) |
|---|---|
{``{hostname}} |
ip-172-1-7-33 |
{``{fqdn}} |
ip-172-1-7-33.ap-xxxx.compute.internal |
步骤 4:立即重新渲染 hosts
不必等到重启,可用 cloud-init 手动触发一次渲染:
bash
sudo cloud-init single --name update_etc_hosts --frequency always
五、结果验证
1. 查看生成后的 /etc/hosts
bash
cat /etc/hosts
输出(已脱敏):
# Your system has configured 'manage_etc_hosts' as True.
# As a result, if you wish for changes to this file to persist
# then you will need to either
# a.) make changes to the master file in /etc/cloud/templates/hosts.debian.tmpl
# b.) change or remove the value of 'manage_etc_hosts' in
# /etc/cloud/cloud.cfg or cloud-config from user-data
#
127.0.1.1 ip-172-1-7-33.ap-xxxx.compute.internal ip-172-1-7-33
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# 业务后台
172.1.7.162 admin.xx.com
# SOC 平台
172.1.7.200 biz-unit.aa.yy.com
172.1.7.200 api.bb.yy.com
可以看到:
127.0.1.1那一行由模板变量自动渲染出了完整 FQDN 与主机名;- 三条业务域名完整保留。
2. 验证命令
bash
# sudo 警告应消失,直接输出 root
sudo whoami
# 主机名可被解析
grep "$(hostname)" /etc/hosts
# 业务域名可正常解析
getent hosts admin.xx.com
getent hosts biz-unit.aa.yy.com
getent hosts api.bb.yy.com
预期:sudo whoami 不再出现 unable to resolve host 告警,业务域名均能返回对应 IP。
六、长期收益与维护规范
启用该方案后,这台机器获得以下能力:
- 重启不丢配置------cloud-init 每次以模板重建 hosts,主机名与业务域名均在。
- 主机名自愈 ------
{``{hostname}}动态填充,即使更换 IP / 主机名,sudo 警告也不会再出现。 - 集中管理------所有 hosts 变更统一在模板中维护。
⚠️ 维护红线
开启
manage_etc_hosts: true后,禁止直接手动编辑/etc/hosts,否则重启会被覆盖。所有变更都应改模板文件
/etc/cloud/templates/hosts.debian.tmpl,然后执行:
bashsudo cloud-init single --name update_etc_hosts --frequency always
七、总结
| 环节 | 关键点 |
|---|---|
| 现象 | sudo 报 unable to resolve host;且直接改 hosts 会被覆盖 |
| 根因 | 主机名无解析记录;cloud-init 的 manage_etc_hosts 会重建 hosts |
| 方案 | 开启 manage_etc_hosts: true,改用模板管理 |
| 关键认知 | 模板里 {``{hostname}}/{``{fqdn}} 自动填主机名,无需写死 |
| 手动只需加 | cloud-init 不知道的业务域名 |
| 维护规范 | 只改模板,不改 hosts;改完手动渲染一次 |
这次排查的核心思路是:先搞清楚"谁在管理这个文件",再顺着它的机制去做变更 ,而不是与自动化工具对抗。理解 manage_etc_hosts 的模板渲染机制后,问题从"反复丢配置"转变为"配置自愈",一劳永逸。