SVC 通过 Label Selector 标签选择的方式,匹配一组 Pod,对外访问服务。每一个 SVC可以理解成为一个微服务。
service 能够提供负载均衡的能力,但是在使用上有以下限制:
Clusterip:默认类型,自动分配一个仅 Cluster 内部可以访问的 虚拟IP,一般用作集群内部负载均衡。
NodePort(service向外暴露):在ClusterIP 基础上为 Service 在每台机器上绑定一个映射端口,外网客户端可以通过 NodeIP,Nodeport访问。
LoadBalancer(service向外暴露):在 NodePort 基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到 NodeIP 和 NodePort
ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,只有1.7之后版本的 kube-dns支持。
在kubernetes集群中,每个 Node 运行一个 Kube-porxy 进程。kube-proxy负责为 service 实现了一种 VIP (虚拟IP) 的形式,而不是 ExternaName 的形式。
1.0版本,代理完全在 userspace
1.1版本,新增 iptables 代理,但并不是默认的运行模式
1.2版本,默认采用 iptables 代理
1.4版本,默认采用 ipvs 代理
service 是 “4层(TCP/UDP over IP)概念”,在1.1版本 新增了 Ingress API(beat 版),用来表示“7层代理”。
所有的请求,代理全部由 iptables 来完成,不再需要 kube-proxy 充当代理角色。
提高了 稳定性和访问效率,压力减少
ipvs (IP Virtual Server) 实现了传输层负载均衡,也就是我们常说的4层LAN
交换,作为 Linux 内核的一部分。ipvs
运行在主机上,在真实服务器集群前充当负载均衡器。ipvs
可以将基于TCP
和UDP
的服务请求转发到真实服务器上,并使真实服务器的服务在单个 IP 地址上显示为虚拟服务。
我们知道kube-proxy
支持 iptables 和 ipvs 两种模式, 在kubernetes
v1.8 中引入了 ipvs 模式,在 v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。iptables 模式在 v1.1 中就添加支持了,从 v1.2 版本开始 iptables 就是 kube-proxy 默认的操作模式,ipvs 和 iptables 都是基于netfilter
的,那么 ipvs 模式和 iptables 模式之间有哪些差异呢?
ipvs为负载均衡提供算法:
注意:ipvs 模式假定在运行 kube-proxy 之前在节点上都已经安装了 IPVS 内核模块。当 kube-proxy 以 ipvs 代理模式启动时,kube-proxy 将验证节点上是否安装了 IPVS 模块,如果未安装,则 kube-proxy 将回退到 iptables 代理模式
client Pod 访问 Server Pod
clusterIP 主要在每个 node 节点使用 ipvs,将发向 Cluster IP对应端口的数据,转发到 Service-ipvs,ipvs通过调度算法将请求进行负载均衡,发送至后端 Pod节点。
1、先创建 Deployment 控制器 3个Nginx 应用
apiVersion: apps/v1
kind: Deployment #创建Deployment控制器
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3 #创建三个副本
selector:
matchLabels:
app: myapp #副本标签
release: stabel #副本标签
template:
metadata:
labels:
app: myapp #副本标签
release: stabel #副本标签
env: test
spec:
containers:
- name: myapp
image: nginx:1.9.1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
kubectl apply -f nginx.yaml --record
kubectl get pod -o wide
2、为这三个 Nginx 应用创建 Service 暴露IP、Port
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: ClusterIP #Cluster IP
selector: #选择器
app: myapp #service匹配标签
release: stabel #service匹配标签
ports:
- name: http #匹配Deployment.spec.ports名称
port: 80 #暴露端口
targetPort: 80 #后端真是服务器端口
kubectl apply -f myapp-service.yaml
kubectl describe service myapp 查看集群虚拟IP 和 后端 Pod地址
访问这个 10.98.227.26 Cluster IP地址,轮询调度三个 nginx 副本的页面
Headless Service 属于 Cluster IP的一种,Pod 通过 service_name 方式直接解析到后端 Pod IP。
有时不需要或者不想要负载均衡的 Service,遇到这种情况,可以通过指定 Cluster IP的值为 None,来创建 Headless Service。这类Service 并不会分配 ClusterIP,kube-proxy 不会处理他们,而且平台也不会为他们进行负载均衡和路由。
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
labels:
app: myapp
spec:
selector:
app: myapp
clusterIP: "None"
ports:
- protocol: TCP
port: 80
targetPort: 80
1、查看 headless service详细信息
kubectl describe service myapp-headless
2、解析 该 headless 域名
nslookup myapp-headless.default.svc.cluster.local 10.244.0.2
10.244.0.2 是集群的DNS解析地址
nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由kube-proxy 进一步给到对应的 Pod。
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
namespace: default
spec:
type: NodePort #NodePort
selector: #选择器
app: myapp #service匹配标签
release: stabel #service匹配标签
ports:
- name: http #匹配Deployment.spec.ports名称
port: 80 #暴露端口
targetPort: 80 #后端真是服务器端口
kubectl get svc
查看 NodePort IP地址
kubectl describe svc myapp-nodeport
查看详细 svc 后端 Pod 节点IP地址
loadBalancer 和 nodePort 其实是同一种方法。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用 cloud provider 去创建 LB 来向节点导流。
每一个 Node 节点同样会暴露 一个 NodePort,只不过在外网存在一个 LB 供应商的调度层。
客户端访问的是 LB 供应商的 IP & PORT ,由 LB 提供负载均衡。
对外部服务设定别名,通过别名直接访问
这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如自定义域名:hub.shmguigu.com) 引入外部服务到内部流量。
ExternalName service 是 Service 的特例,它没有selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。
Kind: Service
apiVersion: v1
metadata:
name: my-service-1
namespace: default
spec:
type: ExternalName
externalName: hub.shmguigu.com
kubectl get svc
my-service-1 ExternalName