hostnamectl / timedatectl —— 改主机名与时区
一句话定义
这是 systemd 的"set state"系列工具,取代了 vim /etc/hostname 和 vim /etc/timezone 这种手改文件:
hostnamectl—— 设置主机名(hostname)timedatectl—— 设置时区、NTP、本地/UTC 硬件时钟
两个命令风格一样、用法对称,所以放一起讲。
典型场景
Day0 §4:装机基线的最后一步。改完虚拟化探测、磁盘、SSH 之后,把 5 台机器的 hostname 改成 k8s-cp-1 ~ k8s-w-2,时区统一到 UTC(K8s 集群强烈建议跟 UTC、避免本地时间踩坑)。
hostnamectl set-hostname k8s-cp-1
timedatectl set-timezone UTC
为什么不直接改 /etc/hostname
echo "k8s-cp-1" > /etc/hostname # ❌ 不推荐
直接改有三个问题:
- 当前 shell 看到的 hostname 不变(要 logout 或
hostname命令手动同步) - 不通知 dbus —— 其它在运行的服务(rsyslog、Avahi、kubelet)感知不到变化
- 不一致 ——
/etc/hostname只是其中一个 hostname,systemd 还有"transient hostname"和"pretty hostname"概念
hostnamectl set-hostname 帮你处理这些:
- 写
/etc/hostname - 通知 dbus
- 立刻在所有视角下生效
- 处理多种 hostname 类型
hostnamectl 用法
看当前 hostname
$ hostnamectl
Static hostname: k8s-cp-1
Icon name: computer-vm
Chassis: vm
Machine ID: abc123...
Boot ID: def456...
Virtualization: kvm
Operating System: Ubuntu 22.04 LTS
Kernel: Linux 5.15.0-...
Architecture: x86-64
只看 hostname:
hostnamectl --static # 等价于 cat /etc/hostname
hostname # 也行
改 hostname
hostnamectl set-hostname k8s-cp-1
立刻生效(包括当前 shell 的 \h 提示符也会变 —— 重连 ssh 后看得到)。
三种 hostname 类型
| 类型 | 说明 | 怎么改 |
|---|---|---|
| Static | 持久 hostname,存 /etc/hostname | hostnamectl set-hostname xxx |
| Transient | 动态 hostname(DHCP / 内核默认) | 重启 / 网络变化时自动 |
| Pretty | 人类可读名(含空格、Unicode) | hostnamectl set-hostname "My Laptop" --pretty |
绝大多数场景只需要 Static。Pretty 是给 GUI 看的。
集群里批量改
ssh m1 'hostnamectl set-hostname k8s-cp-1'
ssh m2 'hostnamectl set-hostname k8s-cp-2'
# ... etc
或者用 for 循环 + 数组(参考 Day0 §4):
declare -A HOSTS=(
[m1]=k8s-cp-1
[m2]=k8s-cp-2
[m3]=k8s-cp-3
[m4]=k8s-w-1
[m5]=k8s-w-2
)
for alias in "${!HOSTS[@]}"; do
ssh "$alias" "hostnamectl set-hostname ${HOSTS[$alias]}"
done
hostname 改完之后还要做的事
hostnamectl 只改 hostname 本身。但很多服务依赖 hostname → IP 的映射,需要同步改 /etc/hosts:
# 5 节点统一的 /etc/hosts
cat > /etc/hosts <<'EOF'
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
10.0.24.28 k8s-cp-1 m1
10.0.24.29 k8s-cp-2 m2
10.0.24.30 k8s-cp-3 m3
10.0.24.31 k8s-w-1 m4
10.0.24.32 k8s-w-2 m5
EOF
为什么 /etc/hosts 重要:
- kubeadm init 要解析自己的 hostname 到 IP;如果 hostname 只在 DNS 里、或者根本没解析,会失败
- 节点间通信:kubelet → apiserver、kube-proxy → service 等都涉及反查 hostname
- etcd peer:用 hostname 在 SAN 证书里,没解析就 TLS 失败
K8s 安装 99% 的"hostname not found"或"x509: certificate signed by ... is not valid for ..."类问题都和 /etc/hosts 缺失有关。
timedatectl 用法
看当前时间状态
$ timedatectl
Local time: Mon 2026-05-27 14:30:15 UTC
Universal time: Mon 2026-05-27 14:30:15 UTC
RTC time: Mon 2026-05-27 14:30:15
Time zone: UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
关键字段:
- Local time:当前时间(按时区计算)
- Universal time:UTC 时间(无时区)
- RTC time:硬件时钟(主板 BIOS 时间)
- Time zone:时区
- System clock synchronized:是否和 NTP 同步过(boot 时和现在都同步过返回 yes)
- NTP service:是否有活跃的 NTP 同步服务
- RTC in local TZ:硬件时钟是否走本地时间(默认应该
no,走 UTC)
设时区
timedatectl list-timezones # 看所有可用时区
timedatectl list-timezones | grep -i shanghai
timedatectl set-timezone UTC # K8s 集群推荐 UTC
timedatectl set-timezone Asia/Shanghai # 上海时区
K8s 集群强烈建议所有节点统一用 UTC:
- 日志时间在所有节点能直接对比
- 容器里的应用通常默认 UTC,日志一致
- 跨时区团队协作无歧义
启用 / 禁用 NTP
timedatectl set-ntp true # 启用 systemd-timesyncd
timedatectl set-ntp false # 禁用
注意:这里启用的是 systemd-timesyncd(systemd 自带的轻量 NTP 客户端)。生产环境通常用更专业的 chrony,两者不能同时跑。
chrony vs systemd-timesyncd
| 维度 | systemd-timesyncd | chrony |
|---|---|---|
| 安装 | systemd 自带 | 要装 chrony 包 |
| 精度 | 一般 | 高 |
| 网络瞬断恢复 | 慢 | 快(最快秒级) |
| 能当 NTP 服务端 | ❌ | ✅ |
| K8s 推荐 | 仅小型实验 | ✅ 生产标配 |
装 chrony 就要禁掉 timesyncd(不然两者抢着同步 / 互相打架):
apt-get install -y chrony
timedatectl set-ntp false # 关 timesyncd
systemctl enable --now chrony # 起 chrony
确认:
timedatectl # NTP service: 应该是 active(chrony 也算)
chronyc tracking # chrony 自己的状态
chronyc sources # 看上游 NTP 服务器
为什么 K8s 对时间敏感
K8s 几乎所有组件对时间漂移都敏感:
- etcd raft —— leader election、心跳都用时间。漂移超过 500ms 会导致 leader 频繁换 → 集群抖动
- TLS 证书校验 ——
Not Before/Not After字段。节点时间比证书早 → 证书"还没生效";晚 → 证书"过期" - kubelet → apiserver token —— ServiceAccount token 有 issued-at / expiry,漂移超过容忍范围被拒
- HPA 决策 —— 按时间窗口算 metric,漂移导致决策错乱
- 日志关联 —— 节点 A 在 10:00 发了请求、节点 B 在 09:59 收到,分布式追踪全乱
集群里所有节点的时间漂移要 < 50ms。chrony 默认能做到 < 10ms。
hostname / 时区 一气呵成的装机段(Day0 §4)
HOSTNAME="$1" # 各机器自己的名字传进来
ssh root@$ip "
# 1. hostname
hostnamectl set-hostname $HOSTNAME
# 2. /etc/hosts 全集群一致
cat > /etc/hosts <<'HOSTS'
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
10.0.24.28 k8s-cp-1 m1
10.0.24.29 k8s-cp-2 m2
10.0.24.30 k8s-cp-3 m3
10.0.24.31 k8s-w-1 m4
10.0.24.32 k8s-w-2 m5
HOSTS
# 3. 时区 UTC
timedatectl set-timezone UTC
# 4. 启用 chrony(已装的话)
systemctl enable --now chrony 2>/dev/null || true
# 5. 验证
hostnamectl --static
timedatectl | grep -E 'Time zone|NTP'
"
常见踩坑
坑 1:改了 hostname,但提示符没变
hostnamectl set-hostname k8s-cp-1
# bash 提示符还是 root@old-name
bash 的 \h 提示符是 shell 启动时缓存的。重新登录或 exec bash:
exec bash
# 或
exit && ssh m1
坑 2:/etc/hosts 里 hostname 指向 127.0.0.1,K8s 起不来
Ubuntu 装机有时 /etc/hosts 默认:
127.0.1.1 k8s-cp-1
这会让 kubeadm 解析 hostname 时拿到 127.0.1.1,证书 SAN 不匹配,集群挂。
修复:删掉那行,改成真实 IP:
10.0.24.28 k8s-cp-1 m1
坑 3:节点时间差 5 分钟,TLS 报"signed by unknown authority"
x509: certificate has expired or is not yet valid: current time ... is after ...
时间问题伪装成证书问题。先 timedatectl 看时间:
ssh m1 'timedatectl'
ssh m2 'timedatectl'
# 看 Local time 差距
如果差几分钟以上:
ssh m1 'systemctl restart chrony'
sleep 5
ssh m1 'chronyc tracking' # System time: 0.0001 seconds slow
坑 4:硬件时钟(RTC)跑本地时间
RTC in local TZ: yes
通常 Windows 双系统的机器是这样(Windows 把 RTC 设成本地时间)。Linux 默认 RTC 走 UTC。两者打架会让重启后时间偏差几小时。
修复:
timedatectl set-local-rtc 0 # RTC 走 UTC
云机器一般默认正确。物理机 / 双系统才需要注意。
坑 5:set-ntp 报错
timedatectl set-ntp true
# Failed to set ntp: NTP not supported
通常是因为系统装了 chrony / ntpd,systemd-timesyncd 已经被禁用。这种情况你不需要 set-ntp true —— chrony 自己跑着就行。
确认 chrony 在工作:
chronyc tracking
chronyc sources
坑 6:hostname 太长 / 含特殊字符
hostnamectl set-hostname "我的机器 1"
# Failed: hostname "我的机器 1" is not valid
Static hostname 必须是 RFC 1123 合规:字母数字、-、.,最长 64 字符。中文 / 空格 / 下划线都不行。
要"漂亮"的名字用 pretty hostname:
hostnamectl set-hostname "My K8s Master" --pretty
hostnamectl set-hostname "k8s-cp-1" --static
但 K8s 集群里别用 pretty,到处显示的 hostname 都是 static 那个。
关联命令
- systemctl —— hostnamectl/timedatectl 同属 systemd 工具家族
chronyc—— 看 chrony 状态(tracking,sources)hostname—— 老式查看(只读用);hostname xxx老式设置(不持久)date—— 看当前时间 / 设置时间(不推荐手动设、让 NTP 处理)- journalctl —— 看 chrony / timesyncd 日志:
journalctl -u chrony -f