一、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-dev和basic-component-uat - 业务项目自己的命名空间里都创建同名
redisService - 通过 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 的
name、port、protocol要保持一致
创建后,集群内应用就可以像访问普通 ClusterIP 一样访问这个外部地址。
六、该怎么选更合适¶
可以用一个简单原则区分:
- 后端是稳定域名:优先用
ExternalName - 后端是固定 IP 或你想手工维护地址列表:用
Service + Endpoints
两种方式的共同目标其实一样:让业务程序不要直接写死真实外部地址,而是通过集群里的统一服务名完成解耦。