欢迎访问我的博客,你的支持,是我最大的动力!

马哥_K8s进阶实战(9)网络模型与网络策略

Docker 马从东 245℃ 评论
目录:
[显示]
Kubernetes网络模型及CNI插件

Docker容器网络模型

Bridge桥接、Host主机、Container容器
Bridge,借助虚拟网桥为容器建立网络连接
Host,直接共享节点主机网络名称空间
Container,多个容器共享一个网络名称空间,彼此能以本地通信方式建立连接

Kubernetes网络模型

Container to Container、Pod to Pod、Service to Pod、external to Service 四类通信

Pod网络的实现方式

每个Pod对象使用一个独立网络名称空间,一个网络接口仅能属于一个网络名称空间,每个名称空间中都有伪网络接口
伪网络接口实现方案:
虚拟网桥:一对虚拟以太网接口veth,一个接入容器内,一个留于根名称空间,借助linux内核桥接功能或OpenVSwitch关联至真实物理接口
多路复用:一个中间交换设备,暴露多个虚拟接口,进行数据包转发。MACVLAN及IPVLAN
硬件交换:SR-IOV

使用CNI插件编排网络,Pod初始化或删除时,kubelet会调用默认CNI插件,创建虚拟设备接口附加到相关的底层网络,设置IP、路由并映射到Pod对象网络名称空间

kubelet在/etc/cni/net.d目录查找cni json配置文件,基于type属性到/opt/cni/bin中查找相关插件的二进制文件,然后调用相应插件设置网络

CNI插件及常见实现

CNI基本思想:创建容器时,先创建好网络名称空间,然后调用CNI插件配置这个网络,而后启动容器内的进程

CNI插件类别:main、meta、ipam
main,实现某种特定的网络功能,如loopback、bridge、macvlan、ipvlan
meta,自身不提供任何网络实现,而是调用其他插件,如flanne
ipam,仅用于分配IP地址,不提供网络实现

常见CNI项目:
Flannel,提供叠加网络,基于linux TUN/TAP,使用UDP封装IP报文来创建叠加网络,并借助etcd维护网络分配情况
Calico,基于BGP的三层网络,支持网络策略实现网络的访问控制。在每台机器上运行一个vRouter,利用内核转发数据包,并借助iptables实现防火墙等功能
Canal,由Flannel和Calico联合发布的一个统一网络插件,支持网络策略
Weave Net,多主机容器的网络方案,支持去中心化的控制平面,数据平面上,通过UDP封装实现L2 Overlay
Contiv,思科方案,直接提供多租户网络,支持L2(VLAN)、L3(BGP)、Overlay(VXLAN)
OpenContrail,Juniper开源
kube-router,K8s网络一体化解决方案,可取代kube-proxy实现基于ipvs的Service,支持网络策略、完美兼容BGP的高级特性

值得关注的方案有:flannel、calico、kube-router

flannel网络插件

预留使用一个网络,如 10.244.0.0/16 每个节点分配一个子网,并将分配信息保存于etcd持久存储
fannel使用的后端:
VxLAN,使用内核中VxLAN模块封装报文,推荐的方式。叠加网络模型
host-gw,在节点上创建到达目标容器地址的路由,直接完成报文转发。要求各节点必须在同一个二层网络中,有较好的转发性能,易于设定,适用于对报文转发性要求较高的场景
UDP,使用普通UDP报文封装,完成遂道转发,性能较前两种底,仅用于不支持前两种的环境中
此外,还实验性支持AliVPC、AWSVPC、Alloc、GCE

flannel的配置参数

flannel使用etcd存储虚拟IP和主机IP之间的映射,各节点上运行的守护进程负责监视etcd中信息并完成报文路由
默认,flannel配置信息保存于etcd的 /coreos.com/network/config 下,config 值是json的字典数据结构
Network,全局CIDR格式的IPv4网络,字符串格式,必选
SubnetLen,子网,默认为24位
SubnetMin,分配给节点的起始子网
SubnetMax,分配给节点的最大子网
Backend,flannel要使用的后端
示例:

