阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Kubernetes入门之kube-proxy实现原理

204次阅读
没有评论

共计 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

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计5835字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中