袁党生博客

  • 主页
  • linux基础
  • SHELL
  • WEB
  • 负载
  • 企业级应用
  • 数据库
  • KVM
  • Docker
  • K8S
  • 监控
  • 存储
  • 博客搭建问题
  1. 首页
  2. K8S
  3. 正文

十六、kubernetes网络组件

2023年8月30日 2132点热度 0人点赞 0条评论


本章概述

  • kubernetes网络组件flannel
  • kubernetes网络组件calico
  • kubernetes NetworkPolicy(网络策略)
  • 通过网络策略限制通信案例

16.1 kubernetes网络组件flannel

官网:https://coreos.com/flannel/docs/latest/
文档:https://coreos.com/flannel/docs/latest/kubernetes.html
  由CoreOS开源的针对k8s的网络服务,其目的为解决k8s集群中各主机上的pod相互通信的问题,其借助于etcd维护网络IP地址分配,并为每一个node服务器分配一个不同的IP地址段。(注意:k8s集群使用flannel组件,每个node节点的网段必须不同)

Flannel 网络模型 (backend后端)

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节点本身必须处于同一个局域网(二层网络)中,因此不适用于网络变动频繁或比较大型的网络环境,但是其性能较好。

  公有云不支持BGP协议,无法建立路由表,使用flannel网络模型,无法使用calico
  私有云常用calico网络模型,也可以使用flannel网络模型,此次部署的K8S集群使用的网络模型为calico+IPIP模式

Flannel 组件的解释:

    Cni0:网桥设备,每创建一个pod都会创建一对 veth pair,其中一端是pod中的eth0,另一端是Cni0网桥中的端口(网卡),Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口(网卡)上,Cni0 设备获得的ip地址是该节点分配到的网段的第一个地址。
    Flannel.1: overlay网络的设备,用来进行vxlan报文的处理(封包和解包),不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。

Flannel的系统文件及目录:

root@k8s-node2:~# find / -name flannel    #运行环境
/run/flannel
/usr/bin/flannel
/var/lib/cni/flannel

root@k8s-node2:~# cat /run/flannel/subnet.env    #子网信息
FLANNEL_NETWORK=172.31.0.0/16
FLANNEL_SUBNET=172.31.2.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

CNI信息:
注意:不要随意改动
root@k8s-node2:~# cat /var/lib/cni/flannel/a77f70994d452ea66c06f0cec194d937dacac1b69c07d31b478f844f216e84c7
{"hairpinMode":true,"ipMasq":false,"ipam":{"routes":[{"dst":"172.31.0.0/16"}],"subnet":"172.31.2.0/24","type":"host-local"},"isDefaultGateway":true,"isGateway":true,"mtu":1450,"name":"cbr0","type":"bridge"}

路由表:
root@k8s-node2:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.7.254 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
172.31.0.0 172.31.0.0 255.255.255.0 UG 0 0 0 flannel.1
172.31.1.0 172.31.1.0 255.255.255.0 UG 0 0 0 flannel.1
172.31.2.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
172.31.3.0 172.31.3.0 255.255.255.0 UG 0 0 0 flannel.1
192.168.0.0 0.0.0.0 255.255.248.0 U 0 0 0 eth0

查看当前集群flannel配置文件
注意:不要随意改动
kubectl edit configmap kube-flannel-cfg -n kube-system
如果在公有云使用flannel vxlan网络模型,会监听8472端口,因此安全组要开启8472端口

下面截图中,8472端口的进程显示为”-”,这是因为8472端口是内核打开的UDP端口,由内核进行监听,并不是由某个服务进程在监听,用来封装和解封装报文。

Flannel VXLAN架构图

1、flannel网络模型的k8s集群每创建一个容器就会创建一个虚拟网卡,该网卡是一对,一端在网桥cni0上(即vethxxxxxxxx),另一端在容器内(即eth0)。因此每个容器内的eth0都会在宿主机网桥cni0都存在一个对应的虚拟网卡vethxxxxxxxx。
2、如果两个容器在同一个node上,可以直接通过网桥cni0基于mac地址进行转发
3、如果两个容器在不同的node上,请求报文经过虚拟网卡vethxxxxxxxx转发给网桥cni0
4、cni0将报文转发给flannel.1,此时内核将报文进行封装,然后转发给宿主机eth0,由eth0转发出去
5、另一个node通过宿主机eth0接收到报文后,内核将报文解封装,经过flannel.1--cni0--vethxxxxxxxx,最终将报文转发给对应的容器。