flannel默认使用VxLAN后端,但VxLAN direct routing 和 host-gw 性能更好

VxLAN后端和direct routing

VxLAN,Virtual extensible Local Area Network 虚拟可扩展局域网,MAC in UDP封装方式

实现方式:虚拟网络数据帧添加到VxLAN首部后,封装在物理网络UDP报文中,到达目地主机后,去掉物理网络报文头部及VxLAN首部,再将报文交付给目的终端

VxLAN可提供多租户支持,但涉及VxLAN通信的IP报文不能分片,要求物理网络提供足够的MTU值

kubectl describe configmaps -n kube-system kube-flannel-cfg  # 查看flannel配置信息
kubectl get daemonsets.apps kube-flannel-ds-amd64 -n kube-system -o yaml  # hostNetwork: true
通过kube-flannel-ds-amd64的daemonset控制器,在每个节点运行flannel相关Pod对象, hostNetwork: true 直接生效于根网络名称空间

VxLAN后端使用隧道网络转发会导致一定和流量开销,VxLAN DirectRouting模式,通过添加必要的路由信息使用节点的二层网络直接发送Pod通信报文,仅在跨IP网络时,才启用隧道方式。这样,在不跨IP网络时,性能基本接近二层物理网络

使用 VxLAN DirectRouting

cd /etc/kubernetes/manifests
curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml  #当前版本为 0.11.0
修改 kube-flannel.yml 中net-conf.json 内容,129行,添加 "Directrouting": true

删除flannel的daemonset及pods,然后
应用到集群:kubectl apply -f kube-flannel.yml
验证:
在任意节点执行 ip route show/netstat -rn  有类似 10.244.2.0/24 via 192.168.1.130 dev ens32 有物理接口的路由条目

iptables -nL 中FORWARD链上添加如下规则:
ACCEPT all -- 10.244.0.0/16 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 10.244.0.0/16
这是 DirectRouting得以实现的必要条件

注意:应当在Pod创建前配置好网络插件,中途修改会导致部分Pod资源需要重建

VxLAN Directrouting 同时兼具VxLAN和host-gw的优势,既保证了传输性能,又具备跨二层网络转发报文的能力
VxLAN配置参数,都有默认值:
Typy,VxLAN,字符串
VNI,VxLAN标识符,默认1,数值
Port,发送封装报文的UDP端口,默认8472,数值
GBP,是否启用基于组的策略,默认false,布尔
DirectRouting,是否为同一二层网络中节点启用直接路由机制,默认false,布尔

host-gw后端

host-gw通过添加必要路由通过节点的二层网络直接传输Pod的报文,类似于VxLAN DirectRouting 但不包括隧道转发能力

配置方法:
cd /etc/kubernetes/manifests/
修改 kube-flannel.yml

kubectl apply -f kube-flannel.yml
配置完成后,各节点会生成类似 VxLAN direct routing 的路由及iptables规则,实现二层转发,但不非同个二层网络的转发不能实现

二层转发在集群较大时路由信息规模将变得庞大而不易维护
flannel自身不具备为Pod网络实现网络策略以实现网络通信隔离的能力,但能借助Canal项目构建网络策略功能

网络策略

使用 NetworkPolicy 资源按需定义网络访问控制策略,实现租户隔离机制

网络策略

网络策略功能由网络插件实现,支持网络策略的插件有 Calico、Canal、kube-router等
策略控制器用于监控创建Pod时所生成的新API端点,并按需为其附加网络策略

Pod网络流量分为 流入Ingress 流出Egress ,每个方向包含允许和禁止两种控制策略
默认Pod处于非隔离状态,应用策略后,所有未经明确允许的流量都将拒绝

部署Canal提供网络策略功能

Canal是针对云原生应用程序最佳策略网络解决方案,可将Calico和flannel网络部署在一起作为统一网络解决方案

