ExternalName 是什么
ExternalName 是一种特殊 Service:它不分配虚拟 IP,也不做任何转发,只是在集群 DNS 里给外部域名起一个集群内的别名。Pod 访问这个服务名时,DNS 返回一条指向 externalName 的 CNAME 记录,由客户端自己去解析并连接。它解决的是「集群内想用统一名字访问外部依赖」,而不是「把外部流量代理进集群」。
基本信息
| 关键字段 | spec.type 为 ExternalName,spec.externalName 填外部域名 |
|---|---|
| 是否分配虚拟 IP | 不分配,spec.clusterIP 为空 |
| 是否经过 kube-proxy | 不经过,集群里没有对应的转发规则 |
| 是否需要选择器 | 不需要 selector,Endpoints 也是空的 |
| 端口处理 | 清单里无需声明 ports,客户端按 externalName 的地址与端口直连 |
| 生效范围 | 仅在集群 DNS 内生效,集群外访问不到这个别名 |
清单与验证
清单与验证
apiVersion: v1
kind: Service
metadata:
name: legacy-db
namespace: prod
spec:
type: ExternalName
externalName: db.legacy.example.com # 只能是域名,不能写 IP验证解析链路
验证解析链路
kubectl get svc legacy-db -o jsonpath='{.spec.type}{" "}{.spec.externalName}' # 确认类型与目标
kubectl get endpoints legacy-db # ExternalName 的端点为 <none>,属预期
kubectl run dns-test --rm -it --restart=Never --image=busybox:1.36 -- \
nslookup legacy-db.prod.svc.cluster.local # 应看到指向外部域名的 CNAME
kubectl exec -it web-x -- nc -vz legacy-db 5432 # 连通性仍取决于外部网络与端口典型使用场景
- 迁移过渡期:把原来的集群内数据库名指向外部实例,应用配置不用改
- 环境统一命名:测试与生产用同一个服务名,各自指向不同的外部地址
- 接入托管服务:外部托管数据库、消息队列在集群内有一个收敛的访问入口名字
- 分阶段搬迁:先用 ExternalName 顶住访问,服务搬进集群后再换成普通 Service
- 避免硬编码域名:把外部域名收敛到一处清单里,换域名只改一个对象
几种外部访问做法
| 做法 | 工作方式 | 主要局限 |
|---|---|---|
| ExternalName | 集群 DNS 返回外部域名的 CNAME | 无端口映射、无健康检查、无虚拟 IP |
| 无选择器 Service 加手工 EndpointSlice | 直接指向固定 IP 与端口 | 地址要自己维护,目标变化需人工更新 |
| 普通 ClusterIP 加外部后端 | 需要真正的 Pod 作为后端 | 不适合集群外的固定外部地址 |
externalName 只接受域名,写 IP 会被校验拒绝;目标地址变化时由外部 DNS 负责,集群侧对象不需要改。外部解析慢或不稳定时,问题在主 DNS 与网络路径,不在 Service 对象上。
TLS 场景容易踩坑:客户端用服务名发起连接时,服务端证书里的域名是真实域名,可能与服务名不匹配导致校验失败。切换前先用测试 Pod 验证,必要时让应用使用真实域名或配置证书。另外 NetworkPolicy 的选择器基于 Pod,管不到外部目标,出向限制要写成目标网段。