kubeasz/docs/guide/networkpolicy.md

190 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

## Network Policy
`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
```
- 策略作用的对象Podsdefault命名空间下带有`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
```