2017-12-28 23:11:03 +08:00
|
|
|
|
## Network Policy
|
2018-01-13 23:07:18 +08:00
|
|
|
|
|
|
|
|
|
`Network Policy`提供了基于策略的网络控制,用于隔离应用并减少攻击面。它使用标签选择器模拟传统的分段网络,并通过策略控制它们之间的流量以及来自外部的流量;目前基于`linux iptables`实现,使用类似`nf_conntrack`检查记录网络流量`session`从而决定流量是否阻断;因此它是`状态检测防火墙`。
|
|
|
|
|
|
|
|
|
|
- `k8s v1.7`版本以后,Network Policy已经默认可用;`v1.6`以及之前版本需要在kube-apiserver中开启extensions/v1beta1/networkpolicies
|
|
|
|
|
- 网络插件要支持 Network Policy,如 Calico、Romana、Weave Net
|
|
|
|
|
|
|
|
|
|
### 简单示例
|
|
|
|
|
|
|
|
|
|
实验环境:k8s v1.9, calico 2.6.5
|
|
|
|
|
|
|
|
|
|
首先部署测试用nginx服务
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
$ kubectl run nginx --image=nginx --replicas=3 --port=80 --expose
|
|
|
|
|
# 验证测试nginx服务
|
|
|
|
|
$ kubectl get pod -o wide
|
|
|
|
|
NAME READY STATUS RESTARTS AGE IP NODE
|
|
|
|
|
nginx-7587c6fdb6-p2fpz 1/1 Running 0 55m 172.20.125.2 10.0.96.7
|
|
|
|
|
nginx-7587c6fdb6-pbw7c 1/1 Running 0 55m 172.20.124.2 10.0.96.6
|
|
|
|
|
nginx-7587c6fdb6-v48db 1/1 Running 0 55m 172.20.121.195 10.0.96.4
|
|
|
|
|
$ kubectl get svc nginx
|
|
|
|
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
|
|
|
|
nginx ClusterIP 10.68.7.183 <none> 80/TCP 1h
|
|
|
|
|
```
|
|
|
|
|
默认情况下,其他pod可以访问nginx服务
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
$ kubectl run busy1 --rm -it --image=busybox /bin/sh
|
|
|
|
|
If you don't see a command prompt, try pressing enter.
|
|
|
|
|
/ # wget --spider --timeout=1 nginx
|
|
|
|
|
Connecting to nginx (10.68.7.183:80)
|
|
|
|
|
```
|
|
|
|
|
创建`DefaultDeny Network Policy`后,其他Pod(包括namespace外部)不能访问nginx
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
$ cat > default-deny.yaml << EOF
|
|
|
|
|
apiVersion: networking.k8s.io/v1
|
|
|
|
|
kind: NetworkPolicy
|
|
|
|
|
metadata:
|
|
|
|
|
name: default-deny
|
|
|
|
|
spec:
|
|
|
|
|
podSelector: {}
|
|
|
|
|
policyTypes:
|
|
|
|
|
- Ingress
|
|
|
|
|
EOF
|
|
|
|
|
$ kubectl create -f default-deny.yaml
|
|
|
|
|
networkpolicy "default-deny" created
|
|
|
|
|
$ kubectl run busy1 --rm -it --image=busybox /bin/sh
|
|
|
|
|
If you don't see a command prompt, try pressing enter.
|
|
|
|
|
/ # wget --spider --timeout=1 nginx
|
|
|
|
|
Connecting to nginx (10.68.7.183:80)
|
|
|
|
|
wget: download timed out
|
|
|
|
|
```
|
|
|
|
|
创建一个允许带有access=true的Pod访问nginx的网络策略
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
$ cat > nginx-policy.yaml << EOF
|
|
|
|
|
kind: NetworkPolicy
|
|
|
|
|
apiVersion: networking.k8s.io/v1
|
|
|
|
|
metadata:
|
|
|
|
|
name: access-nginx
|
|
|
|
|
spec:
|
|
|
|
|
podSelector:
|
|
|
|
|
matchLabels:
|
|
|
|
|
run: nginx
|
|
|
|
|
ingress:
|
|
|
|
|
- from:
|
|
|
|
|
- podSelector:
|
|
|
|
|
matchLabels:
|
|
|
|
|
access: "true"
|
|
|
|
|
EOF
|
|
|
|
|
$ kubectl create -f nginx-policy.yaml
|
|
|
|
|
networkpolicy "access-nginx" created
|
|
|
|
|
|
|
|
|
|
# 不带access=true标签的Pod还是无法访问nginx服务
|
|
|
|
|
$ kubectl run busy1 --rm -it --image=busybox /bin/sh
|
|
|
|
|
If you don't see a command prompt, try pressing enter.
|
|
|
|
|
/ # wget --spider --timeout=1 nginx
|
|
|
|
|
Connecting to nginx (10.68.7.183:80)
|
|
|
|
|
wget: download timed out
|
|
|
|
|
|
|
|
|
|
# 而带有access=true标签的Pod可以访问nginx服务
|
|
|
|
|
$ kubectl run busy2 --rm -it --labels="access=true" --image=busybox /bin/sh
|
|
|
|
|
If you don't see a command prompt, try pressing enter.
|
|
|
|
|
/ # wget --spider --timeout=1 nginx
|
|
|
|
|
Connecting to nginx (10.68.7.183:80)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 示例策略解读
|
|
|
|
|
|
|
|
|
|
``` 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
|
|
|
|
|
```
|
|
|
|
|
- 策略作用的对象Pods:default命名空间下带有`role=db`标签的Pod
|
|
|
|
|
- 内向流量策略
|
|
|
|
|
- 允许属于`172.17.0.0/16`网段但不属于`172.17.1.0/24`的源地址访问该对象Pods的TCP 6379端口
|
|
|
|
|
- 允许带有project=myprojects标签的namespace中所有Pod访问该对象Pods的TCP 6379端口
|
|
|
|
|
- 允许default命名空间下带有role=frontend标签的Pod访问该对象Pods的TCP 6379端口
|
|
|
|
|
- 拒绝其他所有主动访问该对象Pods的网络流量
|
|
|
|
|
- 外向流量策略
|
|
|
|
|
- 允许该对象Pods主动访问目的地址属于`10.0.0.0/24`网段且目的端口为TCP 5978的流量
|
|
|
|
|
- 拒绝该对象Pods其他所有主动外向网络流量
|
|
|
|
|
|
|
|
|
|
### 使用场景
|
|
|
|
|
|
|
|
|
|
参考阅读[ahmetb/kubernetes-network-policy-recipes](https://github.com/ahmetb/kubernetes-network-policy-recipes) 该项目举例一些使用NetworkPolicy的场景,并有形象的配图
|
|
|
|
|
|
|
|
|
|
#### 拒绝其他namespaces访问服务
|
|
|
|
|
|
|
|
|
|
![deny_from_other_namespaces](../../pics/deny_from_other_namespaces.gif)
|
|
|
|
|
|
|
|
|
|
+ 场景1:你的k8s集群应用按照namespaces区分生产、测试环境,你要确保生产环境不会受到测试环境错误访问影响
|
|
|
|
|
+ 场景2:你的k8s集群有多租户应用采用namespaces区分的,你要确保多租户之间的应用隔离
|
|
|
|
|
|
|
|
|
|
在你需要隔离的命名空间创建如下策略:
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
kind: NetworkPolicy
|
|
|
|
|
apiVersion: networking.k8s.io/v1
|
|
|
|
|
metadata:
|
|
|
|
|
namespace: your-ns
|
|
|
|
|
name: deny-other-namespaces
|
|
|
|
|
spec:
|
|
|
|
|
podSelector:
|
|
|
|
|
matchLabels:
|
|
|
|
|
ingress:
|
|
|
|
|
- from:
|
|
|
|
|
- podSelector: {}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 允许外部访问服务
|
|
|
|
|
|
|
|
|
|
+ 场景:暴露特定Pod的特定端口给外部访问
|
|
|
|
|
|
|
|
|
|
![allow_from_external](../../pics/allow_from_external.gif)
|
|
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
|
# 创建示例应用待暴露服务
|
|
|
|
|
$ kubectl run web --image=nginx --labels=app=web --port 80 --expose
|
|
|
|
|
|
|
|
|
|
# 创建网络策略
|
|
|
|
|
kind: NetworkPolicy
|
|
|
|
|
apiVersion: networking.k8s.io/v1
|
|
|
|
|
metadata:
|
|
|
|
|
name: web-allow-external
|
|
|
|
|
spec:
|
|
|
|
|
podSelector:
|
|
|
|
|
matchLabels:
|
|
|
|
|
app: web
|
|
|
|
|
ingress:
|
|
|
|
|
- from: []
|
|
|
|
|
port:
|
|
|
|
|
- protocol: TCP
|
|
|
|
|
port: 80
|
|
|
|
|
```
|