报文转发过程:

pod(eh0)-->网桥虚拟网卡vethxx-->cni0-flannel.1-->vxlan(内核封装overlay)-eth0(源宿主机,源端口为UDP 随机端口,目的端口为目的主机UDP 8472) -->对端主机eth0(UDP 8472) -->flannel.1-->cni0-->网桥虚拟网卡vethxx-->eth0(pod)
    cni0是网桥,类似于二层设备,用于同一个node上不同容器之间进行通讯
    flannel.1,用于封装vxlan报文,实现不同node之间的报文转发
    Flannel vlxan网络模型下的k8s集群内不同node上容器之间通信,是通过封装三层报文,修改二层mac地址实现不同node之间的容器通信。

如何获取到每个node节点上网卡的mac地址信息:
node在加入集群时,会在etcd进行注册,可以从etcd获取每个node的mac地址信息

16.2 kubernetes网络组件calico

calico官网:http://www.projectcalico.org
  calico是一个纯三层的网络解决方案,为容器提供多node间的访问通信,calico将每一个node节点都当做一个路由器(router),各节点通过BGP(Broder Gateway Protocol)边界路由协议学习并在node节点生成路由规则,从而将不同node上的pod链接起来进行通信。
查看calico网络模型下的路由表:
calicoctl node status #在master1节点172.31.7.101上查看路由表

可以看到master节点上有去其他任何一个主机的路由
calico简介:
  calico网络通过3层路由技术(如静态路由或BGP路由分配)或2层地址学习来感知工作负载IP地址,它们可以将未封装的流量路由到作为最终目的地的端点主机。因此可以在工作负载之间发送流程,而无需底层网络知道工作负载IP地址。但是,并非所有网络都能够路由工作负载IP地址,例如:公有云环境、跨VPC子网编辑的AWS以及无法通过BGP、calico对应到underlay网络或无法轻松配置静态路由的其他场景。
calico封装类型:
  calico支持两种类型的封装:VXLAN和IP-in-IP,VXLAN支持在没有IP的某些环境中使用(例如公有云环境),VXLAN的数据报头较大,因此开销相对较高。这两种封装之间的差异是calico的VXLAN实现不使用BGP,而calico的IP-in-IP是在calico节点之间使用BGP协议实现跨子网。
  BGP是一个去中心化的协议,它通过自动学习和维护路由表实现网络的可用性,但并不是所有网络都支持BGP。为了实现更大规模的跨网络管理,calico还支持IP-in-IP的叠加模型,简称IPIP,IPIP可以实现跨不同网段建立路由通信,但是会存在安全性问题,其在内核内置可以通过calico的配置文件设置是否启用IPIP,在公司内部如果K8S的node节点没有跨网段,建议关闭IPIP。
  IPIP是一种将各node的路由之间做一个tunnel隧道,再把两个网络连接起来的模式。启用IPIP模式时,calico将在各node上创建一个名为“tunl0”的虚拟网络接口。

  BGP模式则直接使用物理机作为虚拟路由器,不载创建额外的tunnel。(即使用IPIP,需要开启IPIP模式,会创建tunnel)
calico核心组件:
  Felix:calico的agent,是daemonset容器,运行在每一台node节点上,其主要是维护路由规则,会报当前节点状态以确保pod的跨主机通信。
  BGP client:每台node都运行,其主要负责监听node节点上有felix生成的路由信息,然后通过BGP协议广播至其他剩余的node节点,从而相互学习路由实现pod通信
  Route Reflector:集中式的路由反射器,calico v3.3开始支持,当calico BGP客户端将路由从其FIB(Forward Information dataBase,转发信息库)通过到Route Reflector时,Route Reflector会将这些路由通告给部署集群中的其他节点,Route Reflector专门用于管理BGP网络路由规则,不会产生pod数据通信。该组件不是必需的,而且是单点,启用后一旦出现问题,k8s集群内的node节点之间将无法通信,因此一般不会启用该组件。
