该篇文章已经被专栏《从零开始学k8s》收录
上一篇文章:k8spod的容器探测与启动策略 点击跳转
Service
快速了解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
vip
Service常用类型
Service常用类型有三种
- ClusterIp:集群内部访问
- NodePort:对外访问应用使用
- LoadBalancer:对外访问应用使用,公有云
举例
我们可以导出一个文件 包含service的配置信息
kubectl expose deployment web --port=80 --target-port=80 --dry-run -o yaml > service.yaml
service.yaml 如下所示
apiVersion: v1
kind: Service
metadata:creationTimestamp:nulllabels:app: web
name: web
spec:ports:-port:80protocol: TCP
targetPort:80selector:app: web
status:loadBalancer:{}
如果我们没有做设置的话,默认使用的是第一种方式 ClusterIp,也就是只能在集群内部使用,我们可以添加一个type字段,用来设置我们的service类型
apiVersion: v1
kind: Service
metadata:creationTimestamp:nulllabels:app: web
name: web
spec:ports:-port:80protocol: TCP
targetPort:80selector:app: web
type: NodePort
status:loadBalancer:{}
修改完命令后,我们使用创建一个pod
kubectl apply -f service.yaml
然后能够看到,已经成功修改为 NodePort类型了,最后剩下的一种方式就是LoadBalanced:对外访问应用使用公有云
node一般是在内网进行部署,而外网一般是不能访问到的,那么如何访问的呢?
- 找到一台可以通过外网访问机器,安装nginx,反向代理
- 手动把可以访问的节点添加到nginx中
如果我们使用LoadBalancer,就会有负载均衡的控制器,类似于nginx的功能,就不需要自己添加到nginx上
四层负载均衡 Service:概念、原理解读
为什么要有 Service?
在 kubernetes 中,Pod 是有生命周期的,如果 Pod 重启它的 IP 很有可能会发生变化。如果我们的服务都是将 Pod 的 IP 地址写死,Pod 挂掉或者重启,和刚才重启的 pod 相关联的其他服务将会找不到它所关联的 Pod,为了解决这个问题,在 kubernetes 中定义了 service 资源对象,Service 定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例,service 是一组 Pod 的逻辑集合, 这一组 Pod 能够被 Service 访问到,通常是通过标签选择器实现的。
1、pod ip 经常变化,service 是 pod 的代理,我们客户端访问,只需要访问 service,就会把请求代理到 Pod
2、pod ip 在 k8s 集群之外无法访问,所以需要创建 service,这个 service 可以在 k8s 集群外访问 的。
Service 概述
service 是一个固定接入层,客户端可以通过访问 service 的 ip 和端口访问到 service 关联的后端 pod,这个 service 工作依赖于在 kubernetes 集群之上部署的一个附件,就是 kubernetes 的 dns 服务 (不同 kubernetes 版本的 dns 默认使用的也是不一样的,1.11 之前的版本使用的是 kubeDNS,较新的版本使用的是 coredns),service 的名称解析是依赖于 dns 附件的,因此在部署完 k8s 之后需要再部署 dns 附件,kubernetes 要想给客户端提供网络功能(比如分配ip),需要依赖第三方的网络插件(flannel,calico 等)。每个 K8s 节点上都有一个组件叫做 kube-proxy,kube-proxy 这个组件将始终监视着 apiserver 中有关 service 资源的变动信息,需要跟 master 之上的 apiserver 交互,随时连接到 apiserver 上获取任何一个与 service 资源相关的资源变动状态,这种是通过 kubernetes 中固有的一种请求方法 watch(监视) 来实现的,一旦有 service 资源的内容发生变动(如创建,删除),然后操作会被存在etcd里,然后会把我们的请求调度到后端特定的 pod 资源之上的规则,这个规则可能是 iptables,也可能是 ipvs,取决于 service 的实现方式(可以自己配置规则)。比如创建了一个新的svc,svc会有一个ip,这个ip的网段是创建集群的时候配置的(默认是10),不过这个ipping不通,是只存在于防火墙规则里的虚拟ip。
Service 工作原理
k8s 在创建 Service 时,会根据标签选择器 selector(lable selector)来查找 Pod,据此创建与 Service 同名的 endpoint 对象,当 Pod 地址发生变化时,endpoint 也会随之发生变化,service 接收前端 client 请求的时候,就会通过 endpoint,找到转发到哪个 Pod 进行访问的地址。(至于转发到哪个节点的 Pod,由负载均衡 kube-proxy 决定)
[root@k8smaster node]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.11.139:6443 15d
[root@k8smaster node]# kubectl get pods -n kube-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kube-apiserver-k8smaster 1/1 Running 4 15d 192.168.11.139 k8smaster
apiserver是绑定了宿主机的网络ip,apiserver这个pod,封装的k8sapiservice服务端口是443,这个service关联的pod是apiserver,ednpoints列表里编写的也是apiserverpod的ip和端口
kubernetes 集群中有三类 IP 地址
1、Node Network(节点网络):物理节点或者虚拟节点的网络,如 ens33 接口上的网路地址
[root@k8smaster node]# ip addr
ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:94:59:0f brd ff:ff:ff:ff:ff:ff
inet 192.168.11.139/24 brd 192.168.11.255 scope global noprefixroute dynamic ens3
2、Pod network(pod 网络),创建的 Pod 具有的 IP 地址
[root@k8smaster node]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
frontend-d5tr9 1/1 Running 0 23h 10.244.2.30 k8snode <none>
Node Network 和 Pod network 这两种网络地址是我们实实在在配置的,其中节点网络地址是配置在节点接口之上,而 pod 网络地址是配置在 pod 资源之上的,因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的
3、Cluster Network(集群地址,也称为 service network),这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在 service 的规则当中。
[root@xianchaomaster1 ~]# kubectl get svc [root@k8smaster node]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none>443/TCP 15d
写在最后
创作不易,如果觉得内容对你有帮助,麻烦给个三连关注支持一下我!如果有错误,请在评论区指出,我会及时更改!
目前正在更新的系列:从零开始学k8s
感谢各位的观看,文章掺杂个人理解,如有错误请联系我指出~
版权归原作者 cloud、泡泡 所有, 如有侵权,请联系我们删除。