文章目录
一、概述
在Kubernetes中,NetworkPolicy是一项关键功能,它允许开发者定义和控制Pod之间的网络通信。本文将深入研究Kubernetes中的NetworkPolicy,详细介绍其原理、用途,并通过实际示例演示如何使用NetworkPolicy来确保集群中的网络安全。
1、什么是NetworkPolicy?
NetworkPolicy是Kubernetes中用于定义Pod之间网络通信规则的资源对象。通过NetworkPolicy,开发者可以控制哪些Pod可以与另外哪些Pod通信,以及使用何种方式进行通信。这种细粒度的网络控制有助于提高集群的安全性,防止未经授权的访问和通信。
2、NetworkPolicy的基本原理
NetworkPolicy的工作原理基于以下几个核心概念:
- Pod选择器(PodSelector)& namespaceSelector:NetworkPolicy使用标签选择器来选择特定的Pod。通过标签,可以将网络策略应用于特定的Pod群体。
- Ingress规则:定义了允许从其他Pod进入被选中Pod的规则,包括允许的协议、端口范围等。
- Egress规则:定义了允许被选中Pod访问其他Pod或外部网络的规则。
- Peer Pod:NetworkPolicy中的规则是基于Peer Pod(对等Pod)的。通过选择Peer Pod,可以精确定义通信策略。
二、NetworkPolicy资源清单
apl
apiVersion: networking.k8s.io/v1 # 使用网络策略的稳定 API 组和版本
kind: NetworkPolicy # 资源类型:网络策略
metadata: # 元数据开始
name: test-network-policy # 策略名称,用于标识
namespace: default # 策略生效的命名空间(作用于 default 内的 Pod)
spec: # 规格说明开始
podSelector: # 选择哪些 Pod 应用此策略
matchLabels: # 通过标签匹配
app: backend # 选择带有 app=backend 标签的 Pod 作为目标 Pod
ingress: # 入站规则列表(默认拒绝所有未明确允许的入站流量)
- from: # 允许的来源列表
- podSelector: # 来源1:通过 Pod 标签选择
matchLabels:
app: frontend # 允许带有 app=frontend 标签的 Pod 访问目标 Pod
- ipBlock: # 来源2:通过 IP 地址段选择
cidr: 192.168.1.0/24 # 允许来自 192.168.1.0/24 网段的流量访问目标 Pod
ports: # 允许访问的端口列表
- protocol: TCP # 协议:TCP
port: 8080 # 只允许访问目标 Pod 的 8080 端口
egress: # 出站规则列表(默认拒绝所有未明确允许的出站流量)
- to: # 允许的目标列表
- podSelector: # 目标1:通过 Pod 标签选择
matchLabels:
app: database # 允许目标 Pod 访问带有 app=database 标签的 Pod
ports: # 允许访问的端口列表
- protocol: TCP # 协议:TCP
port: 3306 # 目标 Pod 访问其他 Pod 时只允许使用 3306 端口
三、NetworkPolicy的示例
示例一:不允许相同Namespace下的Pod通信
【注意】提前给命名空间设置labels
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-same-namespace
namespace: default # 改成你要限制的命名空间
spec:
# 作用于命名空间内所有 Pod
podSelector: {}
# 拒绝所有入站流量
policyTypes:
- Ingress
# 入站规则为空 = 拒绝所有入站
ingress: []
####禁止default命令空间一切访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: full-isolation
namespace: default # 改成你要隔离的命名空间
spec:
# 匹配命名空间下所有 Pod
podSelector: {}
# 同时控制 入站 + 出站 流量(核心!缺一不可)
policyTypes:
- Ingress
- Egress
# 1. 拒绝所有入站流量(任何Pod都不能访问我)
ingress: []
# 2. 拒绝所有出站流量(我不能访问任何Pod)
egress: []
示例二:限制与外部访问
yaml
①
##(被选中的 Pod 被"封闭"在当前命名空间内部,只能与同命名空间内的 Pod 交互,无法与外界通信。常用于保护内网敏感服务、限制容器访问外网等场景。)
apiVersion: networking.k8s.io/v1 # 使用网络策略的稳定 API 组和版本(必须完整填写)
kind: NetworkPolicy # 资源类型:网络策略
metadata: # 元数据部分开始
name: deny-external-traffic # 策略名称,用于标识
namespace: network1 # 策略生效的命名空间(只作用于 network1 内的 Pod)
spec: # 规格说明开始
podSelector: # 选择哪些 Pod 应用此策略
matchLabels: # 通过标签匹配
app: nginx # 只作用于标签为 app=nginx 的 Pod
policyTypes: # 声明此策略控制哪些方向的流量
- Ingress # 控制入站流量(进入 Pod)
- Egress # 控制出站流量(从 Pod 发出)
ingress: # 入站规则列表
- from: # 允许的来源列表
- podSelector: {} # 空的选择器表示允许同命名空间内所有 Pod 的入站流量
egress: # 出站规则列表
- to: # 允许的目标列表
- podSelector: {} # 空的选择器表示允许访问同命名空间内所有 Pod 的出站流量
#### 该策略不会影响同一个命名空间内没有 app: nginx 标签的其他 Pod,也不会影响从本 Pod 发往集群内部 DNS、kube-apiserver 等关键服务的流量(如果需要额外放通,可在 egress 中添加对应规则,例如允许访问 kube-system 命名空间的 DNS Pod)。
②
#######允许本命名空间的pod之间的访问,及与default命名空间下的访问,但不允许对其他网络的访问
###在 network1 命名空间中,对标签为 app: nginx 的 Pod 实施网络隔离,允许它们与同命名空间内的所有 Pod 双向通信,同时允许它们访问 default 命名空间中的所有 Pod (出站方向),但拒绝所有其他流量。
apiVersion: networking.k8s.io/v1 # 使用网络策略的稳定 API 组和版本(必须完整)
kind: NetworkPolicy # 资源类型:网络策略
metadata: # 元数据开始
name: deny-external-traffic # 策略名称,用于标识
namespace: network1 # 策略生效的命名空间(只作用于 network1 内的 Pod)
spec: # 规格说明开始
podSelector: # 选择要应用策略的 Pod
matchLabels: # 通过标签匹配
app: nginx # 只作用于标签为 app=nginx 的 Pod
policyTypes: # 声明此策略控制哪些方向的流量
- Ingress # 控制入站流量(进入 Pod)
- Egress # 控制出站流量(从 Pod 发出)
ingress: # 入站规则列表
- from: # 允许的来源列表
- podSelector: {} # 空的选择器表示允许同命名空间内所有 Pod 的入站流量
egress: # 出站规则列表
- to: # 允许的目标列表
- podSelector: {} # 允许访问同命名空间内任意 Pod
- namespaceSelector: # 允许访问特定命名空间内的所有 Pod
matchLabels: # 通过命名空间的标签匹配
kubernetes.io/metadata.name: default # 匹配名称为 default 的命名空间
在这个示例中,我们创建了一个名为"deny-external-traffic"的NetworkPolicy,限制了标签为app: sensitive-app的Pod的Ingress和Egress。该策略允许Pod之间的通信,但不允许访问任何外部网络。
示例三:指定端口范围
yaml
apiVersion: networking.k8s.io/v1 # 使用网络策略的稳定 API 组和版本(必须完整)
kind: NetworkPolicy # 资源类型:网络策略
metadata: # 元数据开始
name: allow-specific-ports # 策略名称,用于标识
spec: # 规格说明开始
podSelector: # 选择哪些 Pod 应用此策略
matchLabels: # 通过标签匹配
app: frontend # 只作用于标签为 app=frontend 的 Pod
ingress: # 入站规则列表(注意:未声明 policyTypes,默认只控制入站)
- ports: # 允许的端口列表
- protocol: TCP # 协议类型:TCP
port: 80 # 端口号:80
- protocol: UDP # 协议类型:UDP
port: 53 # 端口号:53
在这个示例中,我们创建了一个名为"allow-specific-ports"的NetworkPolicy,指定了标签为app: frontend的Pod的Ingress规则。该规则允许从其他Pod进入的流量,其中包括TCP端口80和UDP端口53。
四、限制其他命名空间中的pod访问podSelector匹配到的pod
apl
apiVersion: networking.k8s.io/v1 # 使用网络策略的稳定 API 组和版本(必须完整)
kind: NetworkPolicy # 资源类型:网络策略
metadata: # 元数据开始
name: deny-external-traffic # 策略名称,用于标识
namespace: network1 # 策略生效的命名空间(作用于 network1 内的 Pod)
spec: # 规格说明开始
podSelector: # 选择哪些 Pod 应用此策略
matchLabels: # 通过标签匹配
app: nginx # 只作用于标签为 app=nginx 的 Pod
policyTypes: # 声明此策略控制的流量方向
- Ingress # 只控制入站流量(进入 Pod),出站不受影响
ingress: # 入站规则列表(默认拒绝所有未明确允许的入站)
- from: # 允许的来源列表
- podSelector: {} # 来源1:允许同命名空间(network1)内所有 Pod 的入站流量
- namespaceSelector: # 来源2:通过命名空间标签选择来源
matchLabels: # 匹配命名空间的标签
ns: network1 # 允许带有标签 ns=network1 的命名空间内的所有 Pod 访问
五、只访问外部网络和同命名空间下的pod
现在有如下需求: 使用networkpolicy实现在myns1命名空间下的所有label为app: alpine的pod可以与myns1命名空间中的其他pod和外部互联网通信,不能与其他命名空间中的任何pod通信。请编写资源清单文件。
【注意】 pod访问带有svc的pod时,可以通过svcFQDN访问。
apl
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: alpine-communication-policy
namespace: network1 # 策略仅作用于 myns1 命名空间
spec:
podSelector:
matchLabels:
app: nginx # 目标 Pod:network1 中所有标签为 app: nginx 的 Pod
policyTypes:
- Ingress # 控制入站流量
- Egress # 控制出站流量
# ------------------------------
# 入站规则:仅允许 network1 内 Pod 访问
# ------------------------------
ingress:
- from:
- podSelector: {} # 匹配 network1 命名空间内的所有 Pod(无标签过滤)
# 无端口限制(允许所有端口),如需限制端口可添加 ports 字段
# ------------------------------
# 出站规则:允许访问 network1 内 Pod 和外部互联网,拒绝其他命名空间
# ------------------------------
egress:
# 规则 1:允许访问 network1 命名空间内的所有 Pod(包括自身)
- to:
- podSelector: {} # 匹配当前命名空间(network1)的所有 Pod
# 规则 2:允许访问外部互联网(非集群内部 IP)
- to:
- ipBlock:
cidr: 0.0.0.0/0 # 允许所有 IPv4 地址(需排除集群内部 CIDR)
except:
# 重要:替换为集群实际的 Pod CIDR 和 Service CIDR
- 10.244.0.0/16 # 示例:calico 默认 Pod CIDR(需根据集群调整)
- 10.96.0.0/12 # 示例:Kubernetes Service 默认 CIDR(需根据集群调整)
# 规则 3:允许 DNS 解析(关键!否则无法访问外部域名)
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system # kube-dns 所在命名空间
podSelector:
matchLabels:
k8s-app: kube-dns # kube-dns Pod 标签(可能因集群不同而变化)
ports:
- protocol: UDP
port: 53 # DNS UDP 端口
- protocol: TCP
port: 53 # DNS TCP 端口(用于长查询)
四、NetworkPolicy的高级用法(了解)
除了基本的示例外,NetworkPolicy还支持一些高级用法,如网络策略的继承、Peer Pod选择器的高级匹配等。以下是一些高级用法的示例:
1、网络策略的继承
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: parent-policy
spec:
podSelector:
matchLabels:
role: parent
ingress:
- from:
- podSelector:
matchLabels:
role: child
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: child-policy
spec:
podSelector:
matchLabels:
role: child
policyTypes:
- Ingress
- Egress
在这个示例中,我们创建了两个NetworkPolicy。"parent-policy"用于选择标签为role: parent的Pod,并定义了一个Ingress规则,允许来自标签为role: child的Pod的通信。"child-policy"选择标签为role: child的Pod,并定义了Ingress和Egress规则。这样,"child-policy"继承了"parent-policy"的规则。
2、高级Peer Pod选择器匹配
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: advanced-selector-matching
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchExpressions:
- {key: role, operator: In, values: [frontend, middleware]}
在这个示例中,我们通过matchExpressions定义了更复杂的Peer Pod选择器匹配条件。该规则选择标签为app: backend的Pod,并定义了一个Ingress规则,允许来自标签为role为frontend或middleware的Pod的通信。