架构图:

如何修改集群网络模式:
vim /etc/kubeasz/clusters/k8s-cluster1/hosts

如果将网络模型更改为flannel,则还需要调整文件/etc/kubeasz/roles/flannel/templates/kube-flannel.yaml.j2

如何关闭IPIP模式:
vim /etc/kubeasz/clusters/k8s-cluster1/ config.yml
CALICO_IPV4POOL_IPIP: "Always" #always开启IPIP模式,可以跨子网访问;off关闭IPIP模式

calico存在CrossSubnet模式,即node节点跨子网开启IPIP模式后,如果node节点不跨子网就使用直接路由,不开启IPIP
部署方式参考链接有道云笔记:https://note.youdao.com/ynoteshare/index.html?id=9d9bb8c33aa7a196ec4f024fe484cb78&type=note&_time=1654409523318

calico部署过程参考官网文档:https://projectcalico.docs.tigera.io/getting-started/
也可以通过calico官网提供的yaml文件进行部署,yaml文件链接:https://projectcalico.docs.tigera.io/manifests/calico.yaml

报文访问转发流程:

1、容器将报文转发给虚拟网卡calixxx
2、虚拟网卡calixxx将报文转发给tun0
3、tun0直接将该报文转发给eth0
4、由于是calico IPIP网络模型,node直到目标主机路由,将报文转发给目标node的eth0
5、目标主机eth0接收报文,将报文转发给tun0,再转发给calixxx,然后转发给容器的eth0

报文转发过程:
eth0(容器)-->cali71be67429f9-->tun0(直接转发) -->eth0(IPinIP,源主机) -->eth0(目的主机) -->tun0-->calid941116c5b6-->eth0(容器)

16.3 kubernetes NetworkPolicy(网络策略)

官网链接:https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
基于NetworkPolicy在三层(网络层)或四层(传输层)控制拒绝或允许请求流量。
  允许或拒绝特定的pod请求目的namespace中的目的pod的所有或指定端口。
  允许或拒绝特定的namespace请求目的namespace中的所有或特定的pod所有或指定端口。
  允许或拒绝特定的源IP范围或IP地址请求目的pod的所有或特定端口。

环境准备:

1.kubernetes 1.23.5,calico网络组件, 2个node节点或以上。
2.两个namespace,linux和python,分别代表不同项目的Pod。
3.每个namespace 运行多个pod,且pod可以运行在不同的node主机。
4.测试环境为每个namespace分别运行一个nginx和一个tomcat pod,用于测试不同主机的Pod运行在同一个ns的场景、以及跨ns的访问通信及访问限制。

为了能够便于在演示时查看iptables规则,将当前集群三个node节点的网络模式由ipvs更改为iptables
vim /var/lib/kube-proxy/kube-proxy-config.yaml

kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
clientConnection:
  kubeconfig: "/etc/kubernetes/kube-proxy.kubeconfig"
clusterCIDR: "10.200.0.0/16"
conntrack:
  maxPerCore: 32768
  min: 131072
  tcpCloseWaitTimeout: 1h0m0s
  tcpEstablishedTimeout: 24h0m0s
healthzBindAddress: 0.0.0.0:10256
hostnameOverride: "172.31.7.111"
metricsBindAddress: 0.0.0.0:10249
mode: "iptables"          #由ipvs模式修改为iptables模式

修改完成后重启node节点,使配置生效

16.3.1 环境准备

1、创建namespace
kubectl create ns linux
kubectl create ns python
2、给namespace打标签,对namespace基于网络策略进行限制,用label来匹配namespace
kubectl label ns linux nsname=linux
kubectl label ns python nsname=python

16.3.2 linux namespace下nginx转发tomcat

linux ns部署nginx和tomcat,并让nginx可以将来自于/app的请求转发至当前namespace的tomcat pod。
1、创建linux namespace下的tomcat容器
(1)编辑tomcat yaml文件:
vim linux-tomcat.yaml

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"

