005-k8s-NetworkPolicy
Kubernetes之网络策略(Network Policy) ¶
基本原理 ¶
Network Policy是kubernetes中的一种资源类型,它从属于某个namespace。其内容从逻辑上看包含两个关键部分,一是pod选择器,基于标签选择相同namespace下的pod,将其中定义的规则作用于选中的pod。另一个就是规则了,就是网络流量进出pod的规则,其采用的是白名单模式,符合规则的通过,不符合规则的拒绝。
Pod 可以与之通信的实体是通过如下三个标识符的组合来辩识的:
- 其他被允许的 Pod(例外:Pod 无法阻塞对自身的访问)
- 被允许的名字空间
- IP 组块(例外:与 Pod 运行所在的节点的通信总是被允许的, 无论 Pod 或节点的 IP 地址)
在定义基于 Pod 或名字空间的 NetworkPolicy 时, 你会使用选择算符来设定哪些流量可以进入或离开与该算符匹配的 Pod。
另外,当创建基于 IP 的 NetworkPolicy 时,我们基于 IP 组块(CIDR 范围)来定义策略。
默认情况下,如果命名空间中不存在任何策略,则所有进出该命名空间中的Pod的流量都被允许。
NetworkPolicy的规则可以选择如下3种:
- namespaceSelector:根据命名空间的标签选择,具有该标签的命名空间都可以访问。
- podSelector:根据Pod的标签选择,具有该标签的Pod都可以访问。
- ipBlock:根据网络选择,网段内的IP地址都可以访问。(仅Egress支持IPBlock)
Pod 隔离的两种类型 ¶
Pod 有两种隔离:出口的隔离和入口的隔离。它们涉及到可以建立哪些连接。 这里的“隔离”不是绝对的,而是意味着“有一些限制”。 另外的,“非隔离方向”意味着在所述方向上没有限制。这两种隔离(或不隔离)是独立声明的, 并且都与从一个 Pod 到另一个 Pod 的连接有关。
要允许从源 Pod 到目的 Pod 的某个连接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允许此连接。 如果任何一方不允许此连接,则连接将会失败。
通过 YAML 使用Ingress规则 ¶
场景一:通过网络策略限制Pod只能被带有特定标签的Pod访问 ¶
目标Pod具有 role=db 标签,该 Pod 只允许带有 role=frontend 标签的 Pod 访问其 6379 端口。设置该网络策略的具体操作步骤如下:
1. 创建后端数据库 Pod 和 service
# 1-redis-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: redis-db
namespace: default
labels:
role: db
spec:
containers:
- name: redis
image: redis:latest
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: default
spec:
selector:
role: db
ports:
- protocol: TCP
port: 6379
targetPort: 6379
2. 创建前端应用 Pod
创建一个带有 role: frontend
标签的前端应用 Pod。这里以一个简单的 BusyBox 镜像为例,用于测试网络连接。
# 2-frontend-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: frontend-app
namespace: default
labels:
role: frontend
spec:
containers:
- name: busybox
image: busybox:1.36
command: ['sh', '-c', 'sleep 3600']
3. 创建不满足标签要求的 Pod
为了验证网络策略的效果,我们创建一个不带有 role: frontend
标签的 Pod。
# 3-unauthorized-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: unauthorized-app
namespace: default
labels:
role: other
spec:
containers:
- name: busybox
image: busybox:1.36
command: ['sh', '-c', 'sleep 3600']
4. 创建网络策略
使用你提供的网络策略配置,确保只有带有 role: frontend
标签的 Pod 可以通过 TCP 协议访问带有 role: db
标签的 Pod 的 6379 端口。
# 4-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-demo1
namespace: default
spec:
podSelector:
matchLabels:
role: db
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
5. 验证网络策略
a. 验证前端 Pod 能否访问
使用以下命令在前端 Pod 中尝试访问 Redis 数据库:
kubectl exec -it frontend-app -n default -- sh -c 'nc -zv redis-service 6379'
b. 验证未授权 Pod 能否访问
使用以下命令在未授权 Pod 中尝试访问 Redis 数据库:
kubectl exec -it unauthorized-app -n default -- sh -c 'nc -zv redis-service 6379'
场景二:通过网络策略限制Pod只能被指定命名空间下的Pod访问 ¶
1. 创建后端数据库 Pod 和 service
创建带有 role=db
标签的目标 Pod,这里以 Redis 为例。
# 1-redis-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: redis-db
namespace: default
labels:
role: db
spec:
containers:
- name: redis
image: redis:latest
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: default
spec:
selector:
role: db
ports:
- protocol: TCP
port: 6379
targetPort: 6379
2. 创建指定命名空间及测试 Pod
创建带有 project=myproject
标签的命名空间,并且在该命名空间下创建一个测试 Pod。
# 2-myproject.yaml
apiVersion: v1
kind: Namespace
metadata:
name: myproject-namespace
labels:
project: myproject
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: myproject-namespace
spec:
containers:
- name: busybox
image: busybox:1.36
command: ['sh', '-c', 'sleep 3600']
3. 创建不满足标签要求的 Pod
创建带有 project=myproject
标签的命名空间,并且在该命名空间下创建一个测试 Pod。
# 2-myproject-1.yaml
apiVersion: v1
kind: Namespace
metadata:
name: myproject1-namespace
labels:
project: myproject
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: myproject1-namespace
spec:
containers:
- name: busybox
image: busybox:1.36
command: ['sh', '-c', 'sleep 3600']
4. 创建网络策略
创建网络策略,让目标 Pod 仅允许 project=myproject
标签的命名空间中的 Pod 访问其 6379 端口。
# 4-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-demo
namespace: default
spec:
podSelector:
matchLabels:
role: db
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
ports:
- protocol: TCP
port: 6379
5. 验证网络策略
a. 验证前端 Pod 能否访问
使用以下命令在前端 Pod 中尝试访问 Redis 数据库:
kubectl exec -it test-pod -n myproject-namespace -- sh -c 'nc -zv redis-service.default 6379'
b. 验证未授权 Pod 能否访问
使用以下命令在未授权 Pod 中尝试访问 Redis 数据库:
kubectl exec -it test-pod -n myproject1-namespace -- sh -c 'nc -zv redis-service.default 6379'
场景三:通过网络策略限制Pod只能被指定命名空间下的带特定标签的Pod访问 ¶
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-demo3
namespace: default
spec:
podSelector:
matchLabels:
role: db
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 6379
通过YAML使用Egress规则 ¶
场景一:通过网络策略限制Pod只能访问指定地址 ¶
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-demo3
namespace: default
spec:
policyTypes: # 使用Egress必须指定policyType
- Egress
podSelector: # 规则对具有role=db标签的Pod生效
matchLabels:
role: db
egress: # 表示出规则
- to:
- ipBlock:
cidr: 172.16.0.16/16 # 允许在出方向访问此网段
except:
- 172.16.0.40/32 # 不允许在出方向访问此网段,except网段需在cidr网段内
场景二:通过网络策略限制Pod只能被带有特定标签的Pod访问,且只能访问指定Pod ¶
目标Pod具有role=db标签,该Pod只允许带有role=frontend标签的Pod访问其6379-6380端口,且该Pod只能访问带有role=web标签的Pod。网络策略中的Ingress和Egress可以定义在同一个规则中,具体操作步骤如下:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-demo4
namespace: default
spec:
policyTypes:
- Ingress
- Egress
podSelector: # 规则对具有role=db标签的Pod生效
matchLabels:
role: db
ingress: # 表示入规则
- from:
- podSelector: # 只允许具有role=frontend标签的Pod访问
matchLabels:
role: frontend
ports: # 只能使用TCP协议访问6379端口
- protocol: TCP
port: 6379
endPort: 6380
egress: # 表示出规则
- to:
- podSelector: # 只允许访问具有role=web标签的Pod
matchLabels:
role: web
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- 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
https://support.huaweicloud.com/basics-cce/kubernetes_0027.html#section1