在上一期《生命的火花》中,我们提到,一组pod可以通过service机制,对外提供一个名称。Kubernetes会将这个名称映射到带有同一个标签的Pod,将指向service的访问分发到各个pod上。
让我们看一个例子。
如图所示,我们创建了3个运行着elasticsearch的pod,对外的service名称为es1。
这3个pod的IP地址分别为:
172.17.50.101/24
172.17.50.104/24
172.17.50.113/24
它们对外提供服务的IP为 172.17.30.254/24。
在kubernetes中,我们可以通过yaml来配置它们:
apiVersion: v1 #对象描述规范版本
kind: Service #对象类型为service
metadata:
name: es1 #service对象名称:es1
labels:
name: es #该service对象对外的标签:es。有可能有其他service也使用这个标签。
spec:
type: ClusterIP #这里代表是ClusterIP类型的负载均衡方式
clusterIP: 172.17.30.254 #对外提供服务的IP
ports:
- port: 80 #这里的端口是pod服务的监听端口。
targetPort: 80 #这个端口是pod对外暴露服务的端口
protocol: TCP
selector:
app: elasticsearch #这个标签是后端pod组的标签
这样,就可以将一组具有elasticsearch的标签的Pod,以es1的名称对外发布为一个service,这个service名称将解析为IP地址 172.17.30.254,端口80。
我们注意到,service的type字段为ClusterIP。实际上,kubernetes可以支持三种service模式:
第一种为NodePort,是一种简单粗暴地将Node上的端口,一对一映射到Node内部的Pod上的方式。这种方式的问题在于,如果一个node上有两个pod,监听同样的端口,会造成冲突。
第二种是ClusterIP。这种方式实际上类似负载均衡的VIP。
实际上,ClusterIP方式下,对指向clusterip这个地址的请求,分发到各个pod的实现,是由kube-proxy实现的。
我们翻开厚厚的kubernetes文档,会发现,kube-proxy本质上是一个监视器,它监视pod的创建和销毁,并调用iptables或ipvs进行转发。
如下图:
如果我们有一组容器pod,具有标签MyApp,监听9376端口,kube-proxy只负责控制iptables或ipvs对请求进行转发。
当然,ipvs比iptables有更高的转发效率,LB算法也更丰富,只是要付出部署的代价。
但,clusterip仅限于在容器环境内部使用。如果我们需要将容器服务对容器环境外部,如互联网或公司企业内网开放,我们还需要第三种模式——
第三种是LoadBalancer。这种方式可以对接第三方的负载均衡。我们知道,无论是ipvs还是iptables,它的转发都需要消耗node上宿主机的CPU资源。而第三方专用负载均衡硬件,也恰好能够用专业的硬件实现专业的功能。正可谓:他山之石可以攻玉。
敬请期待下期详解。