# kube-proxy

## 基本原理

`kube-proxy` 是 Service 资源的真正实现者。其作为代理，负责确保来自客户端访问指定 Service 对象的数据可以准确到达 Service 后端的某一个 Pod 中，因此同样也是负载均衡的实现者。

当 API 服务器中有 **Endpoint** 和 **Service** 资源发生变动时，会通过 watch 通知 `kube-proxy` ，它会根据 Endpoint 后端的 Pod 以及 Service 的 IP 地址以及端口生成对应的 iptables 规则（默认情况下，`kube-proxy`还有其他的工作模式）。

![发往Service的数据包会经由kube-proxy设定的iptables规则重定向至其后端的一个Pod中](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F268df89ef4857579a4e1f9d8a1baf9f9f0033235.png?generation=1588594609593506\&alt=media)

如上图，当 Pod A 向 Service 发送数据包时，经由 iptables 规则对数据包的截获，会将数据包的目的地址修改为该 Service 后端的 Endpoint 对象中的某一个 Pod 的 IP 地址和端口。

因此，Service 对象的 `ClusterIP` 是一个由 iptables 规则生成的虚拟 IP 地址和端口，所以是无法 ping 通的。

## 工作模式

目前`kube-proxy`共有三种工作模式：

* userspace 模式
* iptables 模式
* ipvs 模式

### userspace 模式

在该模式中， `kube-proxy` 是四层负载均衡设备。

`kube-proxy` 是一个真实代理服务器，其会为每一个 Service 创建监听的端口，并设置相应的 iptables 规则。

发往 Service 的 Cluster IP (由 iptables 生成的虚拟 IP 和 port) 的请求数据会被重定向至 `kube-proxy` 服务器的端口上，其会根据负载均衡算法将请求转发至某个 Pod 中。

由于 `kube-proxy` 运行在 userspace (用户态) 中，因此在数据转发时，其需要**收/发**两次操作，因此会增加两次内核态与用户态之间的数据拷贝，效率较其他模式更低；优势是，当后端的 Pod 不可用时，其可以重试其他 Pod。

![userspace 模式](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F11a7297c6e53609db1685d1733d9a978d6ea8b37.png?generation=1588594609368131\&alt=media)

### iptables 模式

在该模式中， `kube-proxy` 不承担四层代理的角色，只负责创建 iptables 规则。

在该模式中， `kube-proxy` 仅负责为 Service 后端的每个 Pod 创建对应的 iptables 转发规则，而不真正接收请求数据，请求数据将通过 iptables 规则直接重定向至 Pod 中。

该模式优点是，因为不需要用户态与内核态的数据拷贝，所以效率更高；缺点是无法提供灵活的负载均衡策略，并且当后端 Pod 不可用时，无法重试，此外当Pod数量极大时，iptables 规则数同样很大，转发效率会受损。

![iptables 模式](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F0914040b2500437addc2d4a142128e9940e1636d.png?generation=1588594609988154\&alt=media)

### ipvs 模式

该模式与 iptables 类似，在该模式中 `kube-proxy` 下放的是 ipvs 规则。

ipvs 是通过 netfilter 实现的，并且使用**哈希表**存储规则，因此在规则较多的情况下，ipvs 相对于 iptables 可以更快的查找规则，转发效率更高。此外，ipvs 支持更多的负载均衡算法。

若想使用该模式，需要在操作系统中安装 ipvs 内核模块。

![ipvs 模式](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2F0b0f4eeb4a70065ee28260e5e3f5fcac1798f038.png?generation=1588594610021906\&alt=media)