Calico既能独立为K8s集群提供网络解决方案和网络策略,也能与flannel结合在一起,由flannel提供网络解决方案,而Calico仅用于提供网络策略,此时的Calico称为Canel
Calico将数据存储于etcd中
注意:结合flannel工作时,Calico的默认配置中是以flannel默认的10.244.0.0/16为Pod网络,需要确保kube-controller-manager启动参数中 --cluster-cidr为此网络地址且 --allocate-node-cidrs值为true

第一步:设置rbac
kubectl apply -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
kubectl describe -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
第二步:部署Canal网络策略
kubectl apply -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/canal/canal.yaml
kubectl get -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/canal/canal.yaml

配置网络策略

相关术语:
Pod组,NetworkPolicy通过Pod选择器选定的一组Pod
Egress,出站流量,由流量的目标网络端口 to 和端口 ports 定义
Ingress,入站流量,由流量发出的源站点 from 和流量的目标端口定义
与某Pod组通信的另一方可使用网络端点描述:
某名称空间中一个或一组Pod,由namespaceSelector选定名称空间后,经由ipBlock或podSelector指定

管控入站流量

kubectl explain networkpolicy.spec.ingress
NetworkPolicy属于名称空间级别
参数:
from,源地址对象列表,多个项目间逻辑关系为或,若为空,表示匹配一切源地址;若至少有一个值,则仅允许列表中流量通过
ports,可被访问的端口对象列表,多个项目间为逻辑或,若为空,表示匹配Pod的所有端口;若至少有一个值,则仅允许访问指定的端口

1、设置默认Ingress策略
默认拒绝:
当在spec.policyTypes中指定规则类型,却在networkpolicy.spec中没有定义任何Ingress或Egress字段时,将拒绝相关方向上一切流量!

默认允许:

2、放行特定入站流量
仅定义from将隐含允许本地Pod所有端口;仅定义ports将隐含允许所有源端点;同时定义from和ports时,是逻辑与关系
多个from之间是逻辑或关系
多个ports之间是逻辑或关系
from与ports间是逻辑与关系
from下ipBlock、namespaceSelector、podSelector同时使用多个时,为逻辑或关系

from字段可使用ipBlock、namespaceSelector、podSelector字段,同时使用时,为逻辑或关系
ipBlock,网络地址块
namespaceSelector,名称空间选择
podSelector,在NetworkPolicy当前名称空间内选择Pod资源

管控出站流量

出站流量包括向CoreDNS请求解析名称

1、设置默认Egress策略
拒绝所有出站流量

2、放行特定的出站流量

对app=tomcat的Pod,限制只能访问app=nginx的80端口和app=mysql的3306端口

隔离名称空间

隔离名称空间,应该放行与kube-system名称空间中Pod的通信,以实现监控和名称解析等各种管理功能
kubectl explain networkpolicy.spec.ingress.from.namespaceSelector.matchExpressions

案例

1、准备工作
kubectl create namespace testing
kubectl run nginx --image=nginx:alpine --replicas=1 --namespace=testing --port=80 --expose --labels=app=nginx
kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=1 --namespace=testing --port=80 --expose --labels=app=myapp
# --expose 创建服务
kubectl label namespaces kube-system ns=kube-system   # 方便引用名称空间
## 测试
kubectl run cirros-$RANDOM --namespace=default --rm -it --image=cirros -- sh
curl nginx.testing
curl myapp.testing

2、定义默认网络策略

先禁用所有流量  # curl myapp.testing --connect-timeout 2

3、定义流量放行规则

同时限制端口和Pod实验不成功,原因为podSelector匹配不到相应的pod,原因未知
此时,在default名称空间,可以访问nginx,不能访问myapp

Calico 网络插件

Calico支持网络策略,Calico是纯三层虚拟网络方案,将每个节点都当作路由器,将节点的每个容器当作节点路由器的一个终端并分配IP
各节点路由器通过BGP生成路由规则
Calico控制平面的设计要求物理网络必须是二层网络,以确保vRouter间均直接可达

Calico工作特性

