一、ExternalName 适合什么问题

ExternalName 是一种很特别的 Service。它没有 selector,也不直接维护 Endpoints,而是通过 DNS CNAME 把服务名映射到另一个域名。

最典型的写法:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

访问 my-service.prod.svc.cluster.local 时,集群 DNS 最终会返回 my.database.example.com 的 CNAME 结果。

二、ExternalName 的价值不在转发,而在解耦

ExternalName 本质是 DNS 级别映射,不是代理转发。所以它的优点是:

  • 配置简单
  • 不需要手工维护后端 IP
  • 很适合让应用继续用统一服务名

原文还给了一个跨命名空间的映射例子:让命名空间 b 中的 mysql,映射到命名空间 a 里的 mysql.a.svc.cluster.local

apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: b
spec:
  type: ExternalName
  externalName: mysql.a.svc.cluster.local

这样一来,b 命名空间里的应用只需要访问 mysql:3306,而不必关心真实服务到底在哪个命名空间。

三、ExternalName 的最小实战示例

原文用 www.baidu.com 做了最简单的演示:

apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  type: ExternalName
  externalName: www.baidu.com

创建后:

kubectl create -f externalname-service.yaml
kubectl get svc
kubectl exec -it nginx-deployment-xxx -- sh
wget external-service

即便返回 403 Forbidden,也说明解析和访问路径已经通了。

四、为什么 ExternalName 很适合多环境同名依赖

原文最有价值的部分,其实是 DEV/UAT 环境示例。思路是:

  • 基础组件分别部署在 basic-component-devbasic-component-uat
  • 业务项目自己的命名空间里都创建同名 redis Service
  • 通过 ExternalName 把它们分别指向各自环境的 Redis

例如:

kind: Service
apiVersion: v1
metadata:
  name: redis
  namespace: projecta-dev
spec:
  type: ExternalName
  externalName: redis.basic-component-dev.svc.cluster.local
---
kind: Service
apiVersion: v1
metadata:
  name: redis
  namespace: projecta-uat
spec:
  type: ExternalName
  externalName: redis.basic-component-uat.svc.cluster.local

这样 projecta-dev 里的应用和 projecta-uat 里的应用都只写 redis,但会自动连到不同环境的后端。

五、如果外部后端不是域名,而是固定 IP 怎么办

这时就不能只靠 ExternalName 了,更适合用“Service + Endpoints”来代理集群外服务。

原文给出的示例如下:

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc-external
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
  name: nginx-svc-external
subsets:
- addresses:
  - ip: 103.235.46.102
  ports:
  - name: http
    port: 80
    protocol: TCP

这种方式的关键点有两个:

  • Service 不能再写 selector
  • Service 和 Endpoints 的 nameportprotocol 要保持一致

创建后,集群内应用就可以像访问普通 ClusterIP 一样访问这个外部地址。

六、该怎么选更合适

可以用一个简单原则区分:

  • 后端是稳定域名:优先用 ExternalName
  • 后端是固定 IP 或你想手工维护地址列表:用 Service + Endpoints

两种方式的共同目标其实一样:让业务程序不要直接写死真实外部地址,而是通过集群里的统一服务名完成解耦。