• k8s中的网络通信总结


    一、容器与容器之间的通信

    同一个pod中的容器,共用同一个网络命名空间,直接使用localhost或127.0.0.1加上端口访问就好了。可以看到这两个容器的ip地址,路由表,以及暴露的端口号等都是一样的,因为他们使用的是同一个网络命名空间,同一个网络栈。

    【注意】:他们只是共用网络命名空间(network namespace),但是进程命名空间(PID namespace)、用户命名空间(user namespace)等其他的命名空间是相互隔离的。

    二、POD与POD之间的通信

    1、同一个Node上的pod之间的通信

     每个pod都有唯一一个ip(属于docker0网桥上的网段),每个pod的网络基础设施容器都是通过veth设备对直接连在docker0网桥上的:

    本机docker0网桥的地址的数据包都会通过容器内的eth0(veth设备)直接转给Kernel,路由的范围是link(与本设备直接连接),因为veth设备都是成对存在的,另一端连在docker0网桥上,所以会由Kernel直接转发给docker0网桥上的另一个veth设备。

    宿主机将数据包通过docker0发给Kernel,最终docker0网桥会将数据包转发给目的pod。

    2、不同Node上的pod之间的通信

    要支持不同Node节点上的pod通信需要满足的要求:

    1)整个kubernetes集群中对每个POD分配一个唯一的IP:在部署Kubernetes时,对每个Node节点的docker0网桥的网段重新划分,用户设定一个大的网段(eg:10.20.0.0/16),存在etcd中,每个节点的flanneld会去etcd中查找这个值,然后,flanneld随机生成一个属于大网段的,且不冲突的子网(eg: 10.20.37.0/24; 10.20.92.0/24; 10.20.0.53/24)并将该值写回etcd中,这样就保证了每个pod的IP都会在10.20.0.0/16这个网段内;

    2)Node节点之间需要架设一个overlay网络(一般通过flannel实现),保证pod可以互相访问。

    三、Pod与Service之间的通信

    为了支持水平扩展和高可用,实际使用中并不会直接使用POD的IP来访问POD中的服务,而是定义service来访问一组POD中的服务。service是对一组POD的抽象,会根据访问策略(负载均衡)来访问这组POD。

    Kubernetes会在创建service时随机分配一个ClusterIP,这是一个虚IP(VIP),不能与docker0网桥的网段冲突,比如:10.10.0.0/16这个网段(在 kube-apiserver的--service-cluster-ip-range=10.10.0.0/16配置项中指定)。

    访问POD中服务是只需要访问这个VIP就好了,而service会将请求经过负载均衡之后转发到后端POD中,这些工作都是运行在每个Node节点的kube-proxy进程管理的,它的核心功能是:将对某个Service的访问经过负载均衡(Round Robin算法)之后转发到某一个后端POD:

    1、Service的类型

    1、ClusterIP:默认类型,自动分配一个仅cluster内部可以访问的虚拟IP;
    2、NodePort:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过<NodeIP>:NodePort来访问改服务;
    3、LoadBalancer:在NodePort的基础上,借助cloud provider创建一个外部的负载均衡器,并将请求转发到<NodeIP>:NodePort

    无论是ClusterIP+TargetPort的方式,还是NodeIP+NodePort的方式访问服务,都会被节点的iptables规则重定向到kube-proxy监听Service的服务代理端口,kube-proxy接受到Service请求之后,会使用Round-Robin负载均衡算法按照Service维护的Endpoint对象中选择一个endpoint(其实就是POD)。

    2、ClusterIP类型的service需要的iptables规则

    任何数据包进入宿主机后,首先进入PREROUTING链:

    -A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
    -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER

    kube-proxy进程在启动时或者监听到Service和Endpoint发生变化之后,会为每个endpoint修改本机Iptables的NAT表中的4条规则链:

    -A KUBE-SEP-6XCC4VJACKOMSYVV -s 10.20.92.11/32 -m comment --comment "hyjx--hyjx-group3/mysql-demo:mysqld-demo" -j KUBE-MARK-MASQ
    -A KUBE-SEP-6XCC4VJACKOMSYVV -p tcp -m comment --comment "hyjx--hyjx-group3/mysql-demo:mysqld-demo" -m tcp -j DNAT --to-destination 10.20.92.11:3306
    -A KUBE-SERVICES -d 10.10.147.26/32 -p tcp -m comment --comment "hyjx--hyjx-group3/mysql-demo:mysqld-demo cluster IP" -m tcp --dport 13306 -j KUBE-SVC-DM5EMDBLORDRGWLL
    -A KUBE-SVC-DM5EMDBLORDRGWLL -m comment --comment "hyjx--hyjx-group3/mysql-demo:mysqld-demo" -j KUBE-SEP-6XCC4VJACKOMSYVV

    3、NodePort类型的Service需要的iptables规则

    -A KUBE-NODEPORTS -p tcp -m comment --comment "hyjx--hyjx-group3/mysql-demo2:mysqld-demo2" -m tcp --dport 30016 -j KUBE-MARK-MASQ
    -A KUBE-NODEPORTS -p tcp -m comment --comment "hyjx--hyjx-group3/mysql-demo2:mysqld-demo2" -m tcp --dport 30016 -j KUBE-SVC-NVNGTMQMPFTQA6YS
    -A KUBE-SEP-7MWHP37XXE3W6QI4 -s 10.20.92.11/32 -m comment --comment "hyjx--hyjx-group3/mysql-demo2:mysqld-demo2" -j KUBE-MARK-MASQ
    -A KUBE-SEP-7MWHP37XXE3W6QI4 -p tcp -m comment --comment "hyjx--hyjx-group3/mysql-demo2:mysqld-demo2" -m tcp -j DNAT --to-destination 10.20.92.11:3306
    -A KUBE-SERVICES -d 10.10.95.1/32 -p tcp -m comment --comment "hyjx--hyjx-group3/mysql-demo2:mysqld-demo2 cluster IP" -m tcp --dport 23306 -j KUBE-SVC-NVNGTMQMPFTQA6YS
    -A KUBE-SVC-NVNGTMQMPFTQA6YS -m comment --comment "hyjx--hyjx-group3/mysql-demo2:mysqld-demo2" -j KUBE-SEP-7MWHP37XXE3W6QI4

    NodePort类型的Service比ClusterIP类型就多了两条规则KUBE-NODEPORTS,剩下的4条规则是用来处理使用ClusterIP的方式访问服务的请求,因为NodePort类型的服务,同样可以使用ClusterIP的方式访问。

    1)、第一条规则,实现了IP Masquerade功能 ;

    2)、第二条规则,如果是使用NodeIP+NodePort的方式,目的端口为30016,处理方法和直接使用ClusterIP类型的服务访问一样。

    4、更近一步,直接使用服务的名字访问

    使用服务的VIP的方式还是不太友好,因为只有创建好Service之后,系统才会随机分配一个VIP,运行在容器中的应用无法提前知道这个VIP,动态修改镜像是不现实的。最终的解决方案是直接使用服务的名称来访问服务。而,服务的名称到服务的VIP的解析是由kube-dns来完成的。

    kubelet在启动容器的时候,会修改容器的/etc/resolv.conf,设置容器的DNS服务器为kube-dns(k8s-master节点IP),每个服务都有唯一一个域名。

    在容器中无法ping通服务mysql-demo的VIP,但是使用服务的名称,kube-dns可以正确地返回服务对应的VIP

    四、k8s集群外部到k8s集群内部的访问

    设置service的类型为NodePort,并为服务指定一个不冲突的端口(30000-32767)就行了,访问时直接使用任意一个Node节点的IP加上这个NodePort

  • 相关阅读:
    在typescript中interface和type的区别和相同点
    微信小程序常用的方法
    使用vite创建vue3项目
    JavaCV-流媒体开发系列文章(索引)
    Java 8 日期时间 API
    JavaFX桌面应用-JavaFX应用打包exe及构建安装包
    JavaCV 视频滤镜(LOGO、滚动字幕、画中画、NxN宫格)
    JavaCV 采集摄像头和麦克风数据推流直播
    JavaCV 采集摄麦克风音频数据
    JavaCV 采集摄像头及桌面视频数据
  • 原文地址:https://www.cnblogs.com/peteremperor/p/14026840.html
Copyright © 2020-2023  润新知