---
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

(2)创建tomcat容器
kubectl apply -f linux-tomcat.yaml
(3)进入tomcat容器,为tomcat添加访问页面
kubectl exec -it xxx bash

cd /usr/local/tomcat/webapp
mkdir app
echo "<h1>linux app test webpage<h1>" > app/index.html

2、创建linux namespace下的nginx容器
(1)编写yaml文件
vim linux-nginx.yaml

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"

---
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

(2)创建nginx容器
kubectl apply -f linux-nginx.yaml
(3)进入nginx容器,修改nginx配置文件,将动态请求转发给tomcat

vim /etc/nginx/conf.d/default.conf        #在server{}配置中添加以下配置,将访问/app的请求转发给当前namespace后端tomcat(这里写tomcat service全称,tomcat service会将请求转发给后端tomcat)

    location /app {
        proxy_pass http://linux-tomcat-app1-service.linux.svc.magedu.local;
}

(4)重新加载nginx配置文件
nginx -s reload
3、访问验证:
浏览器访问172.31.7.112:30008/app(nginx容器在172.31.7.112上)
通过访问nginx的/app,nginx将请求转发给tomcat,获取tomcat测试页内容,可以看到返回的是linux namespace下tomcat的测试页面结果

16.3.3 python namespace下nginx转发tomcat

python ns部署nginx和tomcat,并让nginx可以将来自于/app的请求转发至当前namespace的tomcat pod。
1、创建python namespace下的tomcat容器:
(1)编写yaml文件
vim python-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: 172.31.7.113          #为了便于演示效果,指定tomcat容器部署的node节点
      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"

---
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

(2)创建tomcat容器
kubectl apply -f python-tomcat.yaml
(3)创建tomcat容器
kubectl apply -f linux-tomcat.yaml
(4)进入tomcat容器,为tomcat添加访问页面
kubectl exec -it xxx bash

cd /usr/local/tomcat/webapp
mkdir app
echo "<h1>linux app test webpage<h1>" > app/index.html

2、创建python namespace下的nginx容器:
(1)编写yaml文件
vim python-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"

---
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的一个标签

(2)创建nginx容器
kubectl apply -f python-nginx.yaml
(3)进入nginx容器,修改nginx配置文件,将动态请求转发给tomcat

vim /etc/nginx/conf.d/default.conf        #在server{}配置中添加以下配置,将访问/app的请求转发给当前namespace后端tomcat(这里写tomcat service全称,tomcat service会将请求转发给后端tomcat)
    location /app {
        proxy_pass http://python-tomcat-app1-service.python.svc.magedu.local; 
}

重新加载nginx配置文件
nginx -s reload
3、访问验证:
浏览器访问:172.31.7.111:30014/app/index.jsp(nginx容器再172.31.7.111上)
通过访问nginx的/app,nginx将请求转发给tomcat,获取tomcat测试页内容,返回的是python namespace下tomcat的测试页面结果

16.3.4 不同namespace下nginx访问tomcat

验证:linux namespace下的nginx是否可以将请求转发给python namespace下的tomcat
1、修改linux namespace下的nginx配置文件
(1)进入linux namespace下的nginx容器,修改配置文件

vim /etc/nginx/conf.d/default.conf        #在server{}配置中添加以下配置,将访问linux namespace下/app的请求转发给python namespace后端tomcat(这里写tomcat service全称,tomcat service会将请求转发给后端tomcat)
    location /app {
        proxy_pass http://python-tomcat-app1-service.python.svc.magedu.local;
}

(2)重新加载nginx配置文件
nginx -s reload
2、访问验证:
浏览器访问:172.31.7.112:30008/app/index.jsp(linux namespace下的nginx容器在172.31.7.112上)
通过访问nginx的/app,nginx将请求转发给tomcat,获取tomcat测试页内容,可以看到,访问linux namespace下的nginx地址,返回的是python namespace下tomcat的测试页面结果,说明不同的namespace下的容器可以相互通信。

