目录html
重点了解Flannel
, Calico
, Canal
, kube-router
mysql
首先,flannel会利用Kubernetes API或者etcd用于存储整个集群的网络配置,其中最主要的内容为设置集群的网络地址空间,例如,设定整个集群内全部容器的IP都取自网段“10.1.0.0/16”。接着,flannel会在每一个主机中运行flanneld做为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内全部容器的IP地址都将从中分配。而后,flanneld再将本主机获取的subnet以及用于主机间通讯的Public IP,一样经过kubernetes API或者etcd存储起来。最后,flannel利用各类backend mechanism,例如udp,vxlan等等,跨主机转发容器间的网络流量,完成容器间的跨主机通讯。 你们都知道Kubernetes是经过CNI标准对接网络插件的,可是当你去看Flannel(coreos/flannel)的代码时,并无发现它实现了CNI的接口。若是你玩过其余CNI插件,你会知道还有一个二进制文件用来供kubele调用,而且会调用后端的网络插件。对于Flannel(coreos/flannel)来讲,这个二进制文件是什么呢? 这个二进制文件就对应宿主机的/etc/cni/net.d/flannel |
如今,咱们来简单看一下,若是上方Machine A中IP地址为10.1.15.2/24的容器要与下方Machine B中IP地址为10.1.16.2/24的容器进行通讯,封包是如何进行转发的。从上文可知,每一个主机的flanneld会将本身与所获取subnet的关联信息存入etcd中,例如,subnet 10.1.15.0/24所在主机可经过IP 192.168.0.100访问,subnet 10.1.16.0/24可经过IP 192.168.0.200访问。反之,每台主机上的flanneld经过监听etcd,也可以知道其余的subnet与哪些主机相关联。以下图,Machine A上的flanneld经过监听etcd已经知道subnet 10.1.16.0/24所在的主机能够经过Public 192.168.0.200访问,并且熟悉docker桥接模式的同窗确定知道,目的地址为10.1.16.2/24的封包一旦到达Machine B,就能经过cni0网桥转发到相应的pod,从而达到跨宿主机通讯的目的。 所以,flanneld只要想办法将封包从Machine A转发到Machine B就OK了,而上文中的backend就是用于完成这一任务。不过,达到这个目的的方法是多种多样的,因此咱们也就有了不少种backend。在这里咱们举例介绍的是最简单的一种方式`hostgw`:由于`Machine A和Machine B处于同一个子网内`,它们本来就能直接互相访问。所以最简单的方法是:在Machine A中的容器要访问Machine B的容器时,咱们能够将Machine B当作是网关,当有封包的目的地址在subnet 10.1.16.0/24范围内时,就将其直接转发至B便可。而这经过下图中那条红色标记的路由就能完成,对于Machine B同理可得。由此,在知足仍有subnet能够分配的条件下,咱们能够将上述方法扩展到任意数目位于同一子网内的主机。而任意主机若是想要访问主机X中subnet为S的容器,只要在本主机上添加一条目的地址为R,网关为X的路由便可。
Network,全局CIDR格式的IPv4网络,字符串格式,必选 SubnetLen,子网,默认为24位 SubnetMin,分配给节点的起始子网 SubnetMax,分配给节点的最大子网 Backend,flannel要使用的后端
[root@master bin]# cat /run/flannel/subnet.env FLANNEL_NETWORK=10.244.0.0/16 FLANNEL_SUBNET=10.244.0.1/24 FLANNEL_MTU=1450 FLANNEL_IPMASQ=true
hostgw是最简单的backend,它的原理很是简单,直接添加路由,将目的主机当作网关,直接路由原始封包。例如,咱们从etcd中监听到一个EventAdded事件:subnet为10.1.15.0/24被分配给主机Public IP 192.168.0.100,hostgw要作的工做很是简单,在本主机上添加一条目的地址为10.1.15.0/24,网关地址为192.168.0.100,输出设备为上文中选择的集群间交互的网卡便可。对于EventRemoved事件,删除对应的路由便可。
当有一个EventAdded到来时,flanneld如何进行配置的,以及封包是如何在flannel网络中流动的。 |
如上图所示,当主机B加入flannel网络时,和其余全部backend同样,它会将本身的subnet 10.1.16.0/24和Public IP 192.168.0.101写入etcd中,和其余backend不同的是,它还会将vtep设备flannel.1的mac地址也写入etcd中。linux
以后,主机A会获得EventAdded事件,并从中获取上文中B添加至etcd的各类信息。这个时候,它会在本机上添加三条信息:nginx
路由信息:全部通往目的地址10.1.16.0/24的封包都经过vtep设备flannel.1设备发出,发往的网关地址为10.1.16.0,即主机B中的flannel.1设备。sql
fdb信息:MAC地址为MAC B的封包,都将经过vxlan首先发往目的地址192.168.0.101,即主机Bdocker
arp信息:网关地址10.1.16.0的地址为MAC Bshell
如今有一个容器网络封包要从A发往容器B,和其余backend中的场景同样,封包首先经过网桥转发到主机A中。此时经过,查找路由表,该封包应当经过设备flannel.1发往网关10.1.16.0。经过进一步查找arp表,咱们知道目的地址10.1.16.0的mac地址为MAC B。到如今为止,vxlan负载部分的数据已经封装完成。因为flannel.1是vtep设备,会对经过它发出的数据进行vxlan封装(这一步是由内核完成的,至关于udp backend中的proxy),那么该vxlan封包外层的目的地址IP地址该如何获取呢?事实上,对于目的mac地址为MAC B的封包,经过查询fdb,咱们就能知道目的主机的IP地址为192.168.0.101。 最后,封包到达主机B的eth0,经过内核的vxlan模块解包,容器数据封包将到达vxlan设备flannel.1,封包的目的以太网地址和flannel.1的以太网地址相等,三层封包最终将进入主机B并经过路由转发达到目的容器。 |
虚拟网络数据帧添加到VxLAN首部后,封装在物理网络UDP报文中,到达目地主机后,去掉物理网络报文头部及VxLAN首部,再将报文交付给目的终端后端
VxLAN后端使用隧道网络转发会致使必定和流量开销,VxLAN DirectRouting模式,经过添加必要的路由信息使用节点的二层网络直接发送Pod通讯报文,仅在跨IP网络时,才启用隧道方式。这样,在不跨IP网络时,性能基本接近二层物理网络api
已经建立的flannel的网络配置修改后不会生效, 只能删掉flannel, 修改yaml文件后从新建立, 因此必定要提早肯定好网络配置 |
curl https://docs.projectcalico.org/v3.9/manifests/canal.yaml -O kubectl apply -f canal.yaml
kubectl create namespace dev kubectl create namespace prod
apiVersion: v1 kind: Pod metadata: name: pod-demo spec: containers: - name: myapp image: ikubernetes/myapp:v1
kubectl explain networkpolicy.spec.ingress
NetworkPolicy属于名称空间级别 参数: from,源地址对象列表,多个项目间逻辑关系为或,若为空,表示匹配一切源地址;若至少有一个值,则仅容许列表中流量经过 ports,可被访问的端口对象列表,多个项目间为逻辑或,若为空,表示匹配Pod的全部端口;若至少有一个值,则仅容许访问指定的端口 |
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-policy spec: podSelector: {} policyTypes: - Ingress
没有定义Ingress规则, 可是写到了policyTypes里, 就表示默认拒绝入方向访问, 没有写Egress, 表示默认容许出方向访问 |
[root@master networkpolicy]# kubectl apply -f deny-all.yaml -n dev networkpolicy.networking.k8s.io/deny-all-policy created
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-all-ingress spec: podSelector: {} # 匹配全部Pod ingress: - {} # 定义为空, 表示容许访问 policyTypes: ["Ingress"]
仅定义from将默认容许本地Pod全部端口;仅定义ports将默认容许全部源端点;同时定义from和ports时,是逻辑与关系 多个from之间是逻辑或关系 多个ports之间是逻辑或关系 from与ports间是逻辑与关系 from下ipBlock、namespaceSelector、podSelector同时使用多个时,为逻辑或关系 |
# 为pod打标签 [root@master manifests]# kubectl label pod myapp -n dev app=myapp --overwrite pod/myapp labeled [root@master manifests]# kubectl get pod -n dev --show-labels NAME READY STATUS RESTARTS AGE LABELS myapp 1/1 Running 0 29m app=myapp
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-myapp-ingress name: default spec: podSelector: # 该规则只在当前的namespace下,携带app: myapp标签的pod生效。限制请求的类型包括Ingress和Egress matchLabels: app: myapp policyTypes: ["Ingress"] ingress: - from: - ipBlock: # 网络地址块 cidr: 10.244.0.0/16 # 容许某个网段访问 except: # 排除某个网段或ip访问(只拒绝掉10.244.1.5) - 10.244.1.5/32 - podSelector: # 携带了app: myapp标签的pod能够访问 matchLabels: app: myapp ports: - protocol: TCP port: 80
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-egress spec: podSelector: {} policyTypes: ["Egress"]
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-tomcat-egress spec: podSelector: matchLabels: app: tomcat policyTypes: ["Egress"] egress: - to: - podSelector: matchLabels: app: nginx - ports: - protocol: TCP port: 80 - to: - podSelector: matchLabels: app: mysql ports: - protocol: TCP port: 3306
对app=tomcat的Pod,限制只能访问app=nginx的80端口和app=mysql的3306端口 |
隔离名称空间,应该放行与kube-system名称空间中Pod的通讯,以实现监控和名称解析等各类管理功能tomcat
kubectl explain networkpolicy.spec.ingress.from.namespaceSelector.matchExpressions kubectl explain networkpolicy.spec.egress.to.namespaceSelector.matchExpressions
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: namespace-deny-all namespace: default spec: policyTypes: ["Ingress","Egress"] podSelector: {} --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: namespace- namespace: default spec: policyTypes: ["Ingress","Egress"] podSelector: {} ingress: - from: - namespaceSelector: matchExpressions: - key: name operator: In values: ["default","kube-system"] egress: - to: - namespaceSelector: matchExpressions: - key: name operator: In values: ["default","kube-system"]
https://pdf.us/2019/03/27/3129.html
https://my.oschina.net/jxcdwangtao/blog/1624486
https://www.cnblogs.com/YaoDD/p/7681811.html
https://www.cnblogs.com/xzkzzz/p/9952716.html