配置域名解析的时候,经常看到A记录、CNAME这些选项:
- A记录和CNAME到底有什么区别?
- 为什么GitHub Pages要求添加CNAME记录?
- 什么时候该用A记录,什么时候该用CNAME?
先说结论
| 对比项 | A记录 | CNAME记录 |
|---|---|---|
| 指向目标 | IP地址 | 另一个域名 |
| 解析次数 | 1次 | 2次或更多 |
| 根域名支持 | 支持 | 不支持 |
| 典型场景 | 直接指向服务器 | CDN、托管平台 |
| 灵活性 | 低(IP变更需修改) | 高(目标域名IP变更无感知) |
两种记录的本质区别
A记录:直接指向IP
A记录(Address Record)是最基础的DNS记录,直接把域名映射到IP地址。
css
# A记录配置
example.com. IN A 185.199.108.153
DNS查询过程很简单:
用户查询 example.com → DNS返回 185.199.108.153 → 完成
CNAME:指向另一个域名
CNAME(Canonical Name)记录不直接指向IP,而是指向另一个域名。
objectivec
# CNAME配置
blog.example.com. IN CNAME username.github.io.
DNS查询需要两步:
lua
用户查询 blog.example.com → DNS返回 username.github.io → 继续查询 → DNS返回 185.199.108.153 → 完成
用流程图表示更清楚:
为什么需要CNAME
看起来CNAME多了一次查询,更慢了。那为什么还要用它?
场景一:服务器IP会变
假设你用A记录把域名指向了一台服务器:
css
www.example.com. IN A 1.2.3.4
有一天服务器迁移了,IP变成了 5.6.7.8,你需要手动改DNS配置。如果有多个域名都指向这台服务器,每个都要改。
用CNAME就不一样了:
objectivec
www.example.com. IN CNAME myapp.hosting.com.
blog.example.com. IN CNAME myapp.hosting.com.
api.example.com. IN CNAME myapp.hosting.com.
服务器IP变了,只需要托管平台(myapp.hosting.com)更新它的A记录,你的所有域名自动生效。
场景二:CDN加速
CDN服务商会根据用户位置返回最近的节点IP。这个IP是动态的,不可能用A记录。
csharp
# 接入阿里云CDN
static.example.com. IN CNAME example.com.w.kunlunsl.com.
阿里云的CDN会自动把用户引导到最近的节点,你不需要关心具体IP是什么。
场景三:托管服务
GitHub Pages、Vercel、Netlify这类托管平台都要求用CNAME,原因是:
- 平台的服务器IP可能随时变化
- 平台需要通过域名识别你的站点
- 便于实现负载均衡和故障转移
CNAME的限制
根域名不能用CNAME
这是DNS协议的硬性规定。根域名(如 example.com)可能有MX记录(邮件)、NS记录(域名服务器)等,CNAME会与这些记录冲突。
objectivec
# 错误:根域名不能设置CNAME
example.com. IN CNAME username.github.io.
# 正确:使用www子域名
www.example.com. IN CNAME username.github.io.
那根域名怎么办?有两个方案:
方案一:用A记录直接指向IP
css
example.com. IN A 185.199.108.153
example.com. IN A 185.199.109.153
example.com. IN A 185.199.110.153
example.com. IN A 185.199.111.153
方案二:用ALIAS记录(部分DNS服务商支持)
ALIAS是一种"假的CNAME",在DNS服务商那边做了一层转换:
bash
# Cloudflare、DNSPod等支持
example.com. IN ALIAS username.github.io.
实际返回给用户的还是IP地址,但配置时可以填域名。
CNAME不能和其他记录共存
同一个域名,如果设置了CNAME,就不能再设置A记录、MX记录等。
erlang
# 错误:CNAME和MX冲突
mail.example.com. IN CNAME mailserver.com.
mail.example.com. IN MX 10 mailserver.com.
# 正确:分开使用不同子域名
www.example.com. IN CNAME hosting.com.
mail.example.com. IN MX 10 mailserver.com.
实战配置示例
GitHub Pages自定义域名
-
在仓库根目录创建
CNAME文件: -
在域名服务商添加CNAME记录:
bash
# DNS配置
blog.example.com. IN CNAME username.github.io.
- 验证配置:
bash
# 查看CNAME记录
dig CNAME blog.example.com
# 输出示例
;; ANSWER SECTION:
blog.example.com. 300 IN CNAME username.github.io.
username.github.io. 300 IN A 185.199.108.153
Vercel部署
bash
# www子域名用CNAME
www.example.com. IN CNAME cname.vercel-dns.com.
# 根域名用A记录
example.com. IN A 76.76.21.21
Cloudflare CDN
bash
# 接入Cloudflare
www.example.com. IN CNAME example.com.cdn.cloudflare.net.
Cloudflare的特殊之处在于它支持"CNAME Flattening",即使是根域名也可以配置CNAME,它会自动转换成A记录返回。
常见问题排查
配置了CNAME但不生效
检查TTL:DNS缓存可能还没更新,等待TTL时间过期。
bash
# 查看TTL
dig blog.example.com
# 缩短TTL加快测试(配置时设置)
blog.example.com. 60 IN CNAME username.github.io.
检查传播状态:
bash
# 使用nslookup指定DNS服务器
nslookup blog.example.com 8.8.8.8
# 或用在线工具
# https://dnschecker.org/
循环引用
css
# 错误:A指向B,B又指向A
a.example.com. IN CNAME b.example.com.
b.example.com. IN CNAME a.example.com.
DNS服务器会检测循环引用并报错,但排查起来比较麻烦。配置时避免复杂的CNAME链。
HTTPS证书问题
CNAME只是DNS层面的跳转,HTTPS证书需要在最终服务器上配置。
如果你把 blog.example.com CNAME到了 username.github.io,那么:
- GitHub Pages需要支持你的自定义域名
- 证书要能覆盖
blog.example.com
GitHub Pages会自动申请Let's Encrypt证书,但需要在仓库设置里开启HTTPS。
决策指南
objectivec
需要配置域名解析
├─ 托管在第三方平台(GitHub Pages、Vercel、Netlify)?
│ └─ 用 CNAME 指向平台域名
├─ 接入CDN?
│ └─ 用 CNAME 指向CDN域名
├─ 直接部署在自己的服务器?
│ ├─ IP固定且不会变?
│ │ └─ 用 A 记录
│ └─ IP可能变化?
│ └─ 考虑用 CNAME 指向一个自己控制的域名
└─ 根域名?
└─ 只能用 A 记录或 ALIAS(如果DNS服务商支持)
小结
- A记录:域名 → IP,简单直接,但IP变了要手动改
- CNAME:域名 → 域名 → IP,多一次查询,但更灵活
- 根域名不能用CNAME,这是DNS协议限制
- CDN、托管平台都用CNAME,因为它们的IP是动态的
选择的核心原则:如果目标IP可能变化,用CNAME;如果IP固定,用A记录。
如果你觉得这篇文章有帮助,欢迎关注我的 GitHub,下面是我的一些开源项目:
Claude Code Skills (按需加载,意图自动识别,不浪费 token,介绍文章):
- code-review-skill - 代码审查技能,覆盖 React 19、Vue 3、TypeScript、Rust 等约 9000 行规则(详细介绍)
- 5-whys-skill - 5 Whys 根因分析,说"找根因"自动激活
- first-principles-skill - 第一性原理思考,适合架构设计和技术选型
全栈项目(适合学习现代技术栈):
- prompt-vault - Prompt 管理器,用的都是最新的技术栈,适合用来学习了解最新的前端全栈开发范式:Next.js 15 + React 19 + tRPC 11 + Supabase 全栈示例,clone 下来配个免费 Supabase 就能跑
- chat_edit - 双模式 AI 应用(聊天+富文本编辑),Vue 3.5 + TypeScript + Vite 5 + Quill 2.0 + IndexedDB