K8S 容器之间通讯方式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K8S 容器之间通讯方式相关的知识,希望对你有一定的参考价值。
参考技术A 首先k8s里面容器是存在于pod里面的,所以容器之间通讯,一般分为三种类型:1. pod内部容器之间
2. pod 与 pod 容器之间
3. pod 访问service服务
这种情况下容器通讯比较简单,因为k8s pod内部容器是共享网络空间的,所以容器直接可以使用localhost访问其他容器。
k8s在启动容器的时候会先启动一个pause容器,这个容器就是实现这个功能的。
这种类型又可以分为两种情况:
1. 两个pod在一台主机上面
2. 两个pod分布在不同主机之上
针对第一种情况,就比较简单了,就是docker默认的docker网桥互连容器。
第二种情况需要更为复杂的网络模型了,k8s官方推荐的是使用flannel组建一个大二层扁平网络,pod的ip分配由flannel统一分配,通讯过程也是走flannel的网桥。
docker --daemon --bip=172.17.18.1/24
注意其中的“--bip=172.17.18.1/24”这个参数,它限制了所在节点容器获得的IP范围。
每个node上面都会创建一个flannel0虚拟网卡,用于跨node之间通讯。所以容器直接可以直接使用pod id进行通讯。
跨节点通讯时,发送端数据会从docker0路由到flannel0虚拟网卡,接收端数据会从flannel0路由到docker0,这是因为flannel会添加一个路由
发送端:
route -n
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel0
172.17.13.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
接收端:
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel0
172.17.12.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
例如现在有一个数据包要从IP为172.17.13.2的容器发到IP为172.17.12.2的容器。根据数据发送节点的路由表,它只与172.17.0.0/16匹配这条记录匹配,因此数据从docker0出来以后就被投递到了flannel0。同理在目标节点,由于投递的地址是一个容器,因此目的地址一定会落在docker0对于的172.17.12.0/24这个记录上,自然的被投递到了docker0网卡。
flannel的原理是将网络包封装在udp里面,所以发送端和接收端需要装包和解包,对性能有一定的影响。
k8s也支持其他的网络模型,比较有名的还有calico,不过我并没有使用过。
这里涉及到k8s里面一个重要的概念service。它是一个服务的抽象,通过label(k8s会根据service和pod直接的关系创建endpoint,可以通过kubectl get ep查看)关联到后端的pod容器。
Service分配的ip叫cluster ip是一个虚拟ip(相对固定,除非删除service),这个ip只能在k8s集群内部使用,如果service需要对外提供,只能使用Nodeport方式映射到主机上,使用主机的ip和端口对外提供服务。(另外还可以使用LoadBalance方式,但这种方式是在gce这样的云环境里面使用的 )。
节点上面有个kube-proxy进程,这个进程从master apiserver获取信息,感知service和endpoint的创建,然后做两个事:
1. 为每个service 在集群中每个节点上面创建一个随机端口,任何该端口上面的连接会代理到相应的pod
2. 集群中每个节点安装iptables规则,用于clusterip + port路由到上一步定义的随机端口上面,所以集群中每个node上面都有service的转发规则:
KUBE-PORTALS-CONTAINER 从容器中通过service cluster ip和端口访问service的请求
KUBE-PORTALS-HOST 从主机中通过service cluster ip和端口访问service的请求
KUBE-NODEPORT-CONTAINER 从容器中通过service nodeport端口访问service的请求
KUBE-NODEPORT-HOST 从主机中通过service nodeport端口访问service的请求。
见下面测试环境的内容:
-A KUBE-NODEPORT-CONTAINER -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 50171 -j REDIRECT --to-ports 52244
-A KUBE-NODEPORT-HOST -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 50171 -j DNAT --to-destination 10.45.25.227:52244
-A KUBE-PORTALS-CONTAINER -d 10.254.120.169/32 -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 1521 -j REDIRECT --to-ports 52244
-A KUBE-PORTALS-HOST -d 10.254.120.169/32 -p tcp -m comment --comment "smart/ccdb:port1521" -m tcp --dport 1521 -j DNAT --to-destination 10.45.25.227:52244
52244就是kube-proxy针对service “"smart/ccdb:port1521"” 在节点上面监听的端口。
参考:
1. http://www.open-open.com/news/view/1aa473a
2. 《kubernetes权威指南》
docker多个容器内部通信
docker很方便的给我们用容器的方式解决了服务隔离运行,同时也产生了一个需要内部网络多个容器之间发生通讯,其实比较简单就可以实现,方式为:创建一个网络组、然后需要内部通讯的容器都加入到这个网络组中,然后这写加入的容器都是同一个网段,就可以通讯了。
1、创建一个网络组
[root@ecs-b3bf-0225793 ~]#
[root@ecs-b3bf-0225793 ~]# docker network create --driver bridge mq-bridge
5e9af94588646f049559ba049facc50c1c8b3c8a3d06f7cd8c44df5908bf0125
[root@ecs-b3bf-0225793 ~]#
[root@ecs-b3bf-0225793 ~]#
[root@ecs-b3bf-0225793 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
6f66df95e8ce app_net bridge local
95746a181dfb bridge bridge local
9c82ac52a997 docker_default bridge local
d86404029f06 docker_work bridge local
8d350f2a2209 host host local
5e9af9458864 mq-bridge bridge local
2f1631ba396f none null local
[root@ecs-b3bf-0225793 ~]#
如上,我们的网络组就可以使用了:mq-bridge
2、容器启动时指定此容器就可以
[root@ecs-b3bf-0225795 conf]#
[root@ecs-b3bf-0225795 conf]# docker run -d -p 10911:10911 -p 10909:10909 \\
-v /home/docker/rocketmq/logs:/root/logs \\
-v /home/docker/rocketmq/store:/root/store \\
-v /home/docker/rocketmq/conf/broker.conf:/opt/rocketmq-latest/conf/broker.conf \\
--name rmqbroker --link rmqnamesrv:namesrv --net=mq-bridge \\
-e "NAMESRV_ADDR=namesrv:9876" \\
-e "MAX_POSSIBLE_HEAP=200000000" \\
rocketmqinc/rocketmq:latest sh mqbroker
3046c85168b8ee4e6f61c68412c7495c596b4c366eb9091d62205ad5f97eef34
[root@ecs-b3bf-0225795 rocketmq]#
如上最重要的信息:--net=mq-bridge
3、查看我们的网络组中容器的IP
[root@ecs-b3bf-0225795 conf]#
[root@ecs-b3bf-0225795 conf]# docker inspect mq-bridge
ok,多个容器之间的IP就有了,具体再改相应的IP就可以内网通信了
以上是关于K8S 容器之间通讯方式的主要内容,如果未能解决你的问题,请参考以下文章