-
Namespace 隔离
默认情况下,所有 Pod 之间是全通的。每个 Namespace 可以配置独立的网络策略,来 隔离 Pod 之间的流量。
v1.7 + 版本通过创建匹配所有 Pod 的 Network Policy 来作为默认的网络策略
-
默认拒绝所有 Pod 之间 Ingress 通信
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
-
默认拒绝所有 Pod 之间 Egress 通信的策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Egress
-
默认拒绝所有 Pod 之间 Ingress 和 Egress 通信的策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
-
默认允许所有 Pod 之间 Ingress 通信的策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
ingress:
- {}
-
默认允许所有 Pod 之间 Egress 通信的策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
egress:
- {}
-
Pod 隔离
通过使用标签选择器(包括 namespaceSelector 和 podSelector)来控制 Pod 之间的流量。
允许 default namespace 中带有 role=frontend 标签的 Pod 访问 default
namespace 中带有 role=db 标签 Pod 的 6379 端口
允许带有 project=myprojects 标签的 namespace 中所有 Pod 访问 default
namespace 中带有 role=db 标签 Pod 的 6379 端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: tcp
port: 6379
允许 default namespace 中带有 role=frontend 标签的 Pod 访问 default
namespace 中带有 role=db 标签 Pod 的 6379 端口
允许带有 project=myprojects 标签的 namespace 中所有 Pod 访问 default
namespace 中带有 role=db 标签 Pod 的 6379 端口
NetworkPolicy
238
允许 default namespace 中带有 role=db 标签的 Pod 访问 10.0.0.0/24 网段
的 TCP 5978 端口
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
-
例子
现在已经配置了一个nginx服务,访问端口是80,默认的状态是所有的pod都可以访问这个服务
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-deployment NodePort 10.102.52.246 <none> 80:31180/TCP 19d
启动一个busybox pod来访问nginx-deployment服务
$ kubectl exec -it pod/busybox-test -- sh
/ # wget --spider --timeout=1 nginx-deployment
Connecting to nginx-deployment (10.102.52.246:80)
remote file exists
/ #
现在给nginx-deployment服务配置network策略,使得pod无法访问这个服务
$ cat default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
$ kubectl create -f default-deny.yaml
networkpolicy.networking.k8s.io/default-deny created
现在busybox的pod无法访问nginx-deployment服务了
$ kubectl exec -it pod/busybox-test -- sh
/ # wget --spider --timeout=1 nginx-deployment
Connecting to nginx-deployment (10.102.52.246:80)
wget: download timed out
/ # exit
查看networkpolicy
$ kubectl get networkpolicy
NAME POD-SELECTOR AGE
default-deny <none> 102s
再创建一个运行带有 access=true 的 Pod 访问的网络策略:
表示所有带有 access=true label 的pods都可以访问nginx-deployment服务
$ cat nginx-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
access: "true"
启动一个带有access=true label的busybox服务
$ cat busybox-test.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/containerID: fefc92be6bb04bacdf757a0b4132d72c2133c94dbfa684296cf59772817fc939
cni.projectcalico.org/podIP: 172.16.43.1/32
cni.projectcalico.org/podIPs: 172.16.43.1/32
creationTimestamp: "2024-06-28T08:39:13Z"
labels:
access: "true"
purpose: demonstrate-busybox
name: busybox-test
namespace: default
resourceVersion: "208006"
uid: 2d94690d-4f16-4bb6-a540-4682334170af
spec:
containers:
- command:
- sleep
- "3600"
image: busybox
imagePullPolicy: IfNotPresent
name: busybox
resources:
... ...
$ kubectl apply -f busybox-test.yaml
此时看到busybox-test这个pod已经带有access=true的label了
$ kubectl describe pod busybox-test
Name: busybox-test
Namespace: default
Priority: 0
Service Account: default
Node: kevin-pc/192.168.227.129
Start Time: Fri, 28 Jun 2024 16:39:13 +0800
Labels: access=true
然后通过busybox-test访问nginx服务就可以访问到了
$ kubectl exec -it pod/busybox-test -- sh
/ # wget --spider -timeout=1 nginx-deployment
Connecting to nginx-deployment (10.102.52.246:80)
remote file exists
/ #
-
删除networkpolicy
删除networkpolicy之后,所有的pod默认都可以访问nginx-deployment服务了
$ kubectl get networkpolicy
NAME POD-SELECTOR AGE
access-nginx app=nginx 10m
default-deny <none> 17m
$ kubectl delete network policy access-nginx
-
几种访问策略的配置例子
-
禁止访问指定服务
首先启动一个nginx服务,并且给这个服务打上label
kubectl run web --image=nginx --labels app=web,env=prod --expose --po
rt 80
(没有配置ingress,所以所有的pod都没法访问这个服务)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-deny-all
spec:
podSelector:
matchLabels:
app: web
env: prod
-
只允许指定 Pod 访问服务
kubectl run apiserver --image=nginx --labels app=bookstore,role=api -
-expose --port 80
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: api-allow
spec:
podSelector:
matchLabels:
app: bookstore
role: api
ingress:
- from:
- podSelector:
matchLabels:
app: bookstore
-
禁止 namespace 中所有 Pod 之间的相互访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
-
禁止其他 namespace 访问服务
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: default
name: web-deny-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
-
只允许指定 namespace 访问服务
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-prod
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
purpose: production
-
允许外网访问服务
kubectl run web --image=nginx --labels=app=web --port 80
kubectl expose deployment/web --type=LoadBalancer
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
app: web
ingress:
- ports:
- port: 80
from: []