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 的访问请求)
———————————————————————————————————————————————————————————————————————————
无敌小马爱学习