
一、Network Policy
1. Network Policy概述
NetworkPolicy(网络策略)是Kubernetes原生资源对象,用于控制Pod之间、Pod与外部端点之间的网络进出流量,实现集群内微分段网络访问控制。NetworkPolicy作用于Pod,通过标签选择器筛选目标Pod,定义Ingress(入站流量)和Egress(出站流量)访问规则。
NetworkPolicy依赖支持该特性的CNI网络插件,如Calico、Weave等。Flannel默认不支持NetworkPolicy,如果使用Flannel,策略不会生效。
1.1 默认拒绝原则 当一个Pod被NetworkPolicy匹配时:
若策略中没有写明允许的入站规则,所有入站流量默认拒绝。
若策略中没有写明允许的出站规则,所有出站流量默认拒绝。
没有任何NetworkPolicy作用的Pod,保持集群默认互通。
1.2 NetworkPolicy识别可与Pod通信的对象,依靠三类标识
允许通信的Pod:Pod自身访问自身的流量默认不受阻断;
允许通信的命名空间;
IP地址段:Pod与所在节点之间的通信始终放行,不受Pod、节点IP地址影响。
1.3 配置NetworkPolicy规则时存在两种模式
若采用Pod、命名空间作为管控对象,借助标签选择器筛选Pod,以此定义进入匹配Pod的流量权限;
若基于IP进行管控,则通过CIDR地址段设置访问策略。
2. 集群Pod默认互通特性
默认情况下,k8s集群内所有Pod之间网络互通,能够接收任何来源的流量,不存在网络隔离限制。
[Step1] 创建两个namespace,分别名为space01和space02。
root@k8s-master:~# kubectl create namespace space01
root@k8s-master:~# kubectl create namespace space02[Step2] 本地新建YAML清单,定义Pod资源描述模板。使用busybox镜像在分别在space01和space02命名空间内创建Pod。
root@k8s-master:~# vim busybox-pod.yml
# 写入下列内容
apiVersion: v1
kind: Pod
metadata:
name: busybox01
namespace: space01
spec:
containers:
- name: busybox01
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","1000"]
---
apiVersion: v1
kind: Pod
metadata:
name: busybox02
namespace: space02
spec:
containers:
- name: busybox02
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","1000"][Step3] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f busybox-pod.yml[Step4] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。由此可以观察到,尽管两个Pod分属不同命名空间,但集群为其分配的IP地址仍属于同一子网。
root@k8s-master:~# kubectl get -f busybox-pod.yml -o wide
[Step5] 登录到busybox01容器,测试与busybox02的连通性,网络正常通信。
root@k8s-master:~# kubectl exec -n space01 -it busybox01 -- /bin/sh
/ # ping 172.16.126.4 -c 5
[Step6] 登录到busybox02容器,测试与busybox01的连通性,网络正常通信。
root@k8s-master:~# kubectl exec -n space02 -it busybox02 -- /bin/sh
/ # ping 172.16.126.5 -c 5
3. Pod隔离
当Pod被NetworkPolicy匹配时,会开启网络隔离。只要命名空间内存在的网络策略选中某个Pod,该Pod将会拒绝所有策略没有明确放行的网络连接。多条网络策略之间不会相互冲突,规则效果会叠加生效。如果多条策略同时作用于同一个Pod,最终生效规则是所有策略入站、出站规则的合集,策略先后顺序不会影响最终结果。
如果要实现两个Pod正常通信,源Pod的出站规则和目标Pod的入站规则都必须放行这条流量。只要源端出站策略拦截或目标端入站策略拦截,通信都会失败。

4. 流量方向选择
当前存在两个命名空间:targetspace和clientspace。
targetspace:服务端命名空间,里面存放需要被网络策略保护的Pod,负责接收外部访问流量。
clientspace:客户端命名空间,里面的Pod会主动发起访问请求,作为流量的发送方。
NetworkPolicy默认会拒绝所有请求,只要Pod被策略匹配,所有进出流量都会被拦截,只有写在白名单规则中的流量才能正常通行。同时网络策略只对和它同一命名空间内的Pod生效,而入站规则用来管控外部Pod访问当前命名空间内Pod的流量。
因此想要保护targetspace内的服务Pod,网络策略必须部署在targetspace命名空间,才能识别并管控该命名空间下的目标Pod。

