- 由 虚拟的现实创建于9月 06, 2024 需要 2 分钟阅读时间
K8S pod 网络
K8S 的网络如下,POD 的网络是 Overlay 网络,意思是在现有网络上构建一个网络。就像图里的,只有 K8S 节点才能访问 10.244.0.0/16 这个网络,其他机器访问就会走自己默认路由最后路由出去而不会进到 POD 网络。
而 cni0 是 K8S 的 CNI plugin 接口规范,容器运行时并不是只有 docker ,还有很多其他的容器运行时实现,要求 pod 的容器 veth 都挂在 cbr0 下而不限制在 docker0 下,也就是 cni0 网桥。
K8S 的 POD 就是 >=1 个的容器,先创建 pause 这个 sandbox 容器,然后其他的容器 --net container:<pause_id> 附加上去。
Service 工作原理
K8S Service 就是在节点上访问 ServiceIP:ServicePort DNAT 成应用真实副本 POD_IP:POD_PORT 就像下面
而 K8S service 相关工作进程和大体工作流程如下
- kubelet:增删改 POD ,并且对 POD 做探针请求,http、tcp、exec ,如果探针失败认为 POD 不健康,上报 kube-apiserver
- kube-proxy 监听到 POD 就绪、删除、不健康后,会更新到本节点上的 iptables/ipvs 规则
查看当前节点 kube-proxy 模式可以通过下面命令查看,iptables 和 ipvs 模式各有优缺点和 bug,按需选择。
$ curl localhost:10249/proxyMode iptables
Service 虽然工作在内核态的四层(TCP/UDP/STCP)负载均衡,但是还是需要 IP 地址(因为是四层拦截,IP 不会被路由,所以 Service IP 也被称为虚拟 IP,VIP),官方一些教程默认的 CIDR 是 10.96.0.0/12,自行更改的话注意子网计算,例如 10.95.0.0/12 实际上是在 10.80.0.0/12 里,kube-apiserver 启动时候会创建 Service CIDR 第一个主机位的 IP 的 Service:
$ kubectl describe svc kubernetes Name: kubernetes Namespace: default Labels: component=apiserver provider=kubernetes Annotations: <none> Selector: <none> Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.96.0.1 IPs: 10.96.0.1 Port: https 443/TCP TargetPort: 6443/TCP Endpoints: 192.168.2.111:6443,192.168.2.112:6443,192.168.2.113:6443 Session Affinity: None Events: <none>
Service 后端是 Endpoints,而 Endpoint 的 IP 一般是 POD_IP 或者类似 kubernetes 这样的机器 IP ,以及如果你想创建类似把外部 IP 映射到内部的 service 域名,可以创建不指定 selector 的同名 service 和 endpoint。另外不一定要走 Service,很多服务有注册发现机制,把 Pod_IP:Port 注册上去,其他业务直接使用它来连接。
注意事项
- POD 访问自己的 service 会不通(特别是在一些其他人或者云上的 K8S 实例上),需要配置 cni0 为混杂模式或者 kubelet 配置 hairpinMode
- SVC 负载还得看应用层,比如 GRPC (基于 HTTP/2,只会一次 TCP 握手)会因为长连接而在 SVC 下不会均衡在每个 POD 上
- 每个节点最好安装 conntrack-tools 让有 conntrack 二进制命令,kube-proxy 会使用它做一些操作
iptables Service 模式
iptables 模式下规则为以下几类
- KUBE-SERVICES(nat.PREROUTING/nat.OUTPUT):在 PREROUTING 和 OUTPUT 链的最开始,它的规则分为两类:
- -d SVCIP ... --dport Port -j KUBE-SVC-xxx 将 SVC_IP:PORT 发放对应的
- -m addrtype --dst-type LOCAL 将本地网卡的数据包分派到 KUBE-NODEPORTS 链
- KUBE-NODEPORTS:根据 dst-port 匹配 NodePort 端口
- 数据包进入相应的 KUBE-SVC-xxx 链(externalTrafficPolicy=Cluster)
- 数据包进入相应的 KUBE-XLB-xxx 链(externalTrafficPolicy=Local)
- KUBE-SVC-xxx: 对应 service,数据包将随机进入 KUBE-SEP-xxx 链
- KUBE-XLB-xxx: 对应 service,数据包可能进入 KUBE-SEP-xxx 链或者被丢弃
- KUBE-SEP-xxx: 对应 endpoint 中的 IP 地址,数据包将 DNAT 到 Pod IP
- KUBE-FIREWALL(filter.INPUT/filter.OUTPUT):丢弃 0x8000 的包,主要用在 externalTrafficPolicy=Local 的场景
- KUBE-MARK-MASQ:标记数据包为 0x4000(需要SNAT)
- KUBE-MARK-DROP:标记数据包为 0x8000(DROP包)
- KUBE-POSTROUTING(nat.POSTROUTING):MASQUERADE 0x4000 的包
service 一般不会出问题,所以会查 iptables 规则和看就行了,上面的 SERVICE 和 MARK 、KUBE-POSTROUTING 几个实际在 ipvs 里也使用了。
- 无标签
添加评论