kubernetes的核心技术Service
这里写个前言吧
前面我们了解到Deployment只是保证了支撑服务的微服务Pod的数量,但是没有解决如何访问这些服务的问题。一个Pod只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP的和端口号提供服务。
要稳定的提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的后端服务实例。在K8s集群中,客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。
在K8s集群中,微服务的负载均衡是有kube-proxy实现的。kube-proxy是K8s集群内部的负载均衡器。它是一个分布式代理服务器,在K8s的每个节点上都有一个;这体现了它的弹性伸缩优势,需要访问服务的节点越多,提供负载均衡能力的kube-proxy就越多,高可用节点也随之增多。与之相比,我们平时在服务器端使用反向代理作负载均衡,还要进一步解决反向代理的高可用问题。
Service存在的意义
防止Pod失联(服务发现)
因为Pod每次创建都对应一个IP地址,而这个IP地址是短暂的,每次随着Pod的更新都会变化,假设我们的前端页面有多个Pod时,同时后端那也有多个Pod,这时候,他们之间的相互访问,就需要通过注册中心,拿到Pod的IP地址,然后去访问对应的Pod
定义Pod访问策略(负载均衡)
页面前端的Pod访问到后端的Pod,中间会通过Service一层,而Service在这里还能做负载均衡,负载均衡的策略有很多种实现策略,例如
- 随机
- 轮询
- 响应比
Pod和Service的关系
这里Pod和Service之间还是根据label和selector建立关联的(和Controller一样)
我们访问Service的时候,其实也是需要有一个IP地址,这个IP肯定不是pod的IP地址,而是虚拟IP
Service常用类型
SVC常用类型有四种:
- ClusterIP:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP
- NodePort:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过NodeIP:NodePort来访问该服务
- LoadBalancer:在NodePort的基础上,接触Cloud provider创建一个外部负载均衡器,将请求转发到NodeIP:NodePort
- ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用,没有任何类型代理(kubernetes1.7或更高版本的kube-dns支持)
举例
导出一个包含service的文件
kubectl expose deployment web --port=80 --target-port=80 --dry-run=client -o yaml > service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web1
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
status:
loadBalancer: {}
如果没有做设置的话,默认使用的是第一种方式ClusterIP,也就是只能在集群内部使用,我们可以添加type字段,来设置SVC的类型
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web1
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
status:
loadBalancer: {}
修改完成导入即可
kubectl apply -f service.yaml
kubectl get svc
就可以看到已经成功修改为NodePort类型了
然后是LoadBalanced: 对外访问应用使用公有云
node一般是在内网进行部署,而外网一般是不能被访问到的:
- 先找一台可以通过外网访问机器,安装nginx,反向代理
- 手动把可以访问的节点添加到nginx中
如果我们使用LoadBalancer,就会有负载均衡的控制器,类似与nginx的功能,就不需要自己添加到nginx上
最后一种是ExternalName
这种类型的SVC是通过返回CANME和它的值,可以将服务映射到externalName字段的内容(例如:www.yyjl.com)。ExternalName Service是Service的特例,它没有selector,也没有定义任何端口和Endpoint。相反,相对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供。
当查询主SVC_NAME.NAMESPACE.svc.cluster.local
时,集群的DNS服务将会返回一个值www.yyjl.com的CNAME记录。访问这个服务的工作方式和其他的相同,唯一不同的时重定向发生在DNS层,而且不会进行代理或者转发。
注意
SVC能够提供负载均衡的能力,但是在使用上有以下限制:
只提供4层负载能力,而没有7层负载功能,但有时候我们可能需要更多的匹配规则来转发请求,这点上4层负载均衡技术是不支持的