二、NetworkPolicy案例配置
1. 创建NetworkPolicy
[Step1] 本地新建YAML清单,定义NetworkPolicy资源描述模板。对当前命名空间内标签为“label=access”的Pod启用网络隔离。配置入站规则,仅允许同命名空间具备“access=true”标签的Pod进行访问。由于未定义出站规则,受控Pod所有出站流量将默认拒绝。
root@k8s-master:~# vim network-policy.yml
# 写入下列内容
apiVersion: networking.k8s.io/v1 # 版本信息
kind: NetworkPolicy # 资源类型
metadata:
name: network-policy
spec:
podSelector: # Pod选择器
matchLabels: # 采用标签精确匹配的筛选方式
# 匹配携带标签 label=true的Pod,符合该条件的Pod开启网络隔离
label: "true"
ingress: # 定义入站规则
- from: # 流量来源白名单,允许哪些对象发起访问
- podSelector: # 筛选条件,从Pod维度匹配访问源
matchLabels: # 对访问源Pod使用标签精准匹配
access: "true" # 仅允许当前命名空间内携带标签 access=true 的Pod建立访问[Step2] 基于YAML清单向Kubernetes集群声明式地创建NetworkPolicy资源。
root@k8s-master:~# kubectl create -f network-policy.yml[Step3] 验证:查看当前集群中名为network-policy的NetworkPolicy资源详细信息。
root@k8s-master:~# kubectl describe networkpolicies.networking.k8s.io/network-policy
2. 创建正常的Pod
[Step1] 本地新建YAML清单,定义Pod资源描述模板。
root@k8s-master:~# vim busybox-pod.yml
# 写入下列内容
apiVersion: v1 # 版本信息
kind: Pod # 资源类型
metadata:
name: busybox-pod
spec:
containers:
- name: pod-target
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","1000"][Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f busybox-pod.yml[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的详细信息。
root@k8s-master:~# kubectl get -f busybox-pod.yml -o wide
3. 创建网络隔离受控Pod
[Step1] 本地新建YAML清单,定义Pod资源描述模板。基于busybox镜像创建pod-target,将其设置为受控对象,打上标签“label:access”。
root@k8s-master:~# vim pod-target.yml
# 写入下列内容
apiVersion: v1 # 版本信息
kind: Pod # 资源类型
metadata:
name: pod-target
labels: # 给当前资源加上标签
label: access # 标签键值对
spec:
containers:
- name: pod-target
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","1000"][Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f pod-target.yml[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。
root@k8s-master:~# kubectl get -f pod-target.yml -o wide
[Step4] 验证:登录到busybox-pod容器,测试与pod-target的连通性,此时网络无法联通。
root@k8s-master:~# kubectl exec -it busybox-pod -- /bin/sh
/ # ping 172.16.126.43 -c 5
/ # exit
[Step5] 验证:使用k8s-master测试与pod-target的连通性,同样网络无法联通。
root@k8s-master:~# ping 172.16.126.43 -c 5
4. 创建允许访问的Pod
[Step1] 本地新建YAML清单,定义Pod资源描述模板。基于busybox镜像创建pod-client,允许其访问受控Pod,打上标签“access=true”。
root@k8s-master:~# vim pod-client.yml
# 写入下列内容
apiVersion: v1 # 版本信息
kind: Pod # 资源类型
metadata:
name: pod-client
labels: # 给当前资源加上标签
access: "true" # 标签键值对,true本身具备含义,因此需要加上双引号
spec:
containers:
- name: pod-target
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sleep","1000"][Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f pod-client.yml[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的详细信息。
root@k8s-master:~# kubectl get -f pod-client.yml -o wide
[Step4] 验证:登录到pod-client容器,测试与pod-target的连通性,网络正常通信。
root@k8s-master:~# kubectl exec -it pod-client -- /bin/sh
/ # ping 172.16.126.43 -c 5
/ # exit—

