Kubernetes服务发现主要可以归为三种情形:
- Kubernetes集群内部间服务如何互相通信;
- Kuberntes集群外部如何访问集群内部服务;
- Kubernetes集群内部如何访问集群外部服务。
集群间服务通信
部署Pod对应的Service,访问Service IP,请求负载均衡转发服务到各个对应的Pod实例。
比如有如下配置文件demo.yml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-d
spec:
selector:
matchLabels:
name: web-app
replicas: 3
template:
metadata:
labels:
name: web-app
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-s
spec:
ports:
- port: 8080
targetPort: 80
protocol: TCP
selector:
name: web-app
运行该配置,查看Service对应的IP:
通过Service IP和端口就能访问对应的Pod服务:
但是我们事先并不知道Service的IP是多少,如果我们在启动服务后再去配置这个IP的话,这个过程也是非常麻烦的,所幸我们可以通过DNS解决这个问题,也就是下面这种方式:
部署Pod对应的Service,通过ServiceName,请求负载均衡转发服务到各个对应的Pod实例。
通过下面这段配置部署一个新的Pod服务:
apiVersion: v1
kind: Pod
metadata:
name: centos-pod
spec:
containers:
- name: centos
image: centos
command:
- sh
- -c
- 'while true; do sleep 360000000; done'
进入到该容器内部,测试下是否可以访问上面创建的Service:
试着通过ServiceName访问Nginx服务:
可以看到效果是一样的。这得益于Kube-dns,具体的格式为:<service_name>.
所以除了使用curl nginx-s:8080访问外,以下这些也是等效的:
curl nginx-s.default:8080
curl nginx-s.default.svc:8080
curl nginx-s.default.svc.cluster.local:8080
所以我们现在可以不用事先知道Service的IP了,只要事先知道ServiceName即可(ServiceName是我们自己定义的)。
通过Headless Service,返回Pod的所有实例。
有时候我们并不需要Service的负载均衡功能,而是手动获取Service对应的Pod实例,自己决定如何访问。创建一个Headless Service配置:
apiVersion: v1
kind: Service
metadata:
name: nginx-headless-s
spec:
ports:
- port: 8080
clusterIP: None
selector:
name: web-app
创建该Headless Service,然后到centos-pod容器内部查询DNS记录:
如果没有nslookup命令,可以使用yum -y install bind-utils命令安装。
可以看到,通过解析nginx-headless-s DNS,返回了三个Nginx Pod实例地址。
集群外部访问内部
1.Pod指定hostPort,或者开启hostNetwork,这样外部就可以通过Pod宿主机IP+Pod端口访问了,但Pod调度的不确定性,这种方式不推荐;
2.通过Service的NodePort暴露服务,如果服务较多的话不推荐,因为这种方式会在集群中的所有节点上都暴露该端口,所以当服务多的时候很容易造成端口冲突,并且端口维护不便;
3.通过Ingress集中暴露服务,要暴露的服务较多的时候推荐。
这三种方式是前面博客中都有介绍到,所以就不赘述了。
集群内部访问外部
1.直接通过外部服务的IP和端口进行访问;
2.通过Service和Endpoint绑定,集群内的服务通过DNS访问集群外部服务(推荐)。
创建如下配置(test-remote.yml):
apiVersion: v1
kind: Service
metadata:
name: remote-s
spec:
ports:
- protocol: TCP
port: 8081
targetPort: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: remote-s
subsets:
- addresses:
- ip: 192.168.73.42
ports:
- port: 8080
Service和Endpoints名称一样,所以他们会绑定上,通过访问remote-s Service便可以访问到对应的Endpoint地址192.168.73.42:8080服务(这是个我在集群外部,通过Spring Boot搭建的简单web服务)。
运行该配置后,在master节点上,测试是否可以访问:
我们进到centos-pod容器内部,通过服务名称看看是否可以访问到:
可以看到这种方式也是没问题的,推荐使用这种方式,可以降低耦合度。
- 本文链接: https://blog.zoozer.club/archives/k-u-b-e-r-n-e-t-e-s-fu-wu-fa-xian
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!