一、Service
1.1 Service简介
Kubernetes Service定义了这样一种抽象:逻辑上的一组 Pod,一种能够访问它们的策略 —— 一般被称为微服务。这一组 Pod 可以被 Service 访问到,一般是经过 selector实现的。
举例:考虑一个图片处理 backend,它运行了3个副本。这些副本是可互换的 —— frontend 不需要关心它们调用了哪一个 backend 副本。 然而组成这一组 backend 程序的 Pod 实际上可能会发生变化,frontend 客户端不必知道,并且也不需要跟踪这一组 backend 的状态。Service 定义的抽象可以解耦这种关联。
Service能够提供负载均衡的能力,可是使用上存在以下限制:
- 只能提供4层负载均衡能力,而没有7层功能。有时咱们可能须要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的、
如web访问的service服务示例图:
1.2 VIP和Service代理
在 Kubernetes 集群中,每一个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。后端
从Kubernetes v1.0开始,已经可使用 userspace代理模式。Kubernetes v1.1添加了 iptables 代理模式,在 Kubernetes v1.2 中kube-proxy 的 iptables 模式成为默认设置。Kubernetes v1.8添加了 ipvs 代理模式。
1.3 不使用 DNS 轮询的原因
缘由以下:
-
DNS 实现的历史由来已久,它不遵照记录 TTL,而且在名称查找到结果后会对其进行缓存。
-
有些应用程序仅执行一次 DNS 查找,并没有限期地缓存结果。
-
即便应用和库进行了适当的从新解析,DNS 记录上的 TTL 值低或为零也可能会给 DNS 带来高负载,从而使管理变得困难。
由于有缓存,所以不合适。
1.4 iptables 代理模式
这种模式,kube-proxy 会监视 Kubernetes 控制节点对 Service 对象和 Endpoints 对象的添加和移除。 对每一个 Service,它会配置 iptables 规则,从而捕获到达该 Service 的 clusterIP 和端口的请求,进而将请求重定向到 Service 的一组 backend 中的某个上面。对于每一个 Endpoints 对象,它也会配置 iptables 规则,这个规则会选择一个 backend 组合。
默认的策略是,kube-proxy 在 iptables 模式下随机选择一个 backend。
使用 iptables 处理流量具备较低的系统开销,由于流量由 Linux netfilter 处理,而无需在用户空间和内核空间之间切换。 这种方法也可能更可靠。
若是 kube-proxy 在 iptables模式下运行,而且所选的第一个 Pod 没有响应,则链接失败。 这与userspace模式不一样:在这种状况下,kube-proxy 将检测到与第一个 Pod 的链接已失败,并会自动使用其余后端 Pod 重试。
咱们可使用 Pod readiness 探测器 验证后端 Pod 是否能够正常工做,以便 iptables 模式下的 kube-proxy 仅看到测试正常的后端。这样作意味着能够避免将流量经过 kube-proxy 发送到已知已失败的Pod。
1.5 IPVS 代理模式
在 ipvs 模式下,kube-proxy监视Kubernetes服务(Service)和端点(Endpoints),调用 netlink 接口相应地建立 IPVS 规则, 并按期将 IPVS 规则与 Kubernetes服务(Service)和端点(Endpoints)同步。该控制循环可确保 IPVS 状态与所需状态匹配。访问服务(Service)时,IPVS 将流量定向到后端Pod之一。
IPVS代理模式基于相似于 iptables 模式的 netfilter 挂钩函数,可是使用哈希表做为基础数据结构,而且在内核空间中工做。 这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通讯的延迟要短,而且在同步代理规则时具备更好的性能。与其余代理模式相比,IPVS 模式还支持更高的网络流量吞吐量。
IPVS提供了更多选项来平衡后端Pod的流量。分别是:
- rr: round-robin
- lc: least connection (smallest number of open connections)
- dh: destination hashing
- sh: source hashing
- sed: shortest expected delay
- nq: never queue
注意: 要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 以前使 IPVS Linux 在节点上可用。 当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 若是未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
二、Service存在的意义
service引入主要是解决Pod的动态变化,提供统一访问入口:
- 防止Pod失联,准备找到提供同一个服务的Pod(服务发现)
- 定义一组Pod的访问策略(负载均衡)
Pod与Service的关系:
- Service通过标签关联一组Pod
- Service使用iptables或者ipvs为一组Pod提供负载均衡能力
三、Service定义与创建
创建service:
- kybectl apply -f service.yaml
查看service:
- kubectl get service
实例:
[root@master ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gaofan1225/httpd v0.2 f61bbd041ba4 12 days ago 89.2MB
[root@master ~]# cat test.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd
namespace: default
spec:
selector:
matchLabels:
name: httpd
template:
metadata:
labels:
name: httpd
spec:
containers:
- name: httpd
image: gaofan1225/httpd:v0.2
imagePullPolicy: IfNotPresent
// 应用
[root@master ~]# kubectl apply -f test.yaml
deployment.apps/httpd created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
httpd-77bfff888c-4bfzv 1/1 Running 0 8s
// 暴露端口,本机访问映射端口80,容器内访问映射端口80
[root@master ~]# kubectl expose deployment httpd --port 80 --target-port 80
service/httpd exposed
// svc创建成功
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd ClusterIP 10.105.163.84 <none> 80/TCP 5s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d23h
// 测试访问
[root@master ~]# curl 10.105.163.84:80
<html><body><h1>It works!</h1></body></html>
四、Service服务类型
4.1 ClusterIP:集群内部使用
默认类型,自动分配一个仅Cluster内部能够访问的虚拟IP
实例:
[root@master ~]# cat test3.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mydeploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: amu2
release: v1
template:
metadata:
labels:
app: amu2
release: v1
spec:
containers:
- name: amu2
image: gaofan1225/httpd:v0.2
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: mysvc
namespace: default
spec:
type: ClusterIP // 指定ClusterIP类型
selector:
app: amu2
release: v1
ports:
- name: httpd
port: 80
targetPort: 80
[root@master ~]# kubectl apply -f test3.yaml
deployment.apps/mydeploy created
service/mysvc created
// 查看pod、svc
[root@master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/httpd-77bfff888c-4bfzv 1/1 Running 1 (21h ago)