我们知道,k8s 中的 service 最主要的一个功能,是允许我们对集群中的一个或一组 pods 方便地进行网络访问。但其实它还有另外一个用途,将外部服务映射到集群内,方便集群内的其它应用像访问内部服务一样地访问它。
在采用 k8s 后,一些遗留系统或者因为迁移不方便或者因为为了同时服务于多个环境,而仍然以原来的方式运行着(不受 k8s 管理)。如果想让 k8s 内的 pods 访问这些遗留的服务,怎么办?
hostAliases
,给外部服务定义一个别名,以别名的方式访问。不好的地方在于,每个需要访问该外部服务的 pod,都需要定义hostAliases
:apiVersion: v1
kind: Pod
metadata:
name: hostaliases-pod
spec:
hostAliases:
- ip: "172.16.181.198"
hostnames:
- "some-external-service"
kind: Service
apiVersion: v1
metadata:
name: some-external-service
spec:
type: ClusterIP
ports:
- port: 8088
targetPort: 8088
---
kind: Endpoints
apiVersion: v1
metadata:
name: some-external-service
subsets:
- addresses:
- ip: 172.16.181.198
ports:
- port: 8088
对于上面第三个方案,当配置完成后,所有 pod 都可以以http://some-external-service:8088
的形式来访问外部服务了。
需要注意的点有:
name
要一致;另外,如果这个外部服务需要暴露到公网,你原先可能是用 nginx 在公网机器做代理转发,而现在,我们可以复用 k8s 的 ingress 机制,让 k8s 去管理代理转发了,我们要做的,就是定义一个简单的 Ingress 对象:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-some-external-service
namespace: default
spec:
rules:
- host: some-external-service.example.com
http:
paths:
- backend:
serviceName: some-external-service
servicePort: 8088
path: /
tls:
- hosts:
- some-external-service.example.com
secretName: tls-example.com
上述的host
即公网可访问的域名,而backend
就是我们要暴露的外部服务,如果需要启用https
访问,就再配置一个tls
条目。
如此,一个完整的外部服务纳入 k8s 集群的方案就完成了。