在之前的周会上汇报Kubernetes学习结果的时候,被问到一个问题:“一个Service能否提供多种服务,能否代理多组Pod副本?”这里来做一定的研究。
Service基本概念
Kubernetes里的每个Service其实就是微服务架构中的一个“微服务”。
Service定义了一个服务的访问入口地址。前端的应用(Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,Service与其后端Pod副本集群之间则是通过Label Selector来实现“无缝对接”的。
kube-proxy进程通过Service的Label Selector来选择对应的Pod,自动建立起每个Service到对应Pod的请求转发路由表,从而实现Service的智能负载均衡机制。
每个Pod都会被分配一个单独的IP地址,而每个Pod都提供了一个独立的Endpoint(PodIP+ContainerPort)以被客户端访问。
现在多个Pod副本组成了一个集群来提供服务,客户端如何访问它们呢?
常规做法 | Kubernetes做法 |
---|---|
部署一个负载均衡器,为这组Pod开启一个对外的服务端口,如8000端口,并将这些Pod的Endpoint列表加入8000端口的转发列表中,客户端就可以通过负载均衡器的对外IP地址+服务端口来访问此服务。 | kubernetes遵循了常规做法,运行在每个Node上的kube-proxy进程其实就是一个智能的软件负载均衡器,它负责把对Service的请求转发到后端的某个Pod实例上,并且在内部实现服务的负载均衡与会话保持机制。 |
相较常规做法,Kubernetes的Service不是共用一个负载均衡器的IP地址,每个Service都被分配了一个全局唯一的虚拟IP地址(Cluster IP),每个服务就变成了具备唯一IP地址的“通信节点”
通过创建Service,可以为一组具有相同功能的容器提供一个统一的入口地址,并且将请求进行负载分发到后端的各个容器应用上。
Service多端口问题
许多服务都存在多端口的问题,通常一个端口提供业务服务,一个端口提供管理服务。Kubernetes Service支持多个Endpoint,在存在多个Endpoint的情况下,要求每个Endpoint定义一个名字来区分。
例子:
appVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
name: service-port
nodePort: 30001
- port: 8005
name: shutdown-port
nodePort: 30002
selector:
app: myweb
试验Service代理多组Pod
在kubernetes学习记录(6)——Guestbook Demo 的基础上进行修改试验
只修改frontend-service.yaml。如下
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
type: NodePort
ports:
- port: 80
name: frontend
nodePort: 30001
#添加端口8080的映射
- port: 8080
name: myweb
nodePort: 30002
selector:
app: guestbook
tier: frontend
创建myweb1-rc.yaml,如下:
apiVersion: c1
kind: ReplicationController
metadata:
name: myweb1
spec:
replicas: 1
selector:
app: guestbook
tier: frontend
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: myweb1
image: 192.168.121.140:5000/tomcat:v1
ports:
- containerPort: 8080
这样,kube-proxy进程通过label selector,可以建立frontend service到frontend pod和myweb1 pod两组pod的请求转发路由表。
执行
kubectl replace -f frontend-service.yaml
kubectl create -f myweb1-rc.yaml
kubectl get svc frontend -o wide
可以看见80端口被映射到了30001上,8080端口被映射到了30002上。
验证,在浏览器上分别输入nodeip:30001和nodeip:30002。
均可以打开。
结论
通过试验,我的结论是,Service中的关键字段是ports和selector,通过selector和port端口,service提供服务。
所以我认为一个Service能提供多种服务,能代理多组Pod副本。