小规模使用Felix,大规则使用BGP路由反射器(router reflector)
Calico承载的各Pod资源直接通过vRouter经由基础网络进行互联,非叠加、无隧道、不使用VRF表,不依赖NAT,因此每个工作负载可直接配置使用公网IP接入互联网

Pod收发的IP报文由节点内核路由表负责转发,并通过iptables规则实现安全功能
Calico未使用额外报文封装,简化了网络拓扑,高性能、易扩展
Calico各工作负载使用基IP直接进行互联,支持跨地域协同

Calico系统架构

Calico由:Felix、Orchestrator Plugin、etcd、BIRD、BGP Reflector等组件组成
Felix,Calico Agent,运行于每个节点,负责生成路由和ACL,接口管理,路由规划,ACL规划,状态报告
Orchestrator Plugin,编排系统(如K8s/OpenStack等)将Calico整合进系统的插件,如CNI
etcd,存储数据,也是Calico各组件的通信总线
BIRD,分发路由信息的BGP客户端
BGP Route Reflector,BGP路由反射器,可选组件,用于较大规模的网络场景

Calico部署要点

推荐为Calico配置专用集群,而非共用K8s的etcd集群

calico/node,为每个节点提供Felix Agent和BGP客户端
cni-plugin,CNI网络插件,每个运行kubelet的主机都需要配置
calico/kube-controllers,网络策略控制器

安装方式:
1、独立运行于K8s集群之外,但calico/kube-controllers依然需要以Pod资源运行于集群之上
2、以插件方式完全托管于K8s集群之上

Calico分配的地址池应该与集群 --pod-network-cidr的值保持一致,默认,Calico使用192.168.0.0/16作为Pod网络

部署Calico

独立部署Calico,提供网络服务及网络策略,使用K8s API作为Calico的数据存储,以取代etcd
刚由kubeadm部署完成的新集群

在启用RBAC的K8s集群上部署Calico时,首先需创建必要的ClusterRole和ClusterRoleBinding资源
kubectl apply -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
然后部署Calico
kubectl apply -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml

工作于IPIP模式的Calico会在每个节点上创建一个tunl0接口,用于封装三层隧道报文:

IPIP三层隧道外层为节点物理IP,内层为Pod的IP,相比于VxLAN,IPIP开销更小,安全性也要差一些
tunl0接口MTU默认为1440,最佳值为1480 (FELIX_INPUTMTU值)

对50个节点以上的集群,所有Calico节点均基于K8s API存取数据会对API Server带来不小的通信压力,此时应该使用calico-typha进程将所有Calico通信集中起来与API Server进行统一交互。
calico-typha以Pod资源的形式托管运行于K8s之上,启用方法为修改calico.yaml配置,修改Deployment名为calico-typha的replicas数量为期望的值即可
每个calico-typha Pod可承载100到200个Calico节点的连接请求,最多不超过200个;所有calico-typha总数不能超过20个

客户端工具calicoctl

calicoctl可直接以裸二进制文件部署于某管理机上
wget https://github.com/projectcalico/calicoctl/releases/download/v3.1.1/calicoctl -O /usr/bin/calicoctl
chmod +x /usr/bin/calicoctl

calicoctl通过读写Calico的数据存储进行查看或管理操作
当使用API Server作为数据存储时,需要配置认证
DATASTORE_TYPE=kubernetes KUBECONFIG=~/.kube/config calicoctl get nodes
也可以将认证信息保存于配置文件中,默认配置文件为 /etc/calico/calicoctl.cfg

# 查看calico节点状态信息
calicoctl node status
# 查看当前模型
calicoctl get ipPool -o yaml
默认calico的BGP网络工作于node-to-node mesh模型,适用于较小规模的集群
中级集群应使用全局对等BGP模型 Global BGP peers,在同个二层网络中使用一个或一组BGP反射器
大型集群需使用每节点对等BGP模型Per-node BGP peers,即分布式BGP反射器模型

Calico文档:https://docs.projectcalico.org

转载请注明:轻风博客 » 马哥_K8s进阶实战(9)网络模型与网络策略

喜欢 (0)or分享 (0)