集群内的应用有时候需要调用外部的服务,我们知道集群内部服务调用都是通过 Service 互相访问,那么针对外部的服务是否也可以保持统一使用 Service 呢?答案是肯定的,通过 Service 访问外部服务,除了方式统一以外,还能带来其他好处。如配置统一,不同环境(空间)相同应用访问外部不同环境的数据库,可以通过 Service 映射保持两边配置统一,达到不同空间应用通过相同 Service Name 访问不同的外部数据库。如图 test-1 和 test-2 两个空间为两个不同的业务环境,通过服务映射,不同空间相同的 Service 访问到对应外部不同环境的数据库: 另外,还可以保证最小化变更,如果外部数据库 IP 之类的变动,只需要修改 Service 对应映射即可,服务本身配置无需变动。具体场景如下: 创建之后,同一空间 Pod 就可以通过 mysql:3306 访问外部的 MySQL 服务。 需要注意的是,虽然 externalName 也支持填写 IP,但是并不会被 Ingress 和 CoreDNS 解析(KubeDNS 支持)。如果有 IP 相关的需求,则可以使用 Headless Service -> Type ExternalName 。另外一个需要注意的是,因为 CNAME 的缘故,如果外部的服务又经过一层代理转发,如 Nginx,除非配置对应的 server_name ,否则映射无效。 前文提过,虽然 externalName 字段可以配置为 IP 地址,但是 Ingress 和 CoreDNS 并不会解析,如果外部服务为 IP 提供,那么可以使用 Headless Service 实现映射。 service 不指定 selector,手动维护创建 endpoint,创建之后就可以通过 mysql:3306 访问 192.168.1.10:3306 服务的目的。Headless Service 不能修改端口相关,如果要修改访问端口,则需要进一步操作。 如果外部的端口不是标准的端口,想通过 Service 访问时候使用标准端口,如外部 MySQL 提供端口为 3307,内部想通过 Service 3306 访问,这个时候则可以通过如下方式实现: service 不指定 selector,手动维护创建 endpoint,创建之后就可以通过 mysql:3306 达到访问外部 192.168.1.10:3307 服务的目的。 我们可以看出以上外部服务映射,externalName 和 Headless Service 方式映射外部服务是没有经过中间层代理的,都是通过 DNS 劫持实现。而有端口变更需求的时候,则要经过内部 kube-proxy 层转发。正常情况下,能尽可能少的引入中间层就少引用,特别是数据库类的应用,因为引入中间层虽然带来了便利,但也意味着可能会带来性能损耗,特别是那些对延迟比较敏感的服务。 来源地址:https://blog.opskumu.com/kubernetes-ext-service.html1外部域名映射到内部 Service ->ExternalName
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
externalName: mysql.example.com
type: ExternalName
2外部 IP 映射到内部 Service
2.1IP 映射
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: mysql
subsets:
- addresses:
- ip: 192.168.1.10
2.2IP + 端口映射
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
type: ClusterIP
ports:
- port: 3306
targetPort: 3307
---
apiVersion: v1
kind: Endpoints
metadata:
name: mysql
subsets:
- addresses:
- ip: 192.168.1.10
ports:
- port: 3307
3小结