一 网络通信
1 二层通信
基于目标mac地址通信 不可跨局域网通信 通常通过交换机实现报文转发
2 三层网络通信-Vlan
VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理(交换机)的网络在逻辑上划分成多 个广播域的通信技术,VLAN内的主机间可以直接通信,而VLAN网络外的主机需要通过三层网络设备 转发才可以通信,因此一个vlan可以将服务器的广播报文限制在一个VLAN内,从而降低单个网络环 境中的广播报文,vlan采用12位标识vlan ID,即一个交换机设备最多为2^12=4096个vlan。
单臂路由
单臂路由(router-on-a-stick)是指在路由器的一个接口上通过配置子接口(或“逻辑接口”,并不存在真正物理接口)的方式,实现原来相互隔离的不同VLAN(虚拟局域网)之间的互联互通。
单臂路由的子接口
路由器的物理接口可以被划分成多个逻辑接口,这些被划分后的逻辑接口被形象的称为子接口。值得注意的是这些逻辑子接口不能被单独的开启或关闭,也就是说,当物理接口被开启或关闭时,所有的该接口的子接口也随之被开启或关闭。
3 overlay网络
overlay(又叫叠加网络、覆盖网络)简单理解就是把一个逻辑网络建立在一个实体网络之上。其在大体框架上对基础网络不进行大规模修改就能实现应用在网络上的承载,并能与其它网络业务分离,通过控制协议对边缘的网络设备进行网络构建和扩展是SD-WAN以及数据中心等解决方案使用的核心组网技术。
overlay网络与underlay网络区别
vxlan
VxLAN:VxLAN全称是Virtual eXtensible Local Area Network(虚拟扩展本地局域网),主要有Cisco推出,vxlan 是一个 VLAN 的扩展协议,是由IETF定义的NVO3(Network Virtualization over Layer 3)标准技术之一,VXLAN 的特点是将L2的以太帧封装到UDP报文(即L2 over L4)中,并在L3网络中传输,即使用MAC in UDP的方法对报 文进行重新封装, VxLAN 本质上是一种overlay的隧道封装技术,它将L2的以太网帧封装成L4的UDP数据报,然后 在L3的网络中传输,效果就像L2的以太网帧在一个广播域中传输一样,实际上L2的以太网帧跨越了L3网络传输, 但是缺不受L3网络的限制,vxlan采用24位标识vlan ID号,因此可以支持2^24=16777216个vlan,其可扩展性比 vlan强大的多,可以支持大规模数据中心的网络需求。简单来说,overlay 报文封装;pod内容器的ip和mac地址,以及宿主机的ip和mac地址都封装到1个报文里;mac地址可以跨子网传输。
VTEP(VXLAN Tunnel Endpoint vxlan隧道端点),VTEP是VXLAN网络的边缘设备,是VXLAN隧道的起点 和终点,VXLAN对用户原始数据帧的封装和解封装均在VTEP上进行,用于VXLAN报文的封装和解封
装,VTEP与物理网络相连,分配的地址为物理网IP地址,VXLAN报文中源IP地址为本节点的VTEP地址, VXLAN报文中目的IP地址为对端节点的VTEP地址,一对VTEP地址就对应着一个VXLAN隧道,服务器 上的虚拟交换机(隧道flannel.1就是VTEP),比如一个虚拟机网络中的多个vxlan就需要多个VTEP对不同 网络的报文进行封装与解封装。
VNI(VXLAN Network Identifier):VXLAN网络标识VNI类似VLAN ID,用于区分VXLAN段,不同 VXLAN段的虚拟机不能直接二层相互通信,一个VNI表示一个租户,即使多个终端用户属于同一个VNI, 也表示一个租户。
NVGRE:Network Virtualization using Generic Routing Encapsulation,主要支持者是Microsoft,与 VXLAN不同的是,NVGRE没有采用标准传输协议(TCP/UDP),而是借助通用路由封装协议
(GRE),NVGRE使用GRE头部的低24位作为租户网络标识符(TNI),与VXLAN一样可以支持 1777216个vlan。
overlay通信过程:
1.VM A发送L2 帧与VM请求与VM B通信。
2.源宿主机VTEP添加或者封装VXLAN、UDP及IP头部报文。
3.网络层设备将封装后的报文通过标准的报文在三层网络进行转发到目标主机。
4.目标宿主机VTEP删除或者解封装VXLAN、UDP及IP头部。
5.将原始L2帧发送给目标VM
4 underlay网络
Underlay网络就是传统IT基础设施网络,由交换机和路由器等设备组成,借助以太网协议、路由协议和VLAN协议等驱动,它还是Overlay网络的底层网络,为Overlay网络提供数据通信服务。容器网络中的Underlay网络是指借助驱动程序将宿主机的底层网络接口直接暴露给容器使用的一种网络构建技术,较为常见的解决方案有MAC VLAN、IP VLAN和直接路由等。
Underlay依赖于网络网络进行跨主机通信。
underlay实现模式
Mac Vlan模式:
MAC VLAN:支持在同一个以太网接口上虚拟出多个网络接口(子接口),每个虚拟接口都拥有唯一的MAC地址并可配置网卡子接口IP。
IP VLAN模式:
IP VLAN类似于MAC VLAN,它同样创建新的虚拟网络接口并为每个接口分配唯一的IP地址,不同之处在于,每个虚拟接口将共享使用物理接口的MAC地址。
一般都使用mac vlan模式
mac vlan模式
Private(私有)模式:
- 在Private模式下,同一个宿主机下的容器不能通信,即使通过交换机再把数据报文转发回来也不行。
VEPA模式:
- 虚拟以太端口汇聚器(Virtual Ethernet Port Aggregator,简称VEPA),在这种模式下,macvlan内的容器不能直接接收在同一个物理网卡的容器的请求数据包,但是可以经过交换机的(端口回流)再转发回来可以实现通信。
passthru(直通)模式:
- Passthru模式下该macvlan只能创建一个容器,当运行一个容器后再创建其他容器则会报错。
bridge模式:
- 在bridge这种模式下,使用同一个宿主机网络的macvlan容器可以直接实现通信,推荐使用此模式。
overlay与underlay差异
overlay:
- 要对报文进行封装与解封装
- node节点可以使用不同的子网,后期node可扩展性好
- 性能比underlay要低一些
- 主要用于私有云,公有云自建K8S 也用(flannel)
flannel,不支持支持networkpolicy 使用mac地址进行保温传输,因此pod的mac地址不同
calico ,支持networkpolicy
公有云:
underlay:pod使用与宿主机相同的网络,不需要封装和解封装
pod通信的三种实现方式
Overlay络:
Flannel Vxlan、Calico BGP、Calico Vxlan将pod 地址信息封装在宿主机地址信息以内,实现跨主机且可跨node子网的通信报文。
直接路由:
Flannel Host-gw、Flannel VXLAN Directrouting、Calico Directrouting基于主机路由,实现报文从源主机到目的主机的直接转发,不需要进行报文的叠加封装,性能比overlay更好。
Underlay:
需要为pod启用单独的虚拟机网络,而是直接使用宿主机物理网络,pod甚至可以在k8s环境之外的节点直接访问(与node节点的网络被打通),相当于把pod当桥接模式的虚拟机使用,比较方便k8s环境以外的访问访问k8s环境中的pod中的服务,而且由于主机使用的宿主机网络,其性能最好。
flannel网络
由CoreOS开源的针对k8s的网络服务,其目的为解决k8s集群中各主机上的pod相互通信的问题,其借助于etcd维护网络IP地址分配,并为每一个node服务器分配一个不同的IP地址段
flannel网络模式:
Flannel 网络模型 (后端模型),Flannel目前有三种方式实现 UDP/VXLAN/host-gw:
- UDP:早期版本的Flannel使用UDP封装完成报文的跨越主机转发,其安全性及性能略有不足。
- VXLAN:Linux 内核在在2012年底的v3.7.0之后加入了VXLAN协议支持,因此新版本的Flannel也有UDP转换为VXLAN,VXLAN本质上是一种tunnel(隧道)协议,用来基于3层网络实现虚拟的2层网络,目前flannel 的网络模型已经是基于VXLAN的叠加(覆盖)网络,目前推荐使用vxlan作为其网络模型。
- Host-gw:也就是Host GateWay,通过在node节点上创建到达各目标容器地址的路由表而完成报文的转发,因此这种方式要求各node节点本身必须处于同一个局域网(二层网络)中,因此不适用于网络变动频繁或比较大型的网络环境,但是其性能较好。
Flannel 组件的解释:
Cni0:网桥设备,每创建一个pod都会创建一对 veth pair,其中一端是pod中的eth0,另一端是Cni0网桥中的端口(网卡),Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口(网卡)上,Cni0 设备获得的ip地址是该
节点分配到的网段的第一个地址。
Flannel.1: overlay网络的设备,用来进行vxlan报文的处理(封包和解包),不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。
Flanneld:flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库,为flannel.1设备提供封装数据时必要的mac,ip等网络数据信息。
Flannel vxlan架构图
不同node上的pod的通信流程:
·······································
- pod中产生数据,根据pod的路由信息,将数据发送到Cni0
- Cni0 根据节点的路由表,将数据发送到隧道设备flannel.1
- Flannel.1查看数据包的目的ip,从flanneld获得对端隧道设备的必要信息,封装数据包。
- Flannel.1将数据包发送到对端设备。对端节点的网卡接收到数据包,发现数据包为overlay数据包,解开外层封装,并发送内层封装到flannel.1设备。
- Flannel.1设备查看数据包,根据路由表匹配,将数据发送给Cni0设备。
- Cni0匹配路由表,发送数据给网桥上对应的端口。
1 pod中容器到cni0
Pod1与Pod3能够互相ping通
Ping包的dst ip 为192.20.1.43,根据路由匹配到最后一条路由表项,去往192.20.0.0/12的包都转发给192.20.0.1。
192.20.0.1为cni0的ip地址。
2 cni0 到flannel.1
当icmp包达到cni0之后,cni0发现dst为192.20.1.43,cni根据主机路由表来查找匹配项。
根据最小匹配原则,匹配到图上的一条路由表项。去往192.20.1.0/24 网段的包,发送192.20.1.0网关,网关设备是flannel.1。
3 flannel.1
flannel.1为vxlan设备,当数据包来到flannel.1时,需要将数据包封装起来。此时的dst ip 为192.20.1.43,src ip为192.20.0.51。数据包继续封装需要知道192.20.1.43 ip地址对应的mac地址。此时,flannel.1不会发送arp请求去获得192.20.1.42的mac地址,而是由Linux kernel将一个“L3 Miss”事件请求发送的用户空间的flanned程序。Flanned程序收到内核的请求事件之后,从etcd查找能够匹配该地址的子网的flannel.1设备的mac地址,即发往的pod所在host中flannel.1设备的mac地址。Flannel在为Node节点分配ip网段时记录了所有的网段和mac等信息,所以能够知道。交互流程如下图所示:
flanned将查询到的信息放入master node host的arp cache表中:
到这里,vxlan的内层数据包就完成了封装。格式是这样的:
简单总结这个流程:
1.数据包到达flannel.1,通过查找路由表,知道数据包要通过flannel.1发往192.20.1.0
2.通过arp cache表,知道了目的ip192.20.1.0的mac地址。
kernel需要查看node上的fdb(forwarding database)以获得内层封包中目的vtep设备所在的node地址。因为已经从arp table中查到目的设备mac地址为52:77:71:e6:4f:58,同时在fdb中存在该mac地址对应的node节点的IP地址。如果fdb中没有这个信息,那么kernel会向用户空间的flanned程序发起”L2 MISS”事件。flanneld收到该事件后,会查询etcd,获取该vtep设备对应的node的”Public IP“,并将信息注册到fdb中。
当内核获得了发往机器的ip地址后,arp得到mac地址,之后就能完成vxlan的外层封装。
4.对端flannel.1
Node节点的eth0网卡接收到vxlan设备包,kernal将识别出这是一个vxlan包,将包拆开之后转给节点上的flannel.1设备。这样数据包就从发送节点到达目的节点,flannel.1设备将接收到一个如下的数据包:
目的地址为192.20.1.43,flannel.1查找自己的路由表,根据路由表完成转发。
根据最下匹配原则,flannel.1将去往192.20.1.0/24的流量转发到cni0上去。
5 cni0到pod
cni0是一个网桥设备。当cni0拿到数据包之后,通过veth pair,将数据包发送给pod。查看Node节点中的网桥。
在node节点上通过arp解析可以开出,192.20.1.43的mac地址为 66:57:8e:3d:00:85
该地址为pod的网卡eth0的地址。
同时通过veth pair的配对关系可以看出,pod中的eth0是veth pair的一端,另一端在node节点行上,对应的网卡是vethd356ffc1@if3。所以,在cni0网桥上挂载的pod的veth pair为vethd356ffc1,即:
eth0@if50和vethd356ffc1@if3组成的一对veth,pair。其效果相当于将pod中的eth0直接插在到cni0上。所以简单总结cni0转发流量的原理:
- 首先通过arp查找出ip地址对应的mac地址
- 将流量转发给mac地址所在eth0网的对应的veth pair端口
- veth pair端口接收到流量,直接将流量注入到pod的eth0网卡上。
不同后端的封装
Flannel可以指定不同的转发后端网络,常用的有hostgw,udp,vxlan等。
Hostgw
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,输出设备为上文中选择的集群间交互的网卡即可。
优点:简单,直接,效率高
缺点:要求所有的pod都在一个子网中,如果跨网段就无法通信。
UDP
如何应对Pod不在一个子网里的场景呢?将Pod的网络包作为一个应用层的数据包,使用UDP封装之后在集群里传输。即overlay。
其中右边Packer的封装格式就是使用udp完成overlay的格式
当容器10.1.15.2/24要和容器10.1.20.2/24通信时,
1.因为该封包的目的地不在本主机subnet内,因此封包会首先通过网桥转发到主机中。
2.在主机上经过路由匹配,进入网卡flannel.1。(需要注意的是flannel.1是一个tun设备,它是一种工作在三层的虚拟网络设备,而flanneld是一个proxy,它会监听flannel.1并转发流量。)
3.当封包进入flannel.1时,flanneld就可以从flanne.1中将封包读出,由于flanne.1是三层设备,所以读出的封包仅仅包含IP层的报头及其负载。
4.最后flanneld会将获取的封包作为负载数据,通过udp socket发往目的主机。
5.在目的主机的flanneld会监听Public IP所在的设备,从中读取udp封包的负载,并将其放入flannel.1设备内。
6.容器网络封包到达目的主机,之后就可以通过网桥转发到目的容器了。
优点:Pod能够跨网段访问
缺点:隔离性不够,udp不能隔离两个网段。
Vxlan
vxlan和上文提到的udp backend的封包结构是非常类似的,不同之处是多了一个vxlan header,以及原始报文中多了个二层的报头。
当初始化集群里,vxlan网络的初始化工作:
主机B加入flannel网络时,它会将自己的三个信息写入etcd中,分别是:subnet 10.1.16.0/24、Public IP 192.168.0.101、vtep设备flannel.1的mac地址 MAC B。之后,主机A会得到EventAdded事件,并从中获取上文中B添加至etcd的各种信息。这个时候,它会在本机上添加三条信息:
-
路由信息:所有通往目的地址10.1.16.0/24的封包都通过vtep设备flannel.1设备发出,发往的网关地址为10.1.16.0,即主机B中的flannel.1设备。
-
fdb信息:MAC地址为MAC B的封包,都将通过vxlan发往目的地址192.168.0.101,即主机B
3)arp信息:网关地址10.1.16.0的地址为MAC B
事实上,flannel只使用了vxlan的部分功能,由于VNI被固定为1,本质上工作方式和udp backend是类似的,区别无非是将udp的proxy换成了内核中的vxlan处理模块。而原始负载由三层扩展到了二层,但是这对三层网络方案flannel是没有意义的,这么做也仅仅只是为了适配vxlan的模型。vxlan详细的原理参见文后的参考文献,其中的分析更为具体,也更易理解。
总的来说,flannel更像是经典的桥接模式的扩展。我们知道,在桥接模式中,每台主机的容器都将使用一个默认的网段,容器与容器之间,主机与容器之间都能互相通信。要是,我们能手动配置每台主机的网段,使它们互不冲突。接着再想点办法,将目的地址为非本机容器的流量送到相应主机:如果集群的主机都在一个子网内,就搞一条路由转发过去;若是不在一个子网内,就搞一条隧道转发过去。这样以来,容器的跨网络通信问题就解决了。而flannel做的,其实就是将这些工作自动化了而已。
flannel存在问题
1.不支持pod之间的网络隔离。Flannel设计思想是将所有的pod都放在一个大的二层网络中,所以pod之间没有隔离策略。
2.设备复杂,效率不高。Flannel模型下有三种设备,数量经过多种设备的封装、解析,势必会造成传输效率的下降。
calico网络
1 简介
Calico 是一种容器之间互通的网络方案。在虚拟化平台中,比如 OpenStack、Docker 等都需要实现 workloads 之间互连,但同时也需要对容器做隔离控制,就像在 Internet 中的服务仅开放80端口、公有云的多租户一样,提供隔离和管控机制。而在多数的虚拟化平台实现中,通常都使用二层隔离技术来实现容器的网络,这些二层的技术有一些弊端,比如需要依赖 VLAN、bridge 和隧道等技术,其中 bridge 带来了复杂性,vlan 隔离和 tunnel 隧道则消耗更多的资源并对物理环境有要求,随着网络规模的增大,整体会变得越加复杂。我们尝试把 Host 当作 Internet 中的路由器,同样使用 BGP 同步路由,并使用 iptables 来做安全访问策略,最终设计出了 Calico 方案。
适用场景:k8s环境中的pod之间需要隔离
设计思想:Calico 不使用隧道或 NAT 来实现转发,而是巧妙的把所有二三层流量转换成三层流量,并通过 host 上路由配置完成跨 Host 转发。
设计优势:
1.更优的资源利用
二层网络通讯需要依赖广播消息机制,广播消息的开销与 host 的数量呈指数级增长,Calico 使用的三层路由方法,则完全抑制了二层广播,减少了资源开销。
另外,二层网络使用 VLAN 隔离技术,天生有 4096 个规格限制,即便可以使用 vxlan 解决,但 vxlan 又带来了隧道开销的新问题。而 Calico 不使用 vlan 或 vxlan 技术,使资源利用率更高。
2.可扩展性
Calico 使用与 Internet 类似的方案,Internet 的网络比任何数据中心都大,Calico 同样天然具有可扩展性。
3.简单而更容易 debug
因为没有隧道,意味着 workloads 之间路径更短更简单,配置更少,在 host 上更容易进行 debug 调试。
4.更少的依赖
Calico 仅依赖三层路由可达。
5.可适配性
Calico 较少的依赖性使它能适配所有 VM、Container、白盒或者混合环境场景。
2 calico架构
Calico网络模型主要工作组件:
1.Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等。
2.etcd:分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用;
3.BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通。
4.BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。
Felix
Felix会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是创建了一个容器等。用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。
BIRD
BIRD是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。
架构特点
由于Calico是一种纯三层的实现,因此可以避免与二层方案相关的数据包封装的操作,中间没有任何的NAT,没有任何的overlay,所以它的转发效率可能是所有方案中最高的,因为它的包直接走原生TCP/IP的协议栈,它的隔离也因为这个栈而变得好做。因为TCP/IP的协议栈提供了一整套的防火墙的规则,所以它可以通过IPTABLES的规则达到比较复杂的隔离逻辑。
3 calico node之间的两种网路
IPIP
从字面来理解,就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel。它的作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。
BGP
边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP,BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。
IPIP工作模式
1 测试环境
一个msater节点,ip 172.171.5.95,一个node节点 ip 172.171.5.96
创建一个daemonset的应用,pod1落在master节点上 ip地址为192.168.236.3,pod2落在node节点上 ip地址为192.168.190.203
pod1 ping pod2
2 ping包的过程
pod1上的路由信息
根据路由信息,ping 192.168.190.203,会匹配到第一条。第一条路由的意思是:去往任何网段的数据包都发往网管169.254.1.1,然后从eth0网卡发送出去。
路由表中Flags标志的含义:
U up表示当前为启动状态
H host表示该路由为一个主机,多为达到数据包的路由
G Gateway 表示该路由是一个网关,如果没有说明目的地是直连的
D Dynamicaly 表示该路由是重定向报文修改
M 表示该路由已被重定向报文修改
master节点上的路由信息
当ping包来到master节点上,会匹配到路由tunl0。该路由的意思是:去往192.169.190.192/26的网段的数据包都发往网关172.171.5.96。因为pod1在5.95,pod2在5.96。所以数据包就通过设备tunl0发往到node节点上。
node节点上路由信息
当node节点网卡收到数据包之后,发现发往的目的ip为192.168.190.203,于是匹配到红线的路由。该路由的意思是:192.168.190.203是本机直连设备,去往设备的数据包发往caliadce112d250。
这个设备就是veth pair的一端。在创建pod2时calico会给pod2创建一个veth pair设备。一端是pod2的网卡,另一端就是我们看到的caliadce112d250。下面我们验证一下。在pod2中安装ethtool工具,然后使用ethtool -S eth0,查看veth pair另一端的设备号。
pod2 网卡另一端的设备好号是18,在node上查看编号为18的网络设备,可以发现该网络设备就是caliadce112d250。
所以,node上的路由,发送caliadce112d250的数据其实就是发送到pod2的网卡中。ping包的旅行到这里就到了目的地。
查看一下pod2中的路由信息,发现该路由信息和pod1中是一样的。
顾名思义,IPIP网络就是将IP网络封装在IP网络里。IPIP网络的特点是所有pod的数据流量都从隧道tunl0发送,并且在tunl0这增加了一层传输层的封包。
在master网卡上抓包分析该过程。
打开ICMP 285,pod1 ping pod2的数据包,能够看到该数据包一共5层,其中IP所在的网络层有两个,分别是pod之间的网络和主机之间的网络封装。
根据数据包的封装顺序,应该是在pod1 ping pod2的ICMP包外面多封装了一层主机之间的数据包。
之所以要这样做是因为tunl0是一个隧道端点设备,在数据到达时要加上一层封装,便于发送到对端隧道设备中。
两层IP封装的具体内容
IPIP的连接方式:
BGP工作模式
1 修改配置
在安装calico网络时,默认安装是IPIP网络。calico.yaml文件中,将CALICO_IPV4POOL_IPIP的值修改成 "off",就能够替换成BGP网络。
2 对比
BGP网络相比较IPIP网络,最大的不同之处就是没有了隧道设备 tunl0。 前面介绍过IPIP网络pod之间的流量发送tunl0,然后tunl0发送对端设备。BGP网络中,pod之间的流量直接从网卡发送目的地,减少了tunl0这个环节。
master节点上路由信息。从路由信息来看,没有tunl0设备。
同样创建一个daemonset,pod1在master节点上,pod2在node节点上。
3 ping包之旅
pod1 ping pod2
根据pod1中的路由信息,ping包通过eth0网卡发送到master节点上。
master节点上路由信息。根据匹配到的 192.168.190.192 路由,该路由的意思是:去往网段192.168.190.192/26 的数据包,发送网段172.171.5.96。而5.96就是node节点。所以,该数据包直接发送了5.96节点。
node节点上的路由信息。根据匹配到的192.168.190.192的路由,数据将发送给 cali6fcd7d1702e设备,该设备和上面分析的是一样,为pod2的veth pair 的一端。数据就直接发送给pod2的网卡。
当pod2对ping包做出回应之后,数据到达node节点上,匹配到192.168.236.0的路由,该路由说的是:去往网段192.168.236.0/26 的数据,发送给网关 172.171.5.95。数据包就直接通过网卡ens160,发送到master节点上。
通过在master节点上抓包,查看经过的流量,筛选出ICMP,找到pod1 ping pod2的数据包。
可以看到BGP网络下,没有使用IPIP模式,数据包是正常的封装。
值得注意的是mac地址的封装。192.168.236.0是pod1的ip,192.168.190.198是pod2的ip。而源mac地址是 master节点网卡的mac,目的mac是node节点的网卡的mac。这说明,在 master节点的路由接收到数据,重新构建数据包时,使用arp请求,将node节点的mac拿到,然后封装到数据链路层。
BGP的连接方式:
两种网络对比
IPIP网络:
流量:tunlo设备封装数据,形成隧道,承载流量。
适用网络类型:适用于互相访问的pod不在同一个网段中,跨网段访问的场景。外层封装的ip能够解决跨网段的路由问题。
效率:流量需要tunl0设备封装,效率略低
BGP网络:
流量:使用路由信息导向流量
适用网络类型:适用于互相访问的pod在同一个网段,适用于大型网络。
效率:原生hostGW,效率高
Networkpolicy
NetworkPolicy 是一种以应用为中心的结构,允许你设置如何允许 Pod 与网络上的各类网络“实体” (我们这里使用实体以避免过度使用诸如“端点”和“服务”这类常用术语, 这些术语在 Kubernetes 中有特定含义)通信。 NetworkPolicy 适用于一端或两端与 Pod 的连接,与其他连接无关。
基于NetworkPolicy在三层(网络层)或四层(传输层)控制拒绝或允许请求流量。
- 允许或拒绝特定的pod请求目的namespace中的目的pod的所有或指定端口。
- 允许或拒绝特定的namespace请求目的namespace中的所有或特定的pod所有或指定端口。
- 允许或拒绝特定的源IP范围或IP地址请求目的pod的所有或特定端口。
测试环境
两个namespace,linux和python,分别代表不同项目的Pod
每个namespace 运行多个pod,且pod可以运行在不同的node主机
测试环境为每个namespace分别运行一个nginx和一个tomcat pod,用于测试不同主机的Pod运行在同一个ns的场景、以及跨ns的访问通信及访问限制
创建namespace
部署测试web服务
创建linux namespace目录下的nginx 和 tomcat的pod
root@192:/usr/local/src/20230611/NetWorkPolicy-case/linux-ns1# cat nginx.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: linux-nginx-deployment-label
name: linux-nginx-deployment
namespace: linux
spec:
replicas: 1
selector:
matchLabels:
app: linux-nginx-selector
template:
metadata:
labels:
app: linux-nginx-selector
spec:
containers:
- name: linux-nginx-container
image: nginx:1.20.2-alpine
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
- containerPort: 443
protocol: TCP
name: https
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
# resources:
# limits:
# cpu: 2
# memory: 2Gi
# requests:
# cpu: 500m
# memory: 1Gi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: linux-nginx-service-label
name: linux-nginx-service
namespace: linux
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
nodePort: 30008
- name: https
port: 443
protocol: TCP
targetPort: 443
nodePort: 30443
selector:
app: linux-nginx-selector
root@192:/usr/local/src/20230611/NetWorkPolicy-case/linux-ns1# cat tomcat.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: linux-tomcat-app1-deployment-label
name: linux-tomcat-app1-deployment
namespace: linux
spec:
replicas: 1
selector:
matchLabels:
app: linux-tomcat-app1-selector
template:
metadata:
labels:
app: linux-tomcat-app1-selector
spec:
containers:
- name: linux-tomcat-app1-container
image: tomcat:7.0.109-jdk8-openjdk
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
# resources:
# limits:
# cpu: 2
# memory: 2Gi
# requests:
# cpu: 500m
# memory: 1Gi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: linux-tomcat-app1-service-label
name: linux-tomcat-app1-service
namespace: linux
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30006
selector:
app: linux-tomcat-app1-selector
进入linux tomcat的pod 加入web页面
root@192:/usr/local/src/20230611/NetWorkPolicy-case/linux-ns1# kubectl exec -it -n linux linux-tomcat-app1-deployment-57cf9b4cdd-lmhfd bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@linux-tomcat-app1-deployment-57cf9b4cdd-lmhfd:/usr/local/tomcat# cd webapps
root@linux-tomcat-app1-deployment-57cf9b4cdd-lmhfd:/usr/local/tomcat/webapps# mkdir app
root@linux-tomcat-app1-deployment-57cf9b4cdd-lmhfd:/usr/local/tomcat/webapps# echo "linux web app" > app/index.jsp
进入linux nginx的pod 添加后端解析
root@192:/usr/local/src/20230611/NetWorkPolicy-case/linux-ns1# kubectl exec -it -n linux linux-nginx-deployment-58b7ddbdcb-tnp7l /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # vi /etc/nginx/conf.d/default.conf
/ # nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
/ # nginx -s reload
2023/07/20 06:28:59 [notice] 67#67: signal process started
/ # curl linux-tomcat-app1-service/app/index.jsp
linux web app
可以看到已经可以解析到后端。
创建python namespace目录下的nginx 和 tomcat的pod
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat nginx.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: python-nginx-deployment-label
name: python-nginx-deployment
namespace: python
spec:
replicas: 1
selector:
matchLabels:
app: python-nginx-selector
template:
metadata:
labels:
app: python-nginx-selector
project: python
spec:
containers:
- name: python-nginx-container
image: nginx:1.20.2-alpine
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
- containerPort: 443
protocol: TCP
name: https
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
# resources:
# limits:
# cpu: 2
# memory: 2Gi
# requests:
# cpu: 500m
# memory: 1Gi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: python-nginx-service-label
name: python-nginx-service
namespace: python
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
nodePort: 30014
- name: https
port: 443
protocol: TCP
targetPort: 443
nodePort: 30453
selector:
app: python-nginx-selector
project: python #一个或多个selector,至少能匹配目标pod的一个标签
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat tomcat.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: python-tomcat-app1-deployment-label
name: python-tomcat-app1-deployment
namespace: python
spec:
replicas: 1
selector:
matchLabels:
app: python-tomcat-app1-selector
template:
metadata:
labels:
app: python-tomcat-app1-selector
spec:
#nodeName: 192.168.110.209
containers:
- name: python-tomcat-app1-container
image: tomcat:7.0.109-jdk8-openjdk
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
# resources:
# limits:
# cpu: 2
# memory: 2Gi
# requests:
# cpu: 500m
# memory: 1Gi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: python-tomcat-app1-service-label
name: python-tomcat-app1-service
namespace: python
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30015
selector:
app: python-tomcat-app1-selector
同理,tomcat pod中添加app/index.jsp nginx pod中添加后端代理
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# kubectl get pod -n python
NAME READY STATUS RESTARTS AGE
python-nginx-deployment-cf5f7d897-pgqxf 1/1 Running 0 20h
python-tomcat-app1-deployment-7954f8f4cd-sfxgg 1/1 Running 0 20h
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# kubectl exec -it python-tomcat-app1-deployment-7954f8f4cd-sfxgg -n python bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat# cd webapps
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps# mkdir app
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps# ls
app
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps# cd app/
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps/app# ls
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps/app# echo "python web app" > index.jsp
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps/app# ls
index.jsp
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps/app# cat index.jsp
python web app
root@python-tomcat-app1-deployment-7954f8f4cd-sfxgg:/usr/local/tomcat/webapps/app# exit
command terminated with exit code 130
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# kubectl exec -it python-nginx-deployment-cf5f7d897-pgqxf -n python bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
error: Internal error occurred: error executing command in container: failed to exec in container: failed to start exec "68289f1ef6e4a7aba258dee17bde1527edd26f25e83a4488d003697ffe915c07": OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# kubectl exec -it python-nginx-deployment-cf5f7d897-pgqxf -n python sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # vi /etc/nginx/conf.d/default.conf
/ # nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
/ # nginx -s reload
登录浏览器测试
至此环境准备完成。
测试 让linux namespace下的nginx代理python namespace下的tomcat
修改linux namespace下的nginx后端指向python namespace的tomcat
登录测试
可以看到默认规则 跨namespace通信是不受限制的。
case1 ingress-以pod为限制单位、只允同namespace含有特定标签的源pod访问目标pod的所有端口:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case1-ingress-podSelector.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tomcat-access--networkpolicy
namespace: python
spec:
policyTypes:
- Ingress
podSelector:
matchLabels:
app: python-tomcat-app1-selector #对匹配到的目的Pod应用以下规则
ingress: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
- from:
- podSelector:
matchLabels:
app: python-nginx-selector #如果存在多个matchLabel条件,如果存在多个matchLabel条件,是and的关系,即要同时满足条件A、条件B、条件X 符合该app的pod可以通信
#project: "python"
进入python namespace下含有app标签的的nginx 测试连接后端 可以看到连接成功
进入python namespace下不含app标签的的nginx 测试连接后端 可以看到连接失败
注意
1.不允许从其它namespace访问目标pod,即默认禁止了跨ns访问目标pod。
2.非明确允许的pod,同namespace 也无法访问
3.不允许从宿主机访问目标pod。
4.该策略只允许同namespace含有特定标签的源pod访问目标pod,比如tomcat只允许了有特定标签的源pod nginx访问。
5.该策略不影响其它namespace的pod内部之间的相互访问,即linux的pod与linux的pod访问正常。
6.该策略不影响各namespace的pod与非明确禁止的pod之间的访问,即linux的pod访问python的其它pod也正常。
case2: ingress-以pod加端口为限制单位、只允同namespace含有特定标签的源pod访问目标pod的指定端口:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case2-ingress-podSelector-ns-SinglePort.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tomcat-access--networkpolicy
namespace: python
spec:
policyTypes:
- Ingress
podSelector:
matchLabels:
app: python-tomcat-app1-selector
ingress:
- from:
- podSelector:
matchLabels:
#app: python-nginx-selector #指定访问源的匹配条件,如果存在多个matchLabel条件,是and的关系,即要同时满足条件A、条件B、条件X
project: "python"
ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
- protocol: TCP
port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
#port: 80
通过同namespace下含有python标签的nginx测试 可以访问 ;将上面port的8080改成80后,无法访问
case3 ingress-允许同namespace的所有pod访问当前namespace的目标pod多个指定端口:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case3-ingress-podSelector-ns-MultiPort.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tomcat-access-networkpolicy
namespace: python
spec:
policyTypes:
- Ingress
podSelector: #目标pod
matchLabels:
app: python-tomcat-app1-selector
ingress:
- from:
- podSelector: #匹配源pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
matchLabels: {}
ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
- protocol: TCP
port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
#port: 80
- protocol: TCP
port: 3306
- protocol: TCP
port: 6379
与case2同理 该策略允许访问python-tomcat-app1-selector标签pod的8080 3306 6379端口
注意
1跨namespace禁止访问
linux ns的pod访问不了python ns中的pod
2.同namespace的其它pod都可以访问目的pod的指定目标端口(含多目标端口)
case4: ingress-允许同namespace的所有pod访问当前namespace的目标pod所有端口:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case4-ingress-podSelector-ns.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tomcat-access--networkpolicy
namespace: python
spec:
policyTypes:
- Ingress
podSelector: #目标pod
matchLabels: {} #匹配所有目标pod
ingress:
- from:
- podSelector: #匹配源pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
matchLabels: {}
注意
1.其它namespace无法访问目标ns的pod。
2.同namespace的pod可以访问当前namespace中的所有pod的任意端口。
生产环境中该规则使用较多
case5 ingress-ipBlock白名单:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case5-ingress-ipBlock.yaml.bak
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tomcat-access--networkpolicy
namespace: python
spec:
policyTypes:
- Ingress
podSelector: #目标pod
matchLabels:
app: python-tomcat-app1-selector
ingress:
- from:
- ipBlock:
cidr: 10.200.0.0/16 #白名单,允许访问的地址范围,没有允许的将禁止访问目标pod
except:
- 10.200.229.0/24 #在以上范围内禁止访问的源IP地址
- 10.200.110.6/32 #在以上范围内禁止访问的源IP地址
ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
- protocol: TCP
port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
#port: 80
- protocol: TCP
port: 3306
- protocol: TCP
port: 6379
将 python namespace下nginx的pod所在的ip10.200.110.6禁用后,他便无法连通目标pod了
而linux namespace下的nginx可以访问 因为没有设置本namespace才能访问的规则
case6:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case6-ingress-namespaceSelector.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tomcat-access--networkpolicy
namespace: python
spec:
policyTypes:
- Ingress
podSelector: #目标pod
matchLabels: {} #允许访问python namespace 中的所有pod
ingress:
- from:
- namespaceSelector:
matchLabels:
nsname: linux #只允许指定的namespace访问
- namespaceSelector:
matchLabels:
nsname: python #只允许指定的namespace访问
ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
- protocol: TCP
port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
#port: 80
- protocol: TCP
port: 3306
- protocol: TCP
port: 6379
注意
1.被明确允许的namespace中的pod可以访问目标pod
2.没有明确声明允许的namespace将禁止访问
3.没有明确声明允许的话,即使同一个namespace也禁止访问
4.比如只允许了linux和python两个ns,那么default中的pod将无法访问。
测试linux和default两个namespace中nginx对目标pod的访问
case7: Egress-podSelector-Pod出口方向目的IP及目的端口限制-只允许访问指定的目的地址范围及端口:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case7-Egress-ipBlock.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-access-networkpolicy
namespace: python
spec:
policyTypes:
- Egress
podSelector: #目标pod选择器
matchLabels: #基于label匹配目标pod
app: python-tomcat-app1-selector #匹配python namespace中app的值为python-tomcat-app1-selector的pod,然后基于egress中的指定网络策略进行出口方向的网络限制
egress:
- to:
- ipBlock:
cidr: 10.200.0.0/16 #允许匹配到的pod出口访问的目的CIDR地址范围
- ipBlock:
cidr: 192.168.110.206/32 #允许匹配到的pod出口访问的目的主机
# ports:
# - protocol: TCP
# port: 80 #允许匹配到的pod访问目的端口为80的访问
# - protocol: TCP
# port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
# - protocol: UDP
# port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
进入pythonnamespace下 app: python-tomcat-app1-selector的 tomcat的pod中 ping 192.168.110.207 未加规则时可以ping通 加规则后无法ping通
ping206可以ping通,因为规则已放开
case8: Egress-podSelector-Pod出口方向目的Pod限制-只允许访问指定的pod及端口:
root@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case8-Egress-PodSelector.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-access-networkpolicy
namespace: python
spec:
policyTypes:
- Egress
podSelector: #目标pod选择器
matchLabels: #基于label匹配目标pod
app: python-nginx-selector #匹配python namespace中app的值为python-tomcat-app1-selector的pod,然后基于egress中的指定网络策略进行出口方向的网络限制
egress:
- to:
- podSelector: #匹配pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
matchLabels:
app: python-tomcat-app1-selector
ports:
- protocol: TCP
port: 8080 #允许80端口的访问
- protocol: TCP
port: 53 #允许DNS的解析
- protocol: UDP
port: 53
1.匹配成功的源pod只能访问指定的目的pod的指定端口
2.其它没有允许的出口请求将禁止访问
上面规则使含有app: python-nginx-selector的pod只能访问app: python-tomcat-app1-selector的pod 其他均无法访问
其他pod则不受限制
case9 Egress-namespaceSelector:
oot@192:/usr/local/src/20230611/NetWorkPolicy-case/python-ns2# cat case9-Egress-namespaceSelector.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-access-networkpolicy
namespace: python
spec:
policyTypes:
- Egress
podSelector: #目标pod选择器
matchLabels: #基于label匹配目标pod
app: python-nginx-selector #匹配python namespace中app的值为python-tomcat-app1-selector的pod,然后基于egress中的指定网络策略进行出口方向的网络限制
egress:
- to:
- namespaceSelector:
matchLabels:
nsname: python #指定允许访问的目的namespace
- namespaceSelector:
matchLabels:
nsname: linux #指定允许访问的目的namespace
# ports:
# - protocol: TCP
# port: 8080 #允许80端口的访问
# - protocol: TCP
# port: 53 #允许DNS的解析
# - protocol: UDP
# port: 53
限制匹配成功的pod没有访问指定的namespace
1.匹配成功的源pod可以访问指定的目标namespace。
2.不能访问除指定的namespace以外的其它namespace及外网。
3.比如允许指定的源pod访问linux和python ns中的8080、3306、6379等端口,但是其它ns无法访问
Ingress
Ingress简介
Ingress 公开从集群外部到集群内服务的HTTP和HTTPS 路由。 流量路由由Ingress资源上定义的规则控制。
下面是一个将所有流量都发送到同一Service的简单Ingress示例:
Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及基于名称的虚拟托管。 Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。
Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service
Ingress-daemonset配置文件
root@192:/usr/local/src/20230611/ingress-case-20230611-backup/1.1-ingress-nginx-1.3.0_deploy-yaml# cat 2.ingress-nginx-controller-v1.3.0_daemonset.yaml
apiVersion: v1
kind: Namespace
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
name: ingress-nginx
---
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx
namespace: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx
namespace: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resourceNames:
- ingress-controller-leader
resources:
- configmaps
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- coordination.k8s.io
resourceNames:
- ingress-controller-leader
resources:
- leases
verbs:
- get
- update
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission
namespace: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
- namespaces
verbs:
- list
- watch
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- get
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
---
apiVersion: v1
data:
allow-snippet-annotations: "true"
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-controller
namespace: ingress-nginx
#---
#apiVersion: v1
#kind: Service
#metadata:
# labels:
# app.kubernetes.io/component: controller
# app.kubernetes.io/instance: ingress-nginx
# app.kubernetes.io/name: ingress-nginx
# app.kubernetes.io/part-of: ingress-nginx
# app.kubernetes.io/version: 1.3.0
# name: ingress-nginx-controller
# namespace: ingress-nginx
#spec:
# ipFamilies:
# - IPv4
# ipFamilyPolicy: SingleStack
# ports:
# - appProtocol: http
# name: http
# port: 80
# protocol: TCP
# targetPort: http
# nodePort: 50080
# - appProtocol: http #kubernetes v1.20 stable,appProtocol字段提供了一种为每个Service端口指定应用协议的方式,此字段的取值会被映射到对应的Endpoints
# name: prometheus-metrics-port
# port: 10254
# protocol: TCP
# targetPort: 10254 #ingress-nginx-controller内置的指标数据采集端口
# nodePort: 61254
## - name: metrics-port
## port: 10254
## targetPort: 10254
## nodePort: 50254
## protocol: TCP
# - appProtocol: https
# name: https
# port: 443
# protocol: TCP
# targetPort: https
# nodePort: 50443
# selector:
# app.kubernetes.io/component: controller
# app.kubernetes.io/instance: ingress-nginx
# app.kubernetes.io/name: ingress-nginx
# type: NodePort
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-controller-admission
namespace: ingress-nginx
spec:
ports:
- appProtocol: https
name: https-webhook
port: 443
targetPort: webhook
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: ClusterIP
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
minReadySeconds: 0
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
spec:
hostNetwork: true #使用宿主机网络
hostPID: true #使用宿主机Pid
containers:
- args:
- /nginx-ingress-controller
- --election-id=ingress-controller-leader
- --controller-class=k8s.io/ingress-nginx
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/ingress-nginx-controller:v1.3.0
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: controller
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
- containerPort: 8443
name: webhook
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 100m
memory: 90Mi
securityContext:
allowPrivilegeEscalation: true
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
runAsUser: 101
volumeMounts:
- mountPath: /usr/local/certificates/
name: webhook-cert
readOnly: true
dnsPolicy: ClusterFirst
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission-create
namespace: ingress-nginx
spec:
template:
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission-create
spec:
containers:
- args:
- create
- --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
- --namespace=$(POD_NAMESPACE)
- --secret-name=ingress-nginx-admission
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kube-webhook-certgen:v1.3.0
imagePullPolicy: IfNotPresent
name: create
securityContext:
allowPrivilegeEscalation: false
nodeSelector:
kubernetes.io/os: linux
restartPolicy: OnFailure
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
serviceAccountName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission-patch
namespace: ingress-nginx
spec:
template:
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission-patch
spec:
containers:
- args:
- patch
- --webhook-name=ingress-nginx-admission
- --namespace=$(POD_NAMESPACE)
- --patch-mutating=false
- --secret-name=ingress-nginx-admission
- --patch-failure-policy=Fail
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kube-webhook-certgen:v1.3.0
imagePullPolicy: IfNotPresent
name: patch
securityContext:
allowPrivilegeEscalation: false
nodeSelector:
kubernetes.io/os: linux
restartPolicy: OnFailure
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
serviceAccountName: ingress-nginx-admission
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: nginx
spec:
controller: k8s.io/ingress-nginx
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.3.0
name: ingress-nginx-admission
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: ingress-nginx-controller-admission
namespace: ingress-nginx
path: /networking/v1/ingresses
failurePolicy: Fail
matchPolicy: Equivalent
name: validate.nginx.ingress.kubernetes.io
rules:
- apiGroups:
- networking.k8s.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- ingresses
sideEffects: None
配置负载均衡器
测试可以登录 无数据
配置nginx配置文件指定ingress规则
创建两个后端服务tomcat
root@192:/usr/local/src/20230611/ingress-case-20230611-backup# cat tomcat-app1.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app1-deployment-label
name: magedu-tomcat-app1-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app1-selector
template:
metadata:
labels:
app: magedu-tomcat-app1-selector
spec:
containers:
- name: magedu-tomcat-app1-container
image: tomcat:7.0.94-alpine
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 1
memory: "512Mi"
requests:
cpu: 500m
memory: "512Mi"
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-tomcat-app1-service-label
name: magedu-tomcat-app1-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 40003
selector:
app: magedu-tomcat-app1-selector
root@192:/usr/local/src/20230611/ingress-case-20230611-backup# cat tomcat-app2.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 1
memory: "512Mi"
requests:
cpu: 500m
memory: "512Mi"
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-tomcat-app2-service-label
name: magedu-tomcat-app2-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 40004
selector:
app: magedu-tomcat-app2-selector
进入tomcat1-pod 添加测试页面
进入tomcat2-pod 添加测试页面
将tomcat-pod1 和 pod2 service方式改为ClusterIP 取消端口 准备利用ingress转发访问
创建单主机ingress规则
root@192:/usr/local/src/20230611/ingress-case-20230611-backup# cat 2.1.ingress_single-mobile.yaml
#apiVersion: networking.k8s.io/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mobile.jiege.com
namespace: magedu
annotations:
kubernetes.io/ingress.class: "nginx" ##指定Ingress Controller的类型
nginx.ingress.kubernetes.io/use-regex: "true" ##指定后面rules定义的path可以使用正则表达式
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" ##连接超时时间,默认为5s
nginx.ingress.kubernetes.io/proxy-send-timeout: "600" ##后端服务器回转数据超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-read-timeout: "600" ##后端服务器响应超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-body-size: "50m" ##客户端上传文件,最大大小,默认为20m
#nginx.ingress.kubernetes.io/rewrite-target: / ##URL重写
nginx.ingress.kubernetes.io/app-root: /index.html
#spec:
# rules: #路由规则
# - host: www.jiege.com ##客户端访问的host域名
# http:
# paths:
# - path:
# backend:
# serviceName: magedu-nginx-service #转发至哪个service
# servicePort: 80 ##转发至service的端口号
spec:
rules:
- host: mobile.jiege.com
http:
paths:
- pathType: Prefix
path: "/" ##类似nginx location
backend:
service:
name: magedu-tomcat-app2-service
port:
number: 80
宿主机配置域名解析
/etc/hosts
192.168.110.242 mobile.jiege.com
测试登陆成功
创建多域名ingress规则
root@192:/usr/local/src/20230611/ingress-case-20230611-backup# cat 2.2.ingress_multi-host.yaml
#apiVersion: networking.k8s.io/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-web
namespace: magedu
annotations:
kubernetes.io/ingress.class: "nginx" ##指定Ingress Controller的类型
nginx.ingress.kubernetes.io/use-regex: "true" ##指定后面rules定义的path可以使用正则表达式
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" ##连接超时时间,默认为5s
nginx.ingress.kubernetes.io/proxy-send-timeout: "600" ##后端服务器回转数据超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-read-timeout: "600" ##后端服务器响应超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-body-size: "10m" ##客户端上传文件,最大大小,默认为20m
#nginx.ingress.kubernetes.io/rewrite-target: / ##URL重写
nginx.ingress.kubernetes.io/app-root: /index.html
spec:
rules:
- host: www.jiege.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: magedu-tomcat-app1-service
port:
number: 80
- host: mobile.jiege.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: magedu-tomcat-app2-service
port:
number: 80
如图 rules下:使用多个规则可以配置多条代理。
同域名不同url的ingress规则
root@192:/usr/local/src/20230611/ingress-case-20230611-backup# cat 3.1.ingress-url.yaml
#apiVersion: networking.k8s.io/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-web
namespace: magedu
annotations:
kubernetes.io/ingress.class: "nginx" ##指定Ingress Controller的类型
nginx.ingress.kubernetes.io/use-regex: "true" ##指定后面rules定义的path可以使用正则表达式
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" ##连接超时时间,默认为5s
nginx.ingress.kubernetes.io/proxy-send-timeout: "600" ##后端服务器回转数据超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-read-timeout: "600" ##后端服务器响应超时时间,默认为60s
nginx.ingress.kubernetes.io/proxy-body-size: "10m" ##客户端上传文件,最大大小,默认为20m
#nginx.ingress.kubernetes.io/rewrite-target: / ##URL重写
nginx.ingress.kubernetes.io/app-root: /index.html
spec:
rules:
# - host: www.jiege.com
# http:
# paths:
# - path: /magedu
# backend:
# serviceName: magedu-tomcat-app1-service
# servicePort: 80
# - path: /magedu2
# backend:
# serviceName: magedu-tomcat-app2-service
# servicePort: 80
- host: www.jiege.com
http:
paths:
- pathType: Prefix
path: "/app1"
backend:
service:
name: magedu-tomcat-app1-service
port:
number: 80
- pathType: Prefix
path: "/app2"
backend:
service:
name: magedu-tomcat-app2-service
port:
number: 80
https的ingress规则
生成证书
mkdir certs
cd certs
创建证书
certs# openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3560 -nodes -subj '/CN=www.jiegeca.com'
certs# openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=www.jiege.com'
certs# openssl x509 -req -sha256 -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
证书上传至k8s:
kubectl create secret tls tls-secret-www --cert=server.crt --key=server.key -n magedu #第一种方法通过文件直接创建
kubectl create secret tls tls-secret-mobile --cert=server2022.crt --key=server2022.key -n magedu #等于第一个方法,
kubectl create secret generic tls-secret --from-file=tls.crt=server.crt --from-file=tls.key=server.key -n magedu #第二种方法
ingress规则配置
root@192:/usr/local/src/20230611/ingress-case-20230611-backup# cat 4.1.ingress-https-magedu_single-host.yaml
#apiVersion: networking.k8s.io/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-web
namespace: magedu
annotations:
kubernetes.io/ingress.class: "nginx" ##指定Ingress Controller的类型
nginx.ingress.kubernetes.io/ssl-redirect: 'true' #SSL重定向,即将http请求强制重定向至https,等于nginx中的全站https
spec:
tls:
- hosts:
- www.jiege.com ##指定的域名
secretName: tls-secret-www ##指定的证书
# rules:
# - host: www.jiege.com
# http:
# paths:
# - path: /
# backend:
# serviceName: magedu-tomcat-app1-service
# servicePort: 80
rules:
- host: www.jiege.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: magedu-tomcat-app1-service
port:
number: 80
服务器添加host解析,curl测试
多域名https ingress规则
创建添加mobile域名证书
多域名:
# openssl req -new -newkey rsa:4096 -keyout mobile.key -out mobile.csr -nodes -subj '/CN=mobile.jiege.com' #域名要和ingress配置文件中对应
# openssl x509 -req -sha256 -days 3650 -in mobile.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out mobile.crt
# kubectl create secret tls tls-secret-mobile --cert=mobile.crt --key=mobile.key -n magedu
ingress配置文件
root@192:/usr/local/src/20230611/ingress-case-20230611-backup# cat 4.2.ingress-https-magedu_multi-host.yaml
#apiVersion: networking.k8s.io/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-web-mobile
namespace: magedu
annotations:
kubernetes.io/ingress.class: "nginx" ##指定Ingress Controller的类型
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
tls:
- hosts:
- mobile.jiege.com
secretName: tls-secret-mobile
- hosts:
- www.jiege.com
secretName: tls-secret-www
rules:
- host: www.jiege.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: magedu-tomcat-app1-service
port:
number: 80
- host: mobile.jiege.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: magedu-tomcat-app2-service
port:
number: 80
登录测试
ingress证书更新
#更新证书
kubectl edit secrets tls-secret -n magedu
将新证书base64加密后添加进去替换原crt 即可替换证书。
标签:ingress,name,kubernetes,--,app,nginx,io,组件,k8s From: https://www.cnblogs.com/zhaoxiangyu-blog/p/17526429.html