共计 5835 个字符,预计需要花费 15 分钟才能阅读完成。
kube-proxy
service 是一组 pod 的服务抽象,相当于一组 pod 的 LB,负责将请求分发给对应的 pod。service 会为这个 LB 提供一个 IP,一般称为 cluster IP。
kube-proxy 的作用主要是负责 service 的实现,具体来说,就是实现了内部从 pod 到 service 和外部的从 node port 向 service 的访问。
举个例子,现在有 podA,podB,podC 和 serviceAB。serviceAB 是 podA,podB 的服务抽象 (service)。
那么 kube-proxy 的作用就是可以将 pod(不管是 podA,podB 或者 podC)向 serviceAB 的请求,进行转发到 service 所代表的一个具体 pod(podA 或者 podB)上。
请求的分配方法一般分配是采用轮询方法进行分配。
另外,kubernetes 还提供了一种在 node 节点上暴露一个端口,从而提供从外部访问 service 的方式。
比如我们使用这样的一个 manifest 来创建 service
apiVersion: v1
kind: Service
metadata:
labels:
name: mysql
role: service
name: mysql-service
spec:
ports:
- port: 3306
targetPort: 3306
nodePort: 30964
type: NodePort
selector:
mysql-service: "true"
他的含义是在 node 上暴露出 30964 端口。当访问 node 上的 30964 端口时,其请求会转发到 service 对应的 cluster IP 的 3306 端口,并进一步转发到 pod 的 3306 端口。
kuer-proxy 目前有 userspace 和 iptables 两种实现方式。
userspace 是在用户空间,通过 kuber-proxy 实现 LB 的代理服务。这个是 kube-proxy 的最初的版本,较为稳定,但是效率也自然不太高。
另外一种方式是 iptables 的方式。是纯采用 iptables 来实现 LB。是目前一般 kube 默认的方式。
userspace
这里具体举个例子,以 ssh-service1 为例,kube 为其分配了一个 clusterIP。分配 clusterIP 的作用还是如上文所说,是方便 pod 到 service 的数据访问。
[minion@te-yuab6awchg-0-z5nlezoa435h-kube-master-udhqnaxpu5op ~]$ kubectl get service
NAME LABELS SELECTOR IP(S) PORT(S)
kubernetes component=apiserver,provider=kubernetes <none> 10.254.0.1 443/TCP
ssh-service1 name=ssh,role=service ssh-service=true 10.254.132.107 2222/TCP
使用 describe 可以查看到详细信息。可以看到暴露出来的 NodePort 端口 30239。
[minion@te-yuab6awchg-0-z5nlezoa435h-kube-master-udhqnaxpu5op ~]$ kubectl describe service ssh-service1
Name: ssh-service1
Namespace: default
Labels: name=ssh,role=service
Selector: ssh-service=true
Type: LoadBalancer
IP: 10.254.132.107
Port: <unnamed> 2222/TCP
NodePort: <unnamed> 30239/TCP
Endpoints: <none>
Session Affinity: None
No events.
nodePort 的工作原理与 clusterIP 大致相同,是发送到 node 上指定端口的数据,通过 iptables 重定向到 kube-proxy 对应的端口上。然后由 kube-proxy 进一步把数据发送到其中的一个 pod 上。
该 node 的 ip 为 10.0.0.5
[minion@te-yuab6awchg-0-z5nlezoa435h-kube-master-udhqnaxpu5op ~]$ sudo iptables -S -t nat
...
-A KUBE-NODEPORT-CONTAINER -p tcp -m comment --comment "default/ssh-service1:" -m tcp --dport 30239 -j REDIRECT --to-ports 36463
-A KUBE-NODEPORT-HOST -p tcp -m comment --comment "default/ssh-service1:" -m tcp --dport 30239 -j DNAT --to-destination 10.0.0.5:36463
-A KUBE-PORTALS-CONTAINER -d 10.254.132.107/32 -p tcp -m comment --comment "default/ssh-service1:" -m tcp --dport 2222 -j REDIRECT --to-ports 36463
-A KUBE-PORTALS-HOST -d 10.254.132.107/32 -p tcp -m comment --comment "default/ssh-service1:" -m tcp --dport 2222 -j DNAT --to-destination 10.0.0.5:36463
可以看到访问 node 时候的 30239 端口会被转发到 node 上的 36463 端口。而且在访问 clusterIP 10.254.132.107 的 2222 端口时,也会把请求转发到本地的 36463 端口。
36463 端口实际被 kube-proxy 所监听,将流量进行导向到后端的 pod 上。
iptables
iptables 的方式则是利用了 linux 的 iptables 的 nat 转发进行实现。在本例中,创建了名为 mysql-service 的 service。
apiVersion: v1
kind: Service
metadata:
labels:
name: mysql
role: service
name: mysql-service
spec:
ports:
- port: 3306
targetPort: 3306
nodePort: 30964
type: NodePort
selector:
mysql-service: "true"
mysql-service 对应的 nodePort 暴露出来的端口为 30964,对应的 cluster IP(10.254.162.44)的端口为 3306,进一步对应于后端的 pod 的端口为 3306。
mysql-service 后端代理了两个 pod,ip 分别是 192.168.125.129 和 192.168.125.131。先来看一下 iptables。
[root@localhost ~]# iptables -S -t nat
...
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/mysql-service:" -m tcp --dport 30964 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/mysql-service:" -m tcp --dport 30964 -j KUBE-SVC-67RL4FN6JRUPOJYM
-A KUBE-SEP-ID6YWIT3F6WNZ47P -s 192.168.125.129/32 -m comment --comment "default/mysql-service:" -j KUBE-MARK-MASQ
-A KUBE-SEP-ID6YWIT3F6WNZ47P -p tcp -m comment --comment "default/mysql-service:" -m tcp -j DNAT --to-destination 192.168.125.129:3306
-A KUBE-SEP-IN2YML2VIFH5RO2T -s 192.168.125.131/32 -m comment --comment "default/mysql-service:" -j KUBE-MARK-MASQ
-A KUBE-SEP-IN2YML2VIFH5RO2T -p tcp -m comment --comment "default/mysql-service:" -m tcp -j DNAT --to-destination 192.168.125.131:3306
-A KUBE-SERVICES -d 10.254.162.44/32 -p tcp -m comment --comment "default/mysql-service: cluster IP" -m tcp --dport 3306 -j KUBE-SVC-67RL4FN6JRUPOJYM
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
-A KUBE-SVC-67RL4FN6JRUPOJYM -m comment --comment "default/mysql-service:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-ID6YWIT3F6WNZ47P
-A KUBE-SVC-67RL4FN6JRUPOJYM -m comment --comment "default/mysql-service:" -j KUBE-SEP-IN2YML2VIFH5RO2T
下面来逐条分析
���先如果是通过 node 的 30964 端口访问,则会进入到以下链
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/mysql-service:" -m tcp --dport 30964 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/mysql-service:" -m tcp --dport 30964 -j KUBE-SVC-67RL4FN6JRUPOJYM
然后进一步跳转到 KUBE-SVC-67RL4FN6JRUPOJYM 的链
-A KUBE-SVC-67RL4FN6JRUPOJYM -m comment --comment "default/mysql-service:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-ID6YWIT3F6WNZ47P
-A KUBE-SVC-67RL4FN6JRUPOJYM -m comment --comment "default/mysql-service:" -j KUBE-SEP-IN2YML2VIFH5RO2T
这里利用了 iptables 的 –probability 的特性,使连接有 50% 的概率进入到 KUBE-SEP-ID6YWIT3F6WNZ47P 链,50% 的概率进入到 KUBE-SEP-IN2YML2VIFH5RO2T 链。
KUBE-SEP-ID6YWIT3F6WNZ47P 的链的具体作用就是将请求通过 DNAT 发送到 192.168.125.129 的 3306 端口。
-A KUBE-SEP-ID6YWIT3F6WNZ47P -s 192.168.125.129/32 -m comment --comment "default/mysql-service:" -j KUBE-MARK-MASQ
-A KUBE-SEP-ID6YWIT3F6WNZ47P -p tcp -m comment --comment "default/mysql-service:" -m tcp -j DNAT --to-destination 192.168.125.129:3306
同理 KUBE-SEP-IN2YML2VIFH5RO2T 的作用是通过 DNAT 发送到 192.168.125.131 的 3306 端口。
-A KUBE-SEP-IN2YML2VIFH5RO2T -s 192.168.125.131/32 -m comment --comment "default/mysql-service:" -j KUBE-MARK-MASQ
-A KUBE-SEP-IN2YML2VIFH5RO2T -p tcp -m comment --comment "default/mysql-service:" -m tcp -j DNAT --to-destination 192.168.125.131:3306
分析完 nodePort 的工作方式,接下里说一下 clusterIP 的访问方式。
对于直接访问 cluster IP(10.254.162.44)的 3306 端口会直接跳转到 KUBE-SVC-67RL4FN6JRUPOJYM。
-A KUBE-SERVICES -d 10.254.162.44/32 -p tcp -m comment --comment "default/mysql-service: cluster IP" -m tcp --dport 3306 -j KUBE-SVC-67RL4FN6JRUPOJYM
接下来的跳转方式同上文,这里就不再赘述了。
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-10/147498.htm