30.B站薪享宏福笔记——第十一章(4)网络策略NetworkPolicy

11 B站薪享宏福笔记——第十一章

11.5 网络策略 NetworkPolicy

                      —— 既能防进也能防出

11.5.1 网络策略

(1)概念

如果希望在 IP地址 或端口层面(OSI模型 的 第3层 或 第4层)控制网络流量,则可以考虑为集群中特定应用使用 Kubernetes 网络策略(NetworkPolicy)

Pod 是通过如下三个标识符的组合来辨识是否可以通讯:

  其他被允许的 Pods(例外: Pod 无法阻塞对自身的访问)

  被允许的名字空间

  IP 组块(例外: 与 Pod 运行所在节点的通信总是被允许的,无论是 Pod 还是节点 IP 地址)

(2)前置条件

网络策略通过 网络插件 来实现,要使用网略策略,必须使用支持 网络策略NetworkPolicy 的网络解决方案,创建一个 网络策略NetworkPolicy 资源对象而没有控制器来使其生效,是没有任何作用的,以下是支持 网络策略NetworkPolicy 的网络插件:

  Antrea 、Calico 、 Cilium 、 kube-router 、 Romana 、 Weave 网络

(3)隔离默认策略

出口的隔离

  默认情况下,一个 Pod 的出口是非隔离的,即所有外向连接都是被允许

入口的隔离

  默认情况下,一个 Pod 对入口是非隔离的,即所有入站连接都是被允许

即:当不做额外规则设定,默认情况下,既能进又能出

(4)特别说明

  网络策略是相加的,所以不会产生冲突。如果策略适用于 Pod 某一特定方向的流量,Pod 在对应方向所允许的连接是适用的网路策略所允许的集合,因此,评估的顺序不影响策略的结果(即假设先定义所有网络都允许入站,再定义所有网络都拒绝入站,结果是可以入站,可以理解为入站优先级更高或只要有入站就可以入站)

  要允许从源 Pod 到目的 Pod 的连接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。如果任何一方不允许连接,建立连接将会失败(即A连接B时,需要A网络能出,B网络能入,A才能连接到B)

11.5.2 NetworkPolicy 资源

(1)基本语法

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: test-network-policy
 namespace: default
spec:
 podSelector:
   matchLabels: # 空的 `podSelector` 选择名字空间下的所有 Pod
     role: db
 policyTypes: # NetworkPolicy 未指定 `policyTypes` 则默认情况下始终设置 `Ingress`
   - Ingress
   - Egress
 ingress:
   - from:
       - ipBlock:
           cidr: 172.17.0.0/16
           except:
             - 172.17.1.0/24
       - namespaceSelector:
           matchLabels:
             project: myproject
       - podSelector:
           matchLabels:
           role: frontend
     ports:
       - protocol: TCP
         port: 6379
 egress:
   - to:
       - ipBlock:
           cidr: 10.0.0.0/24
     ports:
       - protocol: TCP
         port: 5978
1.接口组版本:networking.k8s.io 组 v1 版本
2.类别:NetworkPolicy 网络策略
3.元数据:当前 NetworkPolicy网络策略 名称、所属名称空间
4.期望:
    pod 选择器:匹配标签:标签名、标签值(当前网络策略应用在 default 名称空间下,具备标签角色为 db 的 pod)
    策略类型:定义入站、定义出站
    入站:从哪里来:ip块:允许、排除(允许172.17段入站,排除172.17.1段) 或者
                  名称空间匹配:标签匹配:标签名、标签值(允许具有 myproject 标签的 名称空间namespace 入站)或者
                  pod 匹配:标签匹配:标签名、标签值(允许 带有 frontend 标签的 pod 入站)
          端口:协议、端口号
(即,ip块、名称空间匹配、pod匹配 中筛选后的条件 能够允许通过 6379端口 访问 default 名称空间下,标签为 db 的 pod )
    出站:到:ip块:允许(允许出站到 10.0 段)
         端口:端口协议:端口号
(即,default 名称空间下,标签为 db 的 pod 能够访问 ip块中筛选后的条件 的 5978 号端口)

(2)选择器 - to 和 from 的行为

可以在 ingress 的 from 部分或 egress 的 to 部分指定四种选择器:

  1.podSelector

  2.namespaceSelector

  3.namespaceseletor 和 podSelector

( 有 - 是或者的关系,只满足一个条件就能匹配,没有 - 是并且的关系,两边条件要同时满足才能匹配)
..........
ingress:
- from:
  - namespaceSelector:
      matchLables:
        user: alice
    podSelector:
      matchLables:
        role: client
