Service 是Kubernetes 最核心的概念、通过创建 Service 可以为一组具有相同功能的容器应用提供一个统一的入口地址。并且将请求进行负载分发到后端的各个容器应用上。
Ingress 资源
TCP 负载均衡器
无论是 iptables 还是 ipvs 模型的Service 资源都配置Linux 内核中的 Netfilter 之上进行四层调度。是一种类型更为通用的调度器。支持调度 HTTP、MySQL 等应用层服务。
HTTP(S) 负载均衡器
HTTP(s) 负载均衡器是应用层负载均衡机制的一种。支持根据环境做成更好的调度决策。与传输层调度器相比。它提供可自定义URL映射和 TLS 卸载功能。
Service
Service 资源基于标签选择器将一组 Pod 定义成一个逻辑组合。并通过自己的IP 地址和端口调度代理请求至组内的Pod 对象之上。
- Service 对象的IP地址也称为 Cluster IP, 位于kubernetes 集群配置指定专用IP地址范围之内。而且是一种虚拟IP 地址。它在创建Service 对象创建保持不变。并且能够被同一集群中的Pod 资源所访问。端口用于接收客户端请求并将转发至其后端的Pod 中应用的应用的响应端口。因此这种代理称为
端口代理
。或四层代理。工作于TCP/IP 协议的传输层。 - service 资源会通过 API Server 持续监视(watch)标签选择器匹配到后端的Pod 对象,并实时跟踪各个对象。例如IP 变动、对象增加,Service 并不直接连接Pod 对象。他们之间通过中间层
Endpoints
对象。它是一个IP地址端口组成的列表。这些IP 地址和端口来自 Service 的标签选择器匹配到 Server 的后端端点Endpoints
虚拟IP 和服务代理
Service IP 事实上是用于生成 iptables或ipvs 规则使用IP地址。它仅用于实现k8s 集群网络的内部通信。并且仅能够将规则中定义的转发服务的请求作为模板地址的响应。这也是它被称为
虚拟IP原因
- kube-proxy 将请求代理至相应端点方式:userspace(用户空间)、iptables、ipvs
- userspace:是指Linux 操作系统的用户空间。kube-proxy 负责跟踪API-Server 上的Server 和 Endpoints 对象的变动。并据此调整server 资源定义。对于每个 Service 对象。他会随机打开一个端口。负责监听。任何到达此代理端口连接请求都将被代理至当前Service 资源后端的各 Pod 对象上。至于挑中那个Pod 对象取决于当前Service 资源的调度方式,默认是轮询。
kubernetes 1.1 之前 uperspace 默认代理模式
- iptables 代理模型:kube-proxy 负责跟踪API Server 上Service 和 Enpoints 对象的变动。并据此作出Service 资源定义的变动。同时对于每个Service 它都会创建iptables 规则直接捕获到达 ClusterIP 和 Port 的流量。并将其重定向到当前Service 的后端。
- ipvs 代理模型:kube-proxy 跟踪 API Server 上Service 和 Endpoints 对象的变动。据此来调用netlink 接口创建 ipvs 规则。并确保与API Serverr 中的变动保持同步。它月 iptables 规则的不同之处仅在其请求流量的调度功能由 ipvs 实现。其余的功能由 iptables 完成。
- userspace:是指Linux 操作系统的用户空间。kube-proxy 负责跟踪API-Server 上的Server 和 Endpoints 对象的变动。并据此调整server 资源定义。对于每个 Service 对象。他会随机打开一个端口。负责监听。任何到达此代理端口连接请求都将被代理至当前Service 资源后端的各 Pod 对象上。至于挑中那个Pod 对象取决于当前Service 资源的调度方式,默认是轮询。
服务发现(Service Discovery)
存在着复杂的依赖关系且彼此之间通常需要进行非常频繁的交互和通信的群体。建立通信之前。服务于服务之间如何获取彼此的地址。但Pod 客户端中的应用得知某个特定 Service 资源的iP和端口。这个时候就需要引入服务发现的机制。
服务暴露
- Service 类型
- ClusterIP: 通过集群内部IP地址暴露服务。此地址仅在集群内部可达。而无法被集群外部的客户端访问。默认Service 类型
- NodePort 建立在 ClusterIP 类型之上。其在每个节点的IP地址的某静态端口暴露服务。因此它依然会为Service 分配集群IP地址。并将此作为NodePort 的路由目标。简单来说。NodePort 类型就是工作节点的IP 地址上选择一个端口用于集群外部的用户请求至目标Service 的CluterIP.
- LoadBalancer 建立NodePort 之上。通过 cloud provider 提供负载均衡将服务暴露到集群外部。因此LoadBalancer 一样具有 NodePort 和 ClusterIP。简单来说。一个LoaderBalancer 类型Service 会指向关联至 k8s 集群外部切实存在的某个负载均衡设备。
- ExteralName 通过将 Service 映射至由 externalName 字段的内容指定的主机名来暴露服务。主机名需要被DNS 服务解析至CNAME 类型的记录。
- Headless 类型的 Service 资源,Session 对象隐藏各Pod 资源。并负责将客户端的请求流量调度至该组Pod 对象之上。
基本用法
- 对于容器应用最简单的方法就是通过TCP/IP 机制监听IP和端口号来实现,每个容器通过 containerPort 设置提供服务的端口。
- 直接通过Pod 的IP 地址和端口号可以访问容器应用。但是Pod 的IP地址是不可靠的。例如当Pod 所在Node 发生故障时,Pod 将被Kubernetes 重新调度到另外一台Node 进行启动。Pod 的IP 地址发生变化。如果容器本省就是分布式部署的。
-
Service 和 Pod 关联
使用相同 selector:app:xxx - kubernetes 提供的两种负载策略
-
RoundRobin(默认)
轮询模式。轮询将请求转发到后端的各个 Pod 上。 -
SessionAffinity(粘性会话或会话粘性)
基于客户端IP地址进行会话保持模式。第一次将某个客户端发起的请求转发到后端Pod.之后从相同的客户端发起请求都转发后端相同的Pod。(service.spec.sessionAffinity 设置 ClientIP 启用 SessinoAffinity 策略)- session affinity 效果仅会在一定时间期限内生效。默认10800 秒。超出此时长之后。客户端的再次访问会被调度算法重新调度。
- kubectl get svc myapp-svc // 获取相关的信息输出了解资源的状态
- k8s 通过
Headless Service
实现这种功能。不给Service 设置 ClusterIP.仅通过Label Serctor 将后端Pod 列表返回给调用客户端
-
kind: Service
spec:
ports:
- port: 80
targetPort: 8080 #将Service 的80端口映射到 Pod 的8080
clusterIP: None
selector:
app: nginx
ports:
- containerPort: 8080
hostPort: 8081 # 通过设置容器级别 hostPort,将容器应用端口映射到物理机上
spec:
hostNetwork: true
ports:
- containerPort: 8080
# 设置hostNetwork=true、该Pod 中所有容器的端口都将直接映射到物理机上。如果指定 hostPort.则 hostPort 必须等于 containerPort 的值。
spec: # 将Service 的端口映射到物理机
type: NodePort #设置NodePort 映射到物理机器。这是Service的类型 NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 8081
-
DNS 服务
(k8s 提供的虚拟DNS 服务名为 skydns)- etcd: DNS 存储
- kube2sky: 将 k8s master中的 Service 服务注册到 etcd
- skyDNS: 提供DNS 域名解析服务
- healthz: 提供对 skydns 服务的健康检查功能。