不同namespace下的容器可以相互通信,这是不安全的。因此,我们可以通过网络策略来限制不同namespace下的pod进行通信
在default、linux、python三个namespace手动创建测试容器,用来测试
kubectl run net-test-centos-pod1 --image=centos:7.9.2009 sleep 10000000 -n linux
kubectl run net-test-centos-pod1 --image=centos:7.9.2009 sleep 10000000 -n python
kubectl run net-test-centos-pod1 --image=centos:7.9.2009 sleep 10000000

16.4 通过网络策略限制通信案例

16.4.1 示例1:ingress-以pod为限制单位、只允同namespace含有特定标签的源pod访问目标pod的所有端口

ingress:对入口流量进行限制,针对目标pod进行限制
1、网络策略:
(1)只允许当前namespace的pod之间互相访问,禁止跨namespace的访问,其他namespace无法访问当前namespace
(2)只允许当前namespace中含有特定标签的pod访问目标pod,不带标签即使在同一个namespace也无法访问
(3)不允许从宿主机访问目标pod
示例:
(1)编写yaml文件
vim case1-ingress-podSelector.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy    #指定网络策略名称
  namespace: python  #指定网络策略所在的namespace,必须和目标pod在同一namespace
spec:
  policyTypes:
  - Ingress      #对入口流量进行限制
  podSelector:
    matchLabels:
      app: python-tomcat-app1-selector   #指定目标pod标签,对匹配到的目的Pod应用以下规则
  ingress: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
  - from:
    - podSelector:
        matchLabels:
          #app: python-nginx-selector #如果存在多个matchLabel条件,如果存在多个matchLabel条件,是and的关系,即要同时满足条件A、条件B、条件X
          project: "pythonxx"         #指定匹配的namespace为pythonxx

yaml文件指定规则为:允许python namespace下标签为project:python的源pod访问目标pod,其他pod均拒绝
(2)创建网络策略
kubectl apply -f case1-ingress-podSelector.yaml
(3)查看网络策略
kubectl get networkpolicies -n python
kubectl describe networkpolicies tomcat-access--networkpolicy -n python

2、验证:
(1)在其他主机172.31.7.109上访问python namespace下的tomcat服务。
注意:这里要访问的目标pod为tomcat,而源pod则是nginx,因此要检测nginx容器是否满足网络策略的限制,nginx容器的标签为python,网络策略中限制的是pythonxx,因此nginx容器无法将请求转发给tomcat容器

(2)在同一个namespace下的其他不带pythonxx标签的pod访问tomcat
获取tomcat地址和pod名称

进入同namespace下的测试容器进行curl测试,同样无法访问,这是calico拒绝访问

(3)查看calico规则
由于目标pod在172.31.7.113上,因此需要在pod所在宿主机172.31.7.113上查看calico规则
calicoctl get networkpolicy -n python

calicoctl get networkpolicy -n python knp.default.tomcat-access--networkpolicy -o yaml

16.4.2 示例2:ingress-以pod加端口为限制单位、只允同namespace含有特定标签的源pod访问目标pod的指定端口

1、网络策略:
(1)只允许当前namespace的pod之间互相访问,禁止跨namespace的访问,其他namespace无法访问当前namespace
(2)只允许当前namespace中含有特定标签的pod访问目标pod,不带标签即使在同一个namespace也无法访问
(3)不允许从宿主机访问目标pod
(4)只允许指定的源pod访问同namespace目标pod的指定端口

示例:
(1)编写yaml文件
vim 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

yaml文件指定规则为:允许python namespace下标签为project:python的源pod访问目标pod,其他pod均拒绝,并且只允许访问8080端口,其他端口不允许访问
(2)创建网络策略
kubectl apply -f case2-ingress-podSelector-ns-SinglePort.yaml
此时可以正常访问tomcat容器
注意:这里要访问的目标pod为tomcat,而源pod则是nginx,因此要检测nginx容器是否满足网络策略的限制,nginx容器的标签为python,且访问tomcat的是8080端口,正好符合网络策略的限制条件。

如果将网络策略中限制的端口由8080更改为80,重新加载yaml文件
再次进行访问测试,nginx将无法访问tomcat容器,这是因为只允许80端口访问,而tomcat服务默认为8080,因此无法访问tomcat