..........
(即 名称空间标签 user 为 alice 且 pod标签 role 为 client 才会被选中)                  

  4.ipBlock

11.5.3 网络策略资源

默认情况下,如果名称空间中不存在任何策略,则所有进出该名称空间的 Pod 的流量都被允许,以下示例的定义可以更改该名称空间中的默认行为

(1)默认拒绝所有入站流量

[root@k8s-master01 11.5]# cat 1.deny_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: default-deny-ingress
spec:
 podSelector: {}
 policyTypes:
 - Ingress
4.期望:pod 选择器:{} 代表匹配所有、策略类型:Ingress 入站
# 正常下面还应该写允许入站匹配规则,没写默认放弃,即拒绝所有入站
# default 名称空间下创建 myapp Pod
[root@k8s-master01 11.5]# kubectl create deployment myapp --image=myapp:v1.0 
deployment.apps/myapp created
# test 名称空间下创建 test Pod
[root@k8s-master01 11.5]# kubectl create namespace test
namespace/test created
[root@k8s-master01 11.5]# kubectl create deployment test --image=myapp:v2.0 -n test 
deployment.apps/test created
[root@k8s-master01 11.5]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
myapp-77d465c645-rfft9   1/1     Running   0          43s   10.244.58.238   k8s-node02   <none>           <none>
[root@k8s-master01 11.5]# kubectl get pod -o wide -n test
NAME                    READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
test-6964996c5f-d9zct   1/1     Running   0          25s   10.244.85.194   k8s-node01   <none>           <none>
# 两个 Pod 都已经启动,本地可以访问
[root@k8s-master01 11.5]# curl 10.244.58.238
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master01 11.5]# curl 10.244.85.194
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
# 假设将 test 设置成客户端,myapp 设置成服务端,进入 test Pod 中,当在未设置 网络策略前,默认是没有限制的
[root@k8s-master01 11.5]# kubectl exec -it test-6964996c5f-d9zct -n test -- /bin/sh
/ # wget 10.244.58.238 && cat index.html && rm -rf index.html
Connecting to 10.244.58.238 (10.244.58.238:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # 
# 新开一个 master01 的 X-shell 终端,添加上面的 入站规则
[root@k8s-master01 ~]# cd /root/11/11.5/
[root@k8s-master01 11.5]# kubectl apply -f 1.deny_networkPolicy.yaml 
networkpolicy.networking.k8s.io/default-deny-ingress created
[root@k8s-master01 11.5]# kubectl get networkpolicies
NAME                   POD-SELECTOR   AGE
default-deny-ingress   <none>         9s
# 添加规则后本地访问入站不通了
[root@k8s-master01 11.5]# curl 10.244.58.238
# 原 master01 的 X-shell 终端再次访问,不能访问的通
[root@k8s-master01 11.5]# kubectl exec -it test-6964996c5f-d9zct -n test -- /bin/sh
/ # wget 10.244.58.238 && cat index.html && rm -rf index.html
Connecting to 10.244.58.238 (10.244.58.238:80)             ---未添加入站规则前,可以访问
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # 
/ # 
/ # wget 10.244.58.238 && cat index.html && rm -rf index.html
Connecting to 10.244.58.238 (10.244.58.238:80)             ---添加入站规则后,访问不通
wget: can't connect to remote host (10.244.58.238): Operation timed out
# 再新开一个 master01 的 X-shell 终端,登录 myapp pod ,访问 test 的 pod , myapp 的入站虽然被限制了,但是出站没有限制
[root@k8s-master01 ~]# kubectl get pod -n test -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
test-6964996c5f-d9zct   1/1     Running   0          63m   10.244.85.194   k8s-node01   <none>           <none>
[root@k8s-master01 ~]# kubectl get pod  -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
myapp-77d465c645-rfft9   1/1     Running   0          64m   10.244.58.238   k8s-node02   <none>           <none>
[root@k8s-master01 ~]# kubectl exec -it myapp-77d465c645-rfft9 -- /bin/sh
/ # wget 10.244.85.194 && cat index.html && rm -rf index.html
Connecting to 10.244.85.194 (10.244.85.194:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
# 控制变量,做下一个实验前,将本次实验的 网络规则删除
[root@k8s-master01 11.5]# kubectl delete -f 1.deny_networkPolicy.yaml 
networkpolicy.networking.k8s.io "default-deny-ingress" deleted

(2)允许所有入站流量

[root@k8s-master01 11.5]# cat 2.allow_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: allow-all-ingress
spec:
 podSelector: {}
 ingress:
 - {}
 policyTypes:
 - Ingress
4.期望:pod 标签匹配:{} 代表匹配所有pod、入站规则匹配:{} 代表匹配所有入站、策略类型:Ingress 入站(可以省略,和 iptables 相同,默认防进不防出,默认就是 Ingress )
# 有了这个策略,任何额外的策略都不会导致规则匹配内 Pod 的任何入站连接被拒绝(允许规则更高)
# 上个实验使用的两个 pod ,当没有添加网络策略时,默认是可以访问的,服务器 和 客户端Pod 都可以
[root@k8s-master01 11.5]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
myapp-77d465c645-rfft9   1/1     Running   0          6h21m   10.244.58.238   k8s-node02   <none>           <none>
[root@k8s-master01 11.5]# kubectl get pod -n test -o wide
NAME                    READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
test-6964996c5f-d9zct   1/1     Running   0          6h20m   10.244.85.194   k8s-node01   <none>           <none>
[root@k8s-master01 11.5]# curl 10.244.58.238
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master01 11.5]# kubectl exec -it test-6964996c5f-d9zct -n test -- /bin/sh
/ # wget 10.244.58.238 && cat index.html && rm -rf index.html
Connecting to 10.244.58.238 (10.244.58.238:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # 
# 新开终端,先添加禁止入站的网络策略,服务器访问不通
[root@k8s-master01 11.5]# kubectl apply -f 1.deny_networkPolicy.yaml 
networkpolicy.networking.k8s.io/default-deny-ingress created
[root@k8s-master01 11.5]# curl 10.244.58.238
# Pod 访问也不通了
[root@k8s-master01 11.5]# kubectl exec -it test-6964996c5f-d9zct -n test -- /bin/sh
/ # 
/ # wget 10.244.58.238 && cat index.html && rm -rf index.html
# 添加允许入站的网络策略后,服务器和 pod 客户端 又可以访问了
[root@k8s-master01 11.5]# kubectl apply -f 2.allow_networkPolicy.yaml 
networkpolicy.networking.k8s.io/allow-all-ingress created
[root@k8s-master01 11.5]# curl 10.244.58.238
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master01 11.5]# kubectl exec -it test-6964996c5f-d9zct -n test -- /bin/sh
/ # wget 10.244.58.238 && cat index.html && rm -rf index.html
Connecting to 10.244.58.238 (10.244.58.238:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # 
# 控制变量,做下一个实验前,将本次实验的 网络规则删除
[root@k8s-master01 11.5]# kubectl get networkpolicies 
NAME                   POD-SELECTOR   AGE
allow-all-ingress      <none>         8m45s
default-deny-ingress   <none>         9m14s
[root@k8s-master01 11.5]# kubectl delete networkpolicies --all
networkpolicy.networking.k8s.io "allow-all-ingress" deleted
networkpolicy.networking.k8s.io "default-deny-ingress" deleted

(3)默认拒绝所有出站流量

[root@k8s-master01 11.5]# cat 3.deny-egress_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: default-deny-egress
spec:
 podSelector: {}
 policyTypes:
 - Egress
4.期望:pod 选择器:{} 代表匹配所有、策略类型:Egress 出站
# 正常下面还应该写允许出站匹配规则,没写默认放弃,即拒绝所有出站
[root@k8s-master01 11.5]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
myapp-77d465c645-rfft9   1/1     Running   0          6h51m   10.244.58.238   k8s-node02   <none>           <none>
[root@k8s-master01 11.5]# kubectl get pod -n test -o wide
NAME                    READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
test-6964996c5f-d9zct   1/1     Running   0          6h50m   10.244.85.194   k8s-node01   <none>           <none>
# 入站正常
[root@k8s-master01 11.5]# curl 10.244.58.238
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
# 出站正常
[root@k8s-master01 11.5]# kubectl exec -it myapp-77d465c645-rfft9 -- /bin/sh
/ # wget 10.244.85.194 && cat index.html && rm -rf index.html
Connecting to 10.244.85.194 (10.244.85.194:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
/ # 
/ # exit
# 添加出站规则,匹配的 Pod 不允许出站,访问不通
[root@k8s-master01 11.5]# kubectl apply -f 3.deny-egress_networkPolicy.yaml 
networkpolicy.networking.k8s.io/default-deny-egress created
[root@k8s-master01 11.5]# kubectl exec -it myapp-77d465c645-rfft9 -- /bin/sh
/ # wget 10.244.85.194 && cat index.html && rm -rf index.html
Connecting to 10.244.85.194 (10.244.85.194:80)
^C

(4)允许所有出站流量

[root@k8s-master01 11.5]# cat 4.allow-egress_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: allow-all-egress
spec:
 podSelector: {}
 egress:
 - {}
 policyTypes:
 - Egress
4.期望:pod 标签匹配:{} 代表匹配所有pod、出站规则匹配:{} 代表匹配所有出站、策略类型:Egress 出站
# 有了这个策略,任何额外的策略都不会导致规则匹配内 Pod 的任何出站连接被拒绝(允许规则更高)
# 上面实验设置为禁止出站后,无法出站,当添加允许出站后,又可以出站了,因为允许出站和禁止出站,允许出站优先级更高
[root@k8s-master01 11.5]# kubectl apply -f 4.allow-egress_networkPolicy.yaml 
networkpolicy.networking.k8s.io/allow-all-egress created
[root@k8s-master01 11.5]# kubectl get networkpolicies
NAME                  POD-SELECTOR   AGE
allow-all-egress      <none>         7s
default-deny-egress   <none>         9m6s
[root@k8s-master01 11.5]# kubectl exec -it myapp-77d465c645-rfft9 -- /bin/sh
/ # wget 10.244.85.194 && cat index.html && rm -rf index.html
Connecting to 10.244.85.194 (10.244.85.194:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
# 消除实验影响
[root@k8s-master01 11.5]# kubectl get networkpolicies NAME POD-SELECTOR AGE allow-all-egress <none> 2d17h default-deny-egress <none> 2d18h [root@k8s-master01 11.5]# kubectl delete networkpolicies --all networkpolicy.networking.k8s.io "allow-all-egress" deleted networkpolicy.networking.k8s.io "default-deny-egress" deleted

(5)默认拒绝所有入站和所有出站流量

可以为名称空间创建 "默认" 策略,可以通过在该名称空间中创建 NetworkPolicy网络策略 来阻止所有入站和出站流量

[root@k8s-master01 11.5]# cat 5.deny-all_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: default-deny-all
spec:
 podSelector: {} # 应用此策略的Pod的选择器,此处为空表示选择所有的Pod
 policyTypes:
 - Ingress
 - Egress
4.期望:pod 选择器:{} 代表匹配所有、策略类型:Ingress 入站、Egress 出站(没对 Ingress 和 Egress 做匹配,即全部不放行,入站禁行、出站禁行)
[root@k8s-master01 11.5]# kubectl apply -f 5.deny-all_networkPolicy.yaml 
networkpolicy.networking.k8s.io/default-deny-all created
[root@k8s-master01 11.5]# kubectl get netpol
NAME               POD-SELECTOR   AGE
default-deny-all   <none>         4m19s
[root@k8s-master01 11.5]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS      AGE    IP              NODE         NOMINATED NODE   READINESS GATES
myapp-77d465c645-rfft9   1/1     Running   1 (22m ago)   3d1h   10.244.58.240   k8s-node02   <none>           <none>
[root@k8s-master01 11.5]# kubectl get pod -n test -o wide
NAME                    READY   STATUS    RESTARTS      AGE    IP              NODE         NOMINATED NODE   READINESS GATES
test-6964996c5f-d9zct   1/1     Running   1 (22m ago)   3d1h   10.244.85.237   k8s-node01   <none>           <none>
# 入站被拒绝
[root@k8s-master01 11.5]# curl 10.244.58.240
^C
# 出站被拒绝
[root@k8s-master01 11.5]# kubectl exec -it myapp-77d465c645-rfft9 -- /bin/sh
/ # wget 10.244.85.237 && cat index.html && rm -f index.html
Connecting to 10.244.85.237 (10.244.85.237:80)
^C
/ # exit
command terminated with exit code 130
# 消除实验影响
[root@k8s-master01 11.5]# kubectl delete deployment --all
deployment.apps "myapp" deleted
[root@k8s-master01 11.5]# kubectl delete deployment -n test --all
deployment.apps "test" deleted
[root@k8s-master01 11.5]# kubectl delete netpol --all
networkpolicy.networking.k8s.io "default-deny-all" deleted

11.5.4 网络策略端口范围定义

特性状态:Kubernetes v1.25[stable]

在编写 NetworkPolicy 时,可以针对一个端口的范围而不是某个固定端口定义,可以通过使用 endport 字段实现

[root@k8s-master01 11.5]# cat 6.port-endPort_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: multi-port-egress
 namespace: default
spec:
 podSelector:
   matchLabels:
     role: db
 policyTypes:
 - Egress
 egress:
 - to:
   - ipBlock:
       cidr: 10.244.0.0/16
   ports:
   - protocol: TCP
     port: 70
     endPort: 90
4.期望:pod 选择器:标签匹配:key 名、value 名、策略类别:Egress 出站、出站策略:至、ip 块、ip 区间地址、端口定义:协议、端口启始值、截止端口值

注意:

  1.endPort 字段必须等于或大于 port 字段的值

  2.只有定义了 port 时才能定义 endPort

  3.两个字段设置的值都只能是数字

11.5.5 生产环境网络策略

(1)允许指定 Pod 访问

# A 终端中创建一个 nginx Deployment 并且通过服务将其暴露
[root@k8s-master01 11.5]# kubectl create deployment nginx --image=myapp:v1.0
deployment.apps/nginx created
[root@k8s-master01 11.5]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP              NODE         NOMINATED NODE   READINESS GATES
nginx-5476c5b568-nt7w2   1/1     Running   0          2m4s   10.244.85.225   k8s-node01   <none>           <none>
# 将此 Deployment 以名为 nginx 的 Service 暴露出来
[root@k8s-master01 11.5]# kubectl expose deployment nginx --port=80
service/nginx exposed
[root@k8s-master01 ~]# kubectl get svc
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx                    ClusterIP   10.8.117.153    <none>        80/TCP    8m48s
# --spider 只显示响应头,不显示响应体,--timeout=1,默认单位秒,nginx 是前面定义的 service 名称(相同名称空间),未定义网络策略前,可以访问
[root@k8s-master01 11.5]#  kubectl run busybox --rm -ti --image=busybox:1.28 /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx         # 未添加网络策略前,可以访问
Connecting to nginx (10.8.117.153:80)
/ # 
[root@k8s-master01 11.5]# cat 7.nginx_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: access-nginx
spec:
 podSelector:
   matchLabels:
     app: nginx
 ingress:
 - from:
   - podSelector:
       matchLabels:
         access: "true"
4.期望:pod 选择器:匹配标签:key 值、value 值、入站匹配:来自:pod 选择器:匹配标签:key 值、value 值(不写网络类别,默认入站)
# 新开一个master01终端 B,上面定义的 nginx 的 deployment 标签符合 nginx 标签匹配,所以会遵循上面定义入站网略策略
[root@k8s-master01 ~]# cd 11/11.5/
[root@k8s-master01 11.5]# kubectl get pod --show-labels
NAME                     READY   STATUS    RESTARTS   AGE    LABELS
busybox                  1/1     Running   0          125m   run=busybox
nginx-5476c5b568-nt7w2   1/1     Running   0          129m   app=nginx,pod-template-hash=5476c5b568
[root@k8s-master01 11.5]# kubectl apply -f 7.nginx_networkPolicy.yaml 
networkpolicy.networking.k8s.io/access-nginx created
[root@k8s-master01 11.5]# kubectl get netpol
NAME           POD-SELECTOR   AGE
access-nginx   app=nginx      4s
# 回到原终端 A,Pod 内,再次访问,添加网络策略后,访问失败
[root@k8s-master01 11.5]# kubectl run busybox --rm -ti --image=busybox:1.28 /bin/sh If you don't see a command prompt, try pressing enter. / # wget --spider --timeout=1 nginx # 未添加网络策略前,可以访问 Connecting to nginx (10.8.117.153:80) / # / # / # / # wget --spider --timeout=1 nginx # 添加网络策略后,访问超时,不可以访问 Connecting to nginx (10.8.117.153:80) wget: download timed out / #
# B 终端中,为最开始访问通,添加网络策略后访问不通的 Pod 添加对应的标签
[root@k8s-master01 11.5]# kubectl get pod --show-labels
NAME                     READY   STATUS    RESTARTS   AGE    LABELS
busybox                  1/1     Running   0          133m   run=busybox
nginx-5476c5b568-nt7w2   1/1     Running   0          137m   app=nginx,pod-template-hash=5476c5b568
[root@k8s-master01 11.5]# kubectl label pod busybox access=true
pod/busybox labeled
[root@k8s-master01 11.5]# kubectl get pod --show-labels
NAME                     READY   STATUS    RESTARTS   AGE    LABELS
busybox                  1/1     Running   0          134m   access=true,run=busybox
nginx-5476c5b568-nt7w2   1/1     Running   0          138m   app=nginx,pod-template-hash=5476c5b568
# 回到原终端 A,Pod 内,再次访问,添加标签后,访问成功
[root@k8s-master01 11.5]#  kubectl run busybox --rm -ti --image=busybox:1.28 /bin/sh
If you don't see a command prompt, try pressing enter. 
/ # wget --spider --timeout=1 nginx       # 未添加网络策略前,可以访问
Connecting to nginx (10.8.117.153:80)
wget: download timed out
/ # 
/ # 
/ # 
/ # wget --spider --timeout=1 nginx       # 添加网络策略后,访问超时,不可以访问
Connecting to nginx (10.8.117.153:80)
wget: download timed out
/ # 
/ # 
/ # wget --spider --timeout=1 nginx       # 添加符合网络策略的标签后,访问成功
Connecting to nginx (10.8.117.153:80)

(2)禁止访问指定服务

[root@k8s-master01 11.5]# kubectl run web --image=myapp:v1.0 --labels app=web,env=prod --expose --port 80
service/web created
pod/web created
[root@k8s-master01 11.5]# kubectl get pod -o wide --show-labels
NAME                     READY   STATUS    RESTARTS   AGE    IP              NODE         NOMINATED NODE   READINESS GATES   LABELS
busybox                  1/1     Running   0          158m   10.244.58.244   k8s-node02   <none>           <none>            access=true,run=busybox
nginx-5476c5b568-nt7w2   1/1     Running   0          162m   10.244.85.225   k8s-node01   <none>           <none>            app=nginx,pod-template-hash=5476c5b568
web                      1/1     Running   0          14s    10.244.58.235   k8s-node02   <none>           <none>            app=web,env=prod
# 本地访问,入站不受限制
[root@k8s-master01 11.5]# curl 10.244.58.235
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master01 11.5]# cat 8.web_networkPolicy.yaml 
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
 name: web-deny-all
spec:
 podSelector:
   matchLabels:
     app: web
     env: prod
4.期望:pod 选择器:匹配标签:key 值、value 值、key 值、value 值(没有写网络类别,默认入站 Ingress,没有写Ingress 代表放行的匹配条件,默认拒绝所有)
[root@k8s-master01 11.5]# kubectl apply -f 8.web_networkPolicy.yaml 
networkpolicy.networking.k8s.io/web-deny-all created
[root@k8s-master01 11.5]# kubectl get networkpolicy
NAME           POD-SELECTOR       AGE
access-nginx   app=nginx          64m
   app=web,env=prod   9s
# 应用网络策略后,本地访问,入站受到限制
[root@k8s-master01 11.5]# curl 10.244.58.235
^C

(3)禁止 namespace 中 Pod 访问

# 删除 网络策略,避免实验干扰
[root@k8s-master01 11.5]# kubectl get networkpolicy
NAME           POD-SELECTOR       AGE
access-nginx   app=nginx          20h
web-deny-all   app=web,env=prod   19h
[root@k8s-master01 11.5]# kubectl delete networkpolicy --all
networkpolicy.networking.k8s.io "access-nginx" deleted
networkpolicy.networking.k8s.io "web-deny-all" deleted
# 相同名称空间下,busybox 可以访问 nginx
[root@k8s-master01 11.5]# kubectl get pod -n default -o wide
NAME                     READY   STATUS    RESTARTS       AGE   IP              NODE         NOMINATED NODE   READINESS GATES
busybox                  1/1     Running   1 (164m ago)   22h   10.244.58.233   k8s-node02   <none>           <none>
nginx-5476c5b568-nt7w2   1/1     Running   1 (164m ago)   22h   10.244.85.220   k8s-node01   <none>           <none>
web                      1/1     Running   1 (164m ago)   20h   10.244.58.239   k8s-node02   <none>           <none>
[root@k8s-master01 11.5]# kubectl exec -it busybox -- /bin/sh
/ # wget 10.244.85.220 && cat index.html && rm -rf index.html
Connecting to 10.244.85.220 (10.244.85.220:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # exit
# 不同名称空间下,busybox 同样可以访问 nginx
[root@k8s-master01 11.5]# kubectl create deployment test --image=myapp:v1.0 -n test
deployment.apps/test created
[root@k8s-master01 11.5]# kubectl get pod -n test -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
test-5bdfbdc6b8-56cb9   1/1     Running   0          12s   10.244.85.197   k8s-node01   <none>           <none>
[root@k8s-master01 11.5]# kubectl exec -it test-5bdfbdc6b8-56cb9 -n test -- /bin/sh
/ # wget 10.244.85.220 && cat index.html && rm -rf index.html
Connecting to 10.244.85.220 (10.244.85.220:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # exit
[root@k8s-master01 11.5]# cat 9.deny_networkPolicy.yaml 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: default-deny
 namespace: default
spec:
 podSelector: {}
4.期望:pod 选择器:匹配所有 (没有写网络策略,默认是 入站Ingress, 没有写入站的匹配,默认是所有,即当前名称空间下访问全部禁止)
[root@k8s-master01 11.5]# kubectl apply -f 9.deny_networkPolicy.yaml 
networkpolicy.networking.k8s.io/default-deny created
[root@k8s-master01 11.5]# kubectl get networkpolicy
NAME           POD-SELECTOR   AGE
default-deny   <none>         9s
# 相同名称空间下,添加网络策略后,访问不通
[root@k8s-master01 11.5]# kubectl exec -it busybox -- /bin/sh
/ # wget 10.244.85.220 && cat index.html && rm -rf index.html
Connecting to 10.244.85.220 (10.244.85.220:80)
^C
/ # exit
command terminated with exit code 130
# 不同名称空间下,添加网络策略后,同样访问不通,这是因为入站规则对 default 名称空间下所有 pod 生效,所以 test 空间下 pod 想要访问 default 名称空间下 pod 同样被拒绝
[root@k8s-master01 11.5]# kubectl exec -it test-5bdfbdc6b8-56cb9 -n test -- /bin/sh
/ # wget 10.244.85.220 && cat index.html && rm -rf index.html
Connecting to 10.244.85.220 (10.244.85.220:80)
^C
/ # exit
command terminated with exit code 130
# 消除实验干扰
[root@k8s-master01 11.5]# kubectl delete networkpolicy --all
networkpolicy.networking.k8s.io "default-deny" deleted

(4)只允许指定 namespace 访问

# 消除实验干扰
[root@k8s-master01 11.5]# kubectl delete svc `kubectl get svc|egrep -v 'NAME|kubernetes'|awk '{print $1}'`
[root@k8s-master01 11.5]# kubectl delete deployment --all
[root@k8s-master01 11.5]# kubectl delete pod --all
[root@k8s-master01 11.5]# kubectl run web --image=myapp:v1.0 --labels=app=web --expose --port 80 
service/web created
pod/web created
[root@k8s-master01 11.5]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.0.0.1      <none>        443/TCP   13d
web          ClusterIP   10.1.78.121   <none>        80/TCP    9s
[root@k8s-master01 11.5]# kubectl get pod -o wide --show-labels
NAME   READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES   LABELS
web    1/1     Running   0          5m41s   10.244.58.252   k8s-node02   <none>           <none>            app=web
[root@k8s-master01 11.5]# cat 10.allow_networkPolicy.yaml 
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
 name: web-allow-prod
spec:
 podSelector:
   matchLabels:
     app: web
 ingress:
 - from:
   - namespaceSelector:
       matchLabels:
         purpose: production
4.期望:pod 选择器:标签匹配:key 值、value 值 、入站匹配:来自:名称空间匹配:匹配标签:key 值 、value 值(匹配pod 带有标签的遵循网络策略)
# 默认未添加网络策略前,可以访问
[root@k8s-master01 11.5]# kubectl get namespaces -n test --show-labels
NAME               STATUS   AGE     LABELS
.........
test               Active   4d1h    kubernetes.io/metadata.name=test
[root@k8s-master01 11.5]# kubectl get pod -n test -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
test-5bdfbdc6b8-56cb9   1/1     Running   0          37m   10.244.85.197   k8s-node01   <none>           <none>
[root@k8s-master01 11.5]# kubectl exec -it test-5bdfbdc6b8-56cb9 -n test -- /bin/sh 
/ # wget 10.1.78.121 && cat index.html && rm -rf index.html
Connecting to 10.1.78.121 (10.1.78.121:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # wget 10.244.58.252 && cat index.html && rm -rf index.html
Connecting to 10.244.58.252 (10.244.58.252:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # exit
# 添加网络策略后,因为 test 名称空间没有 key 值,value 值,所以访问不通
[root@k8s-master01 11.5]# kubectl apply -f 10.allow_networkPolicy.yaml 
networkpolicy.networking.k8s.io/web-allow-prod created
[root@k8s-master01 11.5]# kubectl get networkpolicy
NAME             POD-SELECTOR   AGE
web-allow-prod   app=web        6s
[root@k8s-master01 11.5]# kubectl exec -it test-5bdfbdc6b8-56cb9 -n test -- /bin/sh 
/ # wget 10.1.78.121 && cat index.html && rm -rf index.html
Connecting to 10.1.78.121 (10.1.78.121:80)
^C
/ # wget 10.244.58.252 && cat index.html && rm -rf index.html
Connecting to 10.244.58.252 (10.244.58.252:80)
^C
/ # exit
command terminated with exit code 130
# 为 test 名称空间添加标签后,可以访问
[root@k8s-master01 11.5]# kubectl get namespaces test --show-labels
NAME   STATUS   AGE    LABELS
test   Active   4d1h   kubernetes.io/metadata.name=test
[root@k8s-master01 11.5]# kubectl label namespaces test purpose=production
namespace/test labeled
[root@k8s-master01 11.5]# kubectl get namespaces test --show-labels
NAME   STATUS   AGE    LABELS
test   Active   4d1h   kubernetes.io/metadata.name=test,purpose=production
[root@k8s-master01 11.5]# kubectl exec -it test-5bdfbdc6b8-56cb9 -n test -- /bin/sh 
/ # wget 10.1.78.121 && cat index.html && rm -rf index.html
Connecting to 10.1.78.121 (10.1.78.121:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # wget 10.244.58.252 && cat index.html && rm -rf index.html
Connecting to 10.244.58.252 (10.244.58.252:80)
index.html           100% |********************************************************************************************************************************************************************************************|    65   0:00:00 ETA
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
/ # exit
# 消除本节实验干扰
[root@k8s-master01 11.5]# kubectl delete svc `kubectl get svc|egrep -v 'NAME|kubernetes'|awk '{print $1}'`
[root@k8s-master01 11.5]# kubectl delete netpol --all
[root@k8s-master01 11.5]# kubectl delete deployment --all
[root@k8s-master01 11.5]# kubectl delete pod --all

11.5.6 注意

(1)IP 代理负载

  集群的入站和出站机制通常需要重写数据包的 源IP(SNAT) 或 目标IP(DNAT)。在发生这种情况时,不确定在 NetworkPolicy 处理之前还是之后发生,并且对于网络插件、云提供商、Service 实现等的不同组合,其行为可能会有所不同(源IP 经过 SNAT、DNAT 后,IP地址 可能发生更改,修改入站和出站 IP块 规则后要测试)

    1.对入站流量而言,这意味着在某些情况下,可以根据实际的原始源IP 过滤传入的数据包,而在其他情况下,NetworkPolicy 所作用的 源IP 则可能是 LoadBalancer 或 Pod 的节点等

    2.对出站流量而言,这意味着从 Pod 到被重写为集群外部 IP 的 Service IP 的连接可能会或可能不会受到基于 ipBlock 的策略约束

(2)通过网络策略(至少目前还)无法完成的工作 v1.29

  强制集群内部流量经过某公用网关(这种场景最好通过服务网格或其他代理来实现)

  与 TLS 相关的场景(考虑使用服务网格或者 Ingress 控制器)

  特定于节点的策略(可以使用 CIDR(无类别域间路由选择) 来表达这一需求,不过无法使用节点在 Kubernetes 中的其他标识信息来辨识目标节点)

  基于名字来选择服务、来选择目标 Pod 或名字空间

  创建或管理由第三方来实际完成的"策略请求"

  实现适用于所有名字空间或 Pods 的默认策略(某些第三方 Kubernetes 发行版本或项目可以做到这点(非官方))

  高级的策略查询或可达性相关工具

  生成网络安全事件日志的能力(例如,被阻塞或接收的连接请求)

  显式地拒绝策略的能力(目前,NetworkPolicy 的模型默认采用拒绝操作,其唯一的能力是添加允许策略)

  禁止本地回路或指向宿主的网络流量(Pod 目前无法阻塞 localhost ,它们也无法禁止来自所有节点 master node 的访问请求)

———————————————————————————————————————————————————————————————————————————

                                                                                                                         无敌小马爱学习

posted on 2025-07-31 14:04  马俊南  阅读(48)  评论(0)    收藏  举报