之前我們寫過關(guān)于NetworkPolicy的官方實(shí)例,這篇文章我們會講一下我們?nèi)粘J褂玫囊恍┏S美印?/p>
簡介
首先,我們來回顧一下我們之前關(guān)于Networkpolicy的基本概念。network policy顧名思義就是對pod進(jìn)行網(wǎng)絡(luò)策略控制。 k8s本身并不支持,因?yàn)閗8s有許多種網(wǎng)絡(luò)的實(shí)現(xiàn)方式,企業(yè)內(nèi)部可以使用簡單的flannel、weave、kube-router等,適合公有云的方案則有calico等。不同的網(wǎng)絡(luò)實(shí)現(xiàn)原理(vethpair、bridge、macvlan等)并不能統(tǒng)一地支持network policy。
network policy 策略模型
使用network policy資源可以配置pod的網(wǎng)絡(luò),networkPolicy是namespace scoped的,也就是作用域只是在某個namespace,它只能影響某個namespace下的pod的網(wǎng)絡(luò)出入站規(guī)則。
- metadata 描述信息
- podSelector pod選擇器,選定的pod所有的出入站流量要遵循本networkpolicy的約束
- policyTypes 策略類型。包括了Ingress和Egress,默認(rèn)情況下一個policyTypes的值一定會包含Ingress,當(dāng)有egress規(guī)則時,policyTypes的值中會包含Egress
- ingress 入站
- egress 出站
策略模型可以參考官方文檔, 這里舉個例子:
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
該例子的效果如下:
1、default namespace下label包含role=db的pod,都會被隔絕,他們只能建立“滿足networkPolicy的ingress和egress描述的連接”。即2-5點(diǎn):
2、所有屬于172.17.0.0/16網(wǎng)段的IP,除了172.17.1.0/24中的ip,其他的都可以與上述pod的6379端口建立tcp連接。
3、所有包含label:project=myproject的namespace中的pod可以與上述pod的6379端口建立tcp連接;
4、所有default namespace下的label包含role=frontend的pod可以與上述pod的6379端口建立tcp連接;
5、允許上述pod訪問網(wǎng)段為10.0.0.0/24的目的IP的5978端口。
再例,如果我們想要只允許default這個namespace下label包含access=true的pod訪問nginx pod(label:run=nginx),可以對nginx pod設(shè)置入站規(guī)則:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx
namespace: default
spec:
podSelector:
matchLabels:
run: nginx
ingress:
- from:
- podSelector:
matchLabels:
access: "true"
另外一些默認(rèn)的規(guī)則:
1.同namespace的pod,入站規(guī)則為全部禁止
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
2.同namespace的pod,入站規(guī)則為全部開放:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
ingress:
- {}
3.同namespace的pod,出站規(guī)則為全部禁止
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Egress
4.同namespace的pod,出站規(guī)則為全部開放
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
egress:
- {}
policyTypes:
- Egress
network policy的實(shí)現(xiàn)
network policy的實(shí)現(xiàn)仰賴CNI插件的支持,目前已經(jīng)支持的cni插件包括:
Calico 。calico本身通過BGP路由實(shí)現(xiàn)容器網(wǎng)絡(luò),network policy大致也是通過它實(shí)現(xiàn)的。
Kube-router。 這個工具比較吸引人,因?yàn)樗褂胕ptables實(shí)現(xiàn)networkpolicy,同時它也能成為kube-proxy組件的替代品。
Weave Net。也是通過iptables實(shí)現(xiàn)出入站策略。(看了社區(qū)的例子,里面針對namespace級別的控制好像要用正則表達(dá)式進(jìn)行匹配)
這些容器網(wǎng)絡(luò)解決方案,在支持networkpolicy時,均需要在node上啟動agent(可以用k8s的daemonset)
思考:與neutron 網(wǎng)絡(luò)中安全組的區(qū)別
其實(shí)network policy要做的事情,安全組一樣可以做。但network policy可以做到namespace范圍的整體控制。
思考一個networkpolicy agent要做的事情,應(yīng)該包含以下幾點(diǎn):
1、對networkpolicy進(jìn)行全namespace范圍的list & watch;
2、對規(guī)則原語的解析和定制。(如何將namespace、label等概念具象到iptables中?我的想法比較笨拙:使用正則表達(dá)式表述pod name的規(guī)則,同時list-watch pod并維護(hù)pod name 到pod ip的關(guān)系)
3、維護(hù)這些規(guī)則在本地的實(shí)現(xiàn)和記錄(如iptables表)
安全組的規(guī)則記錄在上層網(wǎng)關(guān),而不是每一個節(jié)點(diǎn)上在安全組規(guī)則上,可能需要list watch networkPolicy、namespace、pod等資源,因此實(shí)現(xiàn)namespace級別的策略可能會影響其性能。