一文搞懂 Kubernetes 网络通信原理
名词解释
1、网络的命名空间:Linux 在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命名空间中,彼此间无法通信;Docker 利用这一特性,实现不容器间的网络隔离。
2、Veth 设备对:也叫虚拟网络接口对。Veth设备对的引入是为了实现在不同网络命名空间的通信。
3、Iptables/Netfilter:Netfilter 负责在内核中执行各种挂接的规则(过滤、修改、丢弃等),运行在内核 模式中;Iptables模式是在用户模式下运行的进程,负责协助维护内核中 Netfilter 的各种规则表;通过二者的配合来实现整个 Linux 网络协议栈中灵活的数据包处理机制。
4、网桥:网桥是一个二层网络设备,通过网桥可以将 linux 支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。
5、路由:Linux 系统包含一个完整的路由功能,当IP层在处理数据发送或转发的时候,会使用路由表来决定发往哪里。
令人头大的网络模型
一个 Service
$ kubectl get svc --selector app=nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 172.19.0.166 <none> 80/TCP 1m
$ kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP: 172.19.0.166
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 172.16.2.125:80,172.16.2.229:80
Session Affinity: None
Events: <none>
上述信息中该 svc 后端代理了2个Pod实例:172.16.2.125:80,172.16.2.229:80
二个 IP
这里未列出 node ip 概念,由于其本身是物理机的网卡IP。因此可理解为nodeip就是物理机IP。
三个 Port
Port
该Port非一般意义上的TCP/IP中的Port概念,它是特指Kubernetes中Service的port,是Service间的访问端口,例如Mysql的Service默认3306端口。它仅对进群内容器提供访问权限,而无法从集群外部通过该端口访问服务。
nodePort
targetPort
kind: Service
apiVersion: v1
metadata:
name: mallh5-service
namespace: abcdocker
spec:
selector:
app: mallh5web
type: NodePort
ports:
- protocol: TCP
port: 3017
targetPort: 5003
nodePort: 31122
集群内部通信
单节点通信
root@node-1:/opt/bin# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.23.100.1 0.0.0.0 UG 0 0 0 eth0
10.1.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel.1 #flannel 网络内跨节点的通信会交给 flannel.1 处理
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0 #flannel 网络内节点内的通信会走 docker0
1 Pod 内通信
如下图所示:
这种情况下,同一个pod内共享网络命名空间,容器之间通过访问 127.0.0.1:(端口)即可。图中的 veth* 即指veth对的一端(另一端未标注,但实际上是成对出现),该veth对是由 Docker Daemon 挂载在 docker0 网桥上,另一端添加到容器所属的网络命名空间,图上显示是容器中的eth0。
图中演示了 bridge 模式下的容器间通信。docker1 向 docker2 发送请求,docker1,docker2 均与 docker0 建立了 veth 对进行通讯。
当请求经过 docker0 时,由于容器和 docker0 同属于一个子网,因此请求经过 docker2与docker0的veth*对,转发到docker2,该过程并未跨节点,因此不经过eth0。
2 Pod 间通信
同节点 pod 间通信
由于 Pod 内共享网络命名空间(由 pause 容器创建),所以本质上也是同节点容器间的通信。同时,同一 Node 中 Pod 的默认路由都是 docker0 的地址,由于它们关联在同一个 docker0 网桥上,地址网段相同,所有它们之间应当是能直接通信的。来看看实际上这一过程如何实现。如上图,Pod1 中容器 1和容器 2 共享网络命名空间,因此对pod 外的请求通过 pod1 和 Docker0 网桥的 veth对(图中挂在eth0和ethx上)实现。
跨节点通信
CNI:容器网络接口
通信方式
外部访问集群
Nodeport
通过将 Service 的类型设置为 NodePort,就可以在 Cluster 中的主机上通过一个指定端口暴露服务。注意通过 Cluster 中每台主机上的该指定端口都可以访问到该服务,发送到该主机端口的请求会被 Kubernetes 路由到提供服务的 Pod 上。采用这种服务类型,可以在 Kubernetes cluster 网络外通过主机 IP:端口的方式访问到服务。
kind: Service
apiVersion: v1
metadata:
name: influxdb
spec:
type: NodePort
ports:
- port: 8086
nodePort: 31112
selector:
name: influxdb
Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: test.name.com
http:
paths:
- path: /test
backend:
serviceName: service-1
servicePort: 8118
- path: /name
backend:
serviceName: service-2
servicePort: 8228
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: s1
servicePort: 80
- path: /bar
backend:
serviceName: s2
servicePort: 80
总结及展望
- END -
Kubernetes 运维架构师实战集训营(多项目)
终于明白了 DevOps 与 SRE 的区别!Kubernetes 4000节点运维经验分享
从网管到架构师,给你分享这10年的成长感悟Kubernetes 的高级部署策略,你不一定知道!
9个常用的Shell脚本,面试也常问!Linux 性能全方位调优经验总结基于Nginx实现灰度发布与AB测试11 个步骤完美排查服务器是否被入侵
K8s kubectl 常用命令总结(建议收藏)
搭建一套完整的企业级 K8s 集群(v1.22,二进制方式)
点亮,服务器三年不宕机