16.4.3 示例3:ingress-允许同namespace的所有pod访问当前namespace的目标pod多个指定端口

1、网络策略:
(1)只允许当前namespace的pod之间互相访问,禁止跨namespace的访问,其他namespace无法访问当前namespace
(2)同namespace的其它pod可以访问目的pod的多个指定的端口
示例
编写yaml文件
vim 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

规则为:允许python namespace下的所有pod之间访问目标pod,但只可以访问8080/3306/6379这三个端口,禁止访问目标pod的其他端口
注意:如果不添加ports字段,则默认允许所有端口,一旦加上ports字段,则必须写明允许访问的端口,否则将无法访问目标pod的对应服务
该示例与示例2类似,只是限制了多个端口,因此这里不再举例

16.4.4 示例4:ingress-允许同namespace的所有pod访问当前namespace的目标pod所有端口

1、网络策略:
(1)只允许当前namespace的pod之间互相访问,禁止跨namespace的访问,其他namespace无法访问当前namespace
(2)不允许从宿主机访问目标pod
(3)同namespace的其它pod可以访问目的pod的任何端口
示例:
(1)编写yaml文件
vim 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: {}

yaml文件指定的规则为:允许python namespace下的所有pod之间访问目标pod的任意端口
(2)创建网络策略
kubectl apply -f case4-ingress-podSelector-ns.yaml

2、验证:
(1)在同namespace中的pod中访问tomcat,可以正常访问

(2)在其他主机172.31.7.109则不能访问tomcat(不能跨namespace,且宿主机也不能访问pod)

16.4.5 示例5:ingress-ipBlock白名单

1、网络策略:
(1)只要在白名单范围内没有被except指定禁止的源pod IP,都允许访问。
(2)在只设置了ipBlock匹配的前提下,其它namespace 中没有在except范围的pod 也可以访问目标pod,及linux ns中的pod只要不在except地址范围内,也可以访问python ns中的pod。
示例:
(1)编写yaml文件
vim case5-ingress-ipBlock.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: {}
    - ipBlock:
        cidr: 10.200.0.0/16 #白名单,允许访问的地址范围,没有允许的将禁止访问目标pod
        except:    #指定白名单中不被允许的ip地址,排除白名单中部分ip访问目标pod
        - 10.200.219.0/24 #在以上范围内禁止访问的源IP地址
        - 10.200.229.0/24 #在以上范围内禁止访问的源IP地址
        - 10.200.36.67/32 #在以上范围内禁止访问的源IP地址
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379

yaml文件指定的规则为:只要ip地址不在except访问内,任何namespace中的任意pod都可以访问目标pod的8080,3306,6379
(2)创建网络策略
kubectl apply -f case5-ingress-ipBlock.yaml

2、验证:
(1)将python namespace下的nginx包含在except范围内
查看python namespace下的nginx地址为10.200.36.67

(2)修改yaml文件(这里之贴出修改部分)

        except:    #指定白名单中不被允许的ip地址,排除白名单中部分ip访问目标pod
        - 10.200.219.0/24 #在以上范围内禁止访问的源IP地址
        - 10.200.229.0/24 #在以上范围内禁止访问的源IP地址
        - 10.200.36.67/32 #在以上范围内禁止访问的源IP地址

(3)重新加载yaml文件,然后在同namespace下的nginx容器访问tomcat容器进行测试,发现无法正常访问。这是因为nginx地址在网络策略限制范围内,因此无法访问目标pod

(4)在同namespace下测试容器进行测试,发现可以正常访问,这是因为测试容器地址不在网络策略限制范围内,因此可以正常访问

(5)删除策略,恢复正常
kubectl delete -f case5-ingress-ipBlock.yaml

16.4.6 示例6:ingress-namespace Selector-ns选择器

1、网络策略:
(1)被明确允许的namespace中的pod可以访问目标pod,没有明确声明允许的namespace将禁止访问
(2)没有明确声明允许的话,即使同一个namespace也禁止访问,比如只允许了linux和python两个ns,那么default中的pod将无法访问。
2、使用场景:
A、B两个项目有关联,允许A项目访问B项目中的容器
示例:
(1)编写yaml文件
vim 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

yaml文件指定规则为:允许linux和python这两个namespace下的pod访问目标pod的8080,3306,6379,其他pod禁止访问
(2)创建网络策略
kubectl apply -f case6-ingress-namespaceSelector.yaml

3、验证
(1)进入default namespace的测试容器,访问tomcat,发现无法访问

(2)进入python或linux namespace下的nginx,访问tomcat,可以正常访问

16.4.7 示例7:Egress-podSelector-Pod出口方向目的IP及目的端口限制-只允许访问指定的目的地址范围及端口

egress:对出口流量进行限制,针对源pod进行限制
1、网络策略:
(1)基于Egress白名单,定义ns中匹配成功的pod可以访问ipBlock指定的地址和ports指定的端口。
(2)匹配成功的pod访问未明确定义在Egress的白名单的其它IP的请求,将拒绝。
(3)没有匹配成功的源pod,主动发起的出口访问请求不受影响。
示例:
(1)编写yaml文件
vim 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: 172.31.7.106/32 #允许匹配到的pod出口访问的目的主机
    ports:
    - protocol: TCP
      port: 80 #允许匹配到的pod访问目的端口为80的访问
    - protocol: TCP
      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
    - protocol: UDP
      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析

yaml文件指定规则为:允许访问python namespace中app值为python-tomcat-app1-selector的目标pod,且该pod的地址范围为10.200.0.0/16和172.31.7.106/32,目标pod端口为TCP 的80端口,TCP和UDP的53端口
注意:如果配置Egress,对源pod的出口流量和端口进行限制,一定要开启53端口,因为53端口是K8S集群的dns使用端口,如果不开启该端口,容器将无法进行dns解析
(2)创建网络策略
kubectl apply -f case7-Egress-ipBlock.yaml
(3)修改yaml文件(这里只贴出修改部分)
vim case7-Egress-ipBlock.yaml

    ports:
    - protocol: TCP
      port: 80 #允许匹配到的pod访问目的端口为80的访问
#    - protocol: TCP
#      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
#    - protocol: UDP
#      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析

重新加载yaml文件

2、验证
(1)进入tomcat容器,ping 百度域名,发现无法解析,这是因为关闭了53端口,导致无法进行dns解析

(2)开启53端的网络策略,可以解析百度域名地址,但仍无法访问,这是因为百度域名不匹配出口策略

16.4.8 示例8:Egress-podSelector-Pod出口方向目的Pod限制-只允许访问指定的pod及端口

基于podSelector选择器,限制源pod能够访问的目的pod
1、网络策略:
  匹配成功的源pod只能访问指定的目的pod的指定端口
示例:
(1)编写yaml文件
vim 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     #指定tomcat的label
    ports:
    - protocol: TCP
      port: 8080 #允许80端口的访问
    - protocol: TCP
      port: 53 #允许DNS的解析
    - protocol: UDP
      port: 53

yaml文件指定规则为:只能访问pod 标签为python-tomcat-app1-selector的pod,且只能访问目标pod的8080端口(53端口用来做dns解析)
(2)创建网络策略
kubectl apply -f case8-Egress-PodSelector.yaml

2、验证
(1)进入nginx容器进行测试:
可以正常访问tomcat

注意:如果此时在nginx容器访问tomcat的service地址,也可以正常访问
但是却无法访问外网,这是因为网络策略指定nginx容器只能访问的目标pod的是tomcat,因此不能访问其他内容

16.4.9 示例9:Egress-namespaceSelector

1、网络策略:
(1)限制匹配成功的源pod可以访问的目标namespace。
(2)不能访问指定的namespace以外的其它namespace及外网。
(3)比如允许指定的源pod访问linux和python ns中的8080、3306、6379等端口,但是无法访问其它ns及外网
示例:
(1)编写yaml文件
vim 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

yaml文件指定规则为:指定源pod可以访问的目标namespace中的pod,且端口为8080(53端口用于dns解析)
该示例类似示例6,这里不再举例验证

标签: k8s k8s网络组件
最后更新:2023年8月30日

袁党生

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2023 linux学习. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

豫ICP备18039507号-1