NetworkPolicy用来控制Pod与Pod之间的网络通信,它也支持针对Namespace进行限制。基于白名单模式,符合规则的对象通过,不符合的拒绝。
应用场景举例:
-
Pod A不能访问Pod B;
-
开发环境所有Pod不能访问测试命名空间;
-
提供对外访问时,限制外部IP;
官方NetworkPolicy YAML示例
bash
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
说明:必需字段:apiVersion、 kind 和 metadata 字段。
podSelector:定义目标Pod的匹配标签,即哪些Pod会生效此策略;
policyTypes:表示给定的策略是应用于目标Pod的入站流量(Ingress)还是出站流量(Egress),或两者兼有。 如果NetworkPolicy未指定policyTypes则默认情况下始终设置Ingress。
ingress:定义入流量限制规则,from用来定义白名单对象,比如网段、命名空间、Pod标签,Ports定义目标端口。
egress:定义出流量限制规则,定义可以访问哪些IP和端口
该 YAML 文件定义了一个 Kubernetes 网络策略(NetworkPolicy),用于控制特定 Pod 的网络访问权限。下面是对这个文件的详细解释:
基本信息
- apiVersion :
networking.k8s.io/v1
- 指定了使用的 Kubernetes API 版本。 - kind :
NetworkPolicy
- 表明这是一个网络策略资源。 - metadata :
- name :
test-network-policy
- 网络策略的名称。 - namespace :
default
- 网络策略所属的命名空间。
- name :
规范(spec)
-
podSelector:
- matchLabels :
- role :
db
- 这个选择器指定网络策略应用于所有带有标签role=db
的 Pod。
- role :
- matchLabels :
-
policyTypes:
Ingress
- 表明这个策略包含对进入选定 Pod 的流量的规则。Egress
- 表明这个策略包含对从选定 Pod 流出的流量的规则。
进入流量规则(Ingress)
- ingress :
- from :
- ipBlock :
- cidr :
172.17.0.0/16
- 允许从这个 CIDR 块的 IP 地址范围进入流量。 - except :
172.17.1.0/24
- 从上述 CIDR 块中排除这个子网,即这个子网中的 IP 地址不允许访问。
- cidr :
- namespaceSelector :
- matchLabels :
- project :
myproject
- 允许来自带有标签project=myproject
的命名空间中的所有 Pod 的流量。
- project :
- matchLabels :
- podSelector :
- matchLabels :
- role :
frontend
- 允许来自带有标签role=frontend
的 Pod 的流量。
- role :
- matchLabels :
- ipBlock :
- ports :
- protocol :
TCP
- 指定允许 TCP 协议。 - port :
6379
- 指定允许访问端口 6379(通常为 Redis 服务端口)。
- protocol :
- from :
流出流量规则(Egress)
- egress :
- to :
- ipBlock :
- cidr :
10.0.0.0/24
- 允许流向这个 CIDR 块的 IP 地址范围的流出流量。
- cidr :
- ipBlock :
- ports :
- protocol :
TCP
- 指定允许 TCP 协议。 - port :
5978
- 指定允许访问端口 5978。
- protocol :
- to :
案例一:
需求:aming命名空间下所有Pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问aming命名空间Pod。
bash
首先创建几个Pod:
root@k8s-master:/home/vagrant# kubectl run busybox --image=busybox -- sleep 3600 ## default命名空间里创建busybox Pod
pod/busybox created
root@k8s-master:/home/vagrant# kubectl create namespace aming
namespace/aming created
root@k8s-master:/home/vagrant# kubectl run busybox --image=busybox -n aming -- sleep 3600 ## aming命名空间里创建busybox Pod
pod/busybox created
root@k8s-master:/home/vagrant# kubectl run web --image=nginx:latest -n aming ## aming命名空间里创建web pod
pod/web created
在没有创建NetworkPolicy的情况下测试:
root@k8s-master:/home/vagrant# kubectl get pods -n aming -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 78s 172.16.126.28 k8s-worker2 <none> <none>
web 1/1 Running 0 56s 172.16.194.88 k8s-worker1 <none> <none>
root@k8s-master:/home/vagrant# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 76s 172.16.126.27 k8s-worker2 <none> <none>
#aming空间的Pod ping default的Pod可以ping通
root@k8s-master:/home/vagrant# kubectl exec -it busybox -n aming -- ping 172.16.126.27
PING 172.16.126.27 (172.16.126.27): 56 data bytes
64 bytes from 172.16.126.27: seq=0 ttl=63 time=0.159 ms
64 bytes from 172.16.126.27: seq=1 ttl=63 time=0.059 ms
#aming空间的Pod ping 本命名空间的Pod可以ping通
root@k8s-master:/home/vagrant# kubectl exec -it busybox -n aming -- ping 172.16.194.88
PING 172.16.194.88 (172.16.194.88): 56 data bytes
64 bytes from 172.16.194.88: seq=0 ttl=62 time=0.633 ms
64 bytes from 172.16.194.88: seq=1 ttl=62 time=0.751 ms
#default命名空间ping aming命名空间的Pod可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox -- ping 172.16.126.28
PING 172.16.126.28 (172.16.126.28): 56 data bytes
64 bytes from 172.16.126.28: seq=0 ttl=63 time=0.064 ms
64 bytes from 172.16.126.28: seq=1 ttl=63 time=0.107 ms
创建networkpolicy的YAML
bash
root@k8s-master:/home/vagrant# cat deny-all-namespaces.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-all-namespaces
namespace: aming
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
root@k8s-master:/home/vagrant# kubectl get NetworkPolicy -n aming
NAME POD-SELECTOR AGE
deny-all-namespaces <none> 15s
验证效果
bash
#aming命名空间 ping default命名空间的Pod 可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox -n aming -- ping 172.16.126.27
PING 172.16.126.27 (172.16.126.27): 56 data bytes
64 bytes from 172.16.126.27: seq=0 ttl=63 time=0.095 ms
64 bytes from 172.16.126.27: seq=1 ttl=63 time=0.142 ms
^C
#default命名空间 ping aming命名空间的Pod 不可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox -- ping 172.16.126.28
^C
root@k8s-master:/home/vagrant# kubectl exec busybox -- ping 172.16.194.88
^C
#aming命名空间 ping 本命名空间的Pod 可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox -n aming -- ping 172.16.194.88
PING 172.16.194.88 (172.16.194.88): 56 data bytes
64 bytes from 172.16.194.88: seq=0 ttl=62 time=0.440 ms
案例二:
通过PodSelector限制
bash
root@k8s-master:/home/vagrant# cat pod-selector.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: pod-selector
namespace: aming
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: dev
ports:
- port: 80
root@k8s-master:/home/vagrant# kubectl apply -f pod-selector.yaml
networkpolicy.networking.k8s.io/pod-selector created
创建测试pod
bash
root@k8s-master:/home/vagrant# kubectl run web01 --image=nginx:latest -n aming -l 'app=test'
pod/web01 created
root@k8s-master:/home/vagrant# kubectl run app01 --image=nginx:latest -n aming -l 'app=dev'
pod/app01 created
root@k8s-master:/home/vagrant# kubectl run app02 --image=nginx:1.23.2 -n aming
pod/app02 created
#查看web01的IP
root@k8s-master:/home/vagrant# kubectl get pods -n aming -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app01 1/1 Running 0 61s 172.16.126.31 k8s-worker2 <none> <none>
app02 1/1 Running 0 54s 172.16.194.89 k8s-worker1 <none> <none>
web01 1/1 Running 0 2m1s 172.16.126.29 k8s-worker2 <none> <none>
root@k8s-master:/home/vagrant# kubectl exec app01 -n aming -- curl 172.16.126.29
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
100 615 100 615 0 0 265k 0 --:--:-- --:--:-- --:--:-- 300k
root@k8s-master:/home/vagrant# kubectl exec app02 -n aming -- curl 172.16.126.29
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:16 --:--:-- 0^C
案例三:
限制namespace
bash
root@k8s-master:/home/vagrant# cat allow-ns.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-ns
namespace: aming
spec:
policyTypes:
- Ingress
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
app: test
ports:
- port: 80
root@k8s-master:/home/vagrant# kubectl create ns test
root@k8s-master:/home/vagrant# kubectl apply -f allow-ns.yaml
networkpolicy.networking.k8s.io/allow-ns created
root@k8s-master:/home/vagrant# kubectl label ns test app=test
namespace/test labeled
root@k8s-master:/home/vagrant# kubectl get ns test --show-labels
NAME STATUS AGE LABELS
test Active 71s app=test,kubernetes.io/metadata.name=test
创建测试pod
bash
kubectl run web01 --image=nginx:latest -n aming
kubectl run web02 --image=nginx:latest -n test
kubectl run web03 --image=nginx:latest
kubectl run web04 --image=nginx:latest -n aming
#查看web01的IP
root@k8s-master:/home/vagrant# kubectl get pods -o wide -n aming
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web01 1/1 Running 0 2m19s 172.16.126.32 k8s-worker2 <none> <none>
web04 1/1 Running 0 51s 172.16.126.35 k8s-worker2 <none> <none>
#可以访问
root@k8s-master:/home/vagrant# kubectl exec web02 -n test -- curl 172.16.126.32
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 1011k 0 --:--:-- --:--:-- --:--:-- 600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#不可以访问
root@k8s-master:/home/vagrant# kubectl exec web03 -- curl 172.16.126.32
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0^C
##不可以访问,即使同一个命名空间也无法访问
root@k8s-master:/home/vagrant# kubectl exec web04 -n aming -- curl 172.16.126.32
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0^C