xiaohanliang
Docker
Docker
  • hi
  • STORAGE DRIVER
    • 1. 什么叫联合挂载
    • 2. 镜像ID是从哪来的
    • 3. 如何组装出一个镜像
    • 4. 为什么有这么多fs@aufs
    • 5. 为什么有这么多fs@overlay
    • 6. 为什么有这么多fs@dm
    • 7. 正确安装devicemapper
  • EXEC DRIVER
    • 1. 资源限制-cgroup
    • 2. 制造小型监狱
    • 3. 切换根目录是什么概念
    • 4. 标准极简容器runC
    • 5. 尝试安装runc工具
  • KUBERNETES NETWORK
    • 0. [WIP]我想串联容器网络的故事
    • 1. 容器网络是什么样的网络
    • 2. cnm认为应该怎样让容器组网
    • 3. 为什么会有一大堆cni插件
    • 4. 为什么要设计出pod
    • 5. 怎样形成一个服务
    • 6. Service就是iptables规则
    • 7. IPVS也能实现Service
    • 8. 从集群外访问服务-nodeport
    • 9. 从集群外访问服务-ingress
    • 10. 想要把域名变成IP
    • 11. DNS是怎么实现的
    • 12. 最常见的方案@flannel
    • 13. 使用tun设备封包@flannel
    • 14. 使用vxlan设备封包@flannel
    • 15. 可不可以不封包@flannel
Powered by GitBook
On this page
  • introduction
  • userspace模式
  • iptables模式
  • ipvs模式

Was this helpful?

  1. KUBERNETES NETWORK

6. Service就是iptables规则

introduction

上一节里我们都只简单讲讲有什么组件, 这些组件大概都是干什么的, 但感觉不稳, 里面的流量走向感觉没理清楚, 感觉还是不清爽. 这一节里就想要把这些事情全都讲清楚了. 在k8s的service工作原理里, 主要涉及的组件包含有:

  • service controller(sc)

  • enpoint controller(ec): 当用户创建service以及对应的后端pod的时候, ec负责监控pod的状态变化, pod状态为就绪的时候就创建一个endpoint并指向这组pod

  • kube-proxy(proxy): 这家伙运行在每个节点上

    • 监控service以及endpoints的状态更新 → "监控"

    • 并调用proxy下的load-balancer模块在宿主机上刷新路由转发规则 → "刷新路由表"

这一节我们主要讲讲这个刷新路由表是怎么回事, 因为这事关流量能不能被正确的指引到后端pod上, 目前可能的实现方式包含: iptables / ipvs / userspace 三种

userspace模式

这种模式其实已经很少使用了, 因为按照他的做法, 流量的转发发生在 用户态 , 故而效率不仅不高而且还容易产生丢包, 时髦的玩法下转发都是在内核态里, 但相对应的对内核版本也有一定要求, 想象一下, 仅仅因为你版本不够高, 连k8s的service都用不了了这可还行? 因此这种模式倒也一直存在着

在userspace的玩法中, 访问服务的请求先是到达了从节点, 然后进入内核iptables, 然后又回到用户态下, 由proxy完成后端Pod的选择, 并建立一条通往pod的连接. 这是一套比较古老(也可以认为是经典) 的玩法, 假设我们现在有一个service(按照userspace模式运行中)

  • service 为cluser ip + port → 10.254.132.107:2222

  • NodePort 为宿主机ip + port → 10.0.0.5:30239

# 检查一下iptables现在是怎么配置的
$ iptables -S -t nat

# 想要访问宿主机30239: 这种是容器访问宿主机的流量 -> 定向到36463
-A KUBE-NODEPORT-CONTAINER --dport 30239 -j REDIRECT --to-ports 36463

# 想要访问宿主机30239: 这种是宿主机上进程想要访问的流量 -> DNAT 到 36463
-A KUBE-NODEPORT-HOST --dport 30239 -j DNAT --to-destination 10.0.0.5:36463

# 想要前往cluster ip:2222 这种是集群内pod通过cluster ip找过来的流量 -> 定向到 36463 
-A KUBE-PORTALS-CONTAINER -d 10.254.132.107 --dport 2222 -j REDIRECT --to-ports 36463

# 想要前往cluster ip:2222 这种是宿主机进程上进程通过cluster ip找过来的流量 -> DNAT 到 36463
-A KUBE-PORTALS-HOST -d 10.254.132.107 --dport 2222 -j DNAT --to-destination 10.0.0.5:36463

从上面的内容有两点很有意思, 任何一个流量到达宿主机以后会先经过iptables判断接下来往哪儿走,

  • 我们看看这个流量是从哪里出发的, 如果是从pod出发的, 就 REDIRECT, 如果是宿主机出发的, 就 DNAT, 这两种做法很有意思, 首先我不知道你是怎么判断出 source 的, 还有就是为什么一个 redirect 另一个 dnat

  • 接下来我们发现无论你是谁, 最后都去 36463, 这个端口跟service无关, 纯kube-proxy自己干的事, 自己监听这个端口, 然后把流量转发到后端Pod上

    • 我们对着iptables找规则 → 在内核态

    • 找到规则转发给proxy由proxy负责转发 → 又回去用户态里了

iptables模式

总结: 那么相比于userspace, 我们现在直接在内核空间里(iptables直接搞定)就能转发, 不需要去用户空间里要求kube-proxy来帮你转发了, 效率确实提升了不少

ipvs模式

IPVS是LVS的一个组件, 负责负载均衡的组件, 也是基于netfilter实现的, 为什么需要它呢? 明明上面才把iptable模式吹的很牛逼呢~ 你想想, Linux中的iptable本身是拿来干什么用的, 人家是拿来搭防火墙的, 写几条就行了, 你呢? 把它当路由器用, 几百条规则咔咔往上整, 而且iptable的规则底层实现是链表啊是链表, 架得住你这么遍历? 仔细想想这么玩还是挺搞笑的.

Previous5. 怎样形成一个服务Next7. IPVS也能实现Service

Last updated 4 years ago

Was this helpful?