CKA認(rèn)證必備:掌握K8s網(wǎng)絡(luò)策略的關(guān)鍵要點(diǎn)
網(wǎng)絡(luò)策略(NetworkPolicy)是Kubernetes中的一種資源對象,用于定義和控制Pod之間的網(wǎng)絡(luò)通信規(guī)則。它允許您在Kubernetes集群中定義詳細(xì)的網(wǎng)絡(luò)規(guī)則,以控制哪些Pod可以相互通信,以及允許或禁止的流量。網(wǎng)絡(luò)策略提供了一種實(shí)現(xiàn)細(xì)粒度網(wǎng)絡(luò)訪問控制的方式,幫助管理員和開發(fā)者確保集群中的網(wǎng)絡(luò)通信符合特定的安全性和策略需求。
一、Pod隔離的兩種類型
Pod 有兩種隔離:
- 出口隔離
- 入口隔離
它們涉及到可以建立哪些連接。這里的“隔離”不是絕對的,而是意味著“有一些限制”。另外的,“非隔離方向”意味著在所述方向上沒有限制。這兩種隔離(或不隔離)是獨(dú)立聲明的, 并且都與從一個(gè) Pod 到另一個(gè) Pod 的連接有關(guān)。
默認(rèn)情況下,一個(gè) Pod 的出口是非隔離的,即所有外向連接都是被允許的。如果有任何的 NetworkPolicy 選擇該 Pod 并在其policyTypes 中包含 Egress,則該 Pod 是出口隔離的, 稱這樣的策略適用于該 Pod 的出口。當(dāng)一個(gè) Pod 的出口被隔離時(shí), 唯一允許的來自 Pod 的連接是適用于出口的 Pod 的某個(gè) NetworkPolicy 的 egress 列表所允許的連接。這些 egress 列表的效果是相加的。
默認(rèn)情況下,一個(gè) Pod 對入口是非隔離的,即所有入站連接都是被允許的。如果有任何的 NetworkPolicy 選擇該 Pod 并在其 policyTypes 中包含 Ingress,則該 Pod 被隔離入口, 稱這種策略適用于該 Pod 的入口。當(dāng)一個(gè) Pod 的入口被隔離時(shí),唯一允許進(jìn)入該 Pod 的連接是來自該 Pod 節(jié)點(diǎn)的連接和適用于入口的 Pod 的某個(gè) NetworkPolicy 的 ingress 列表所允許的連接。這些 ingress 列表的效果是相加的。
網(wǎng)絡(luò)策略是相加的,所以不會產(chǎn)生沖突。如果策略適用于 Pod 某一特定方向的流量,Pod 在對應(yīng)方向所允許的連接是適用的網(wǎng)絡(luò)策略所允許的集合。因此,評估的順序不影響策略的結(jié)果。要允許從源 Pod 到目的 Pod 的連接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允許連接。如果任何一方不允許連接,建立連接將會失敗。
二、NetworkPolicy 配置詳解
以下是一個(gè)NetworkPolicy的示例,參閱 NetworkPolicy[1] 來了解資源的完整定義。
apiVersion:networking.k8s.io/v1
kind:NetworkPolicy
metadata:
name:test-network-policy
namespace:default#策略應(yīng)用在那個(gè)名稱空間,就說對那個(gè)命名空間的pod做限制(目標(biāo))
spec:
podSelector:#選擇匹配哪些標(biāo)簽的pod,選擇一組pod做網(wǎng)絡(luò)策略,寫{}表示該命名空間下pod
matchLabels:
role:db
policyTypes:
-Ingress#入網(wǎng),誰訪問pod(即誰訪問default名稱空間下有role=db標(biāo)簽的pod)
-Egress#出網(wǎng),role=db的pod可以訪問誰
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
三、應(yīng)用場景
它是一個(gè)kuebenetes資源,用于限制pod出入流量,提供pod級別和namespace級別網(wǎng)絡(luò)訪問控制。
- 應(yīng)用程序間的訪問控制,例如項(xiàng)目A不能訪問項(xiàng)目B的pod
- 開發(fā)環(huán)境命名空間不能訪問測試環(huán)境命名空間Pod
- 當(dāng)pod暴露到外部時(shí),需要做Pod白名單
- 多租戶網(wǎng)絡(luò)環(huán)境隔離
四、網(wǎng)絡(luò)訪問控制案例
案例1
拒絕命名空間下所有pod入、出站流量:
apiVersion:networking.k8s.io/v1
kind:NetworkPolicy
metadata:
name:deny-all
namespace:test
spec:
podSelector:{}#匹配本命名空間所有pod
policyTypes:
-Ingress
-Egress
上述網(wǎng)絡(luò)策略是禁止test命名空間的所有pod進(jìn)出流量。
在沒有創(chuàng)建網(wǎng)絡(luò)策略時(shí),test命名空間的Pod都能訪問外網(wǎng),如下:
測試
在deny-all網(wǎng)絡(luò)策略后,test命名空間下的容器就不能訪問外網(wǎng):
測試
外部Pod之間相互也不能訪問了。這里在test命名空間啟動一個(gè)nginx容器作為測試。
測試
案例2
拒絕其他命名空間pod訪問:
在生成環(huán)境中或許有這樣的需求,運(yùn)行相同命名空間的pod相互訪問,拒絕其他命名空間訪問該命名空間的所有Pod。
apiVersion:networking.k8s.io/v1
kind:NetworkPolicy
metadata:
name:deny-ingress
namespace:test
spec:
podSelector:{}#test下的所有pod
policyTypes:
-Ingress
ingress:
-from:
-podSelector:{}#匹配本命名空間所有pod
這里用兩個(gè)命名空間進(jìn)行模擬,一個(gè)是開發(fā)環(huán)境dev,一個(gè)是生成環(huán)境pro?,F(xiàn)在有這樣一個(gè)需求,生成環(huán)境的pro下的所有Pod不能訪問dev開發(fā)環(huán)境的所有Pod。
先創(chuàng)建兩個(gè)命名空間
創(chuàng)建命名空間
分別在兩個(gè)命名空間啟動三個(gè)測試pod:
查看pod的狀態(tài):
Pod的狀態(tài)
在沒有做網(wǎng)絡(luò)策略時(shí),pro命名空間下的pod可以與dev命名空間下的Pod相互通訊,如下:
測試Pod
創(chuàng)建網(wǎng)絡(luò)策略,如下:
root@k8s-master:/home/yaml# cat deny-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-ingress
namespace: pro
spec:
podSelector: {} #test下的所有pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} #匹配本命名空間所有pod
root@k8s-master:/home/yaml# kubectl apply -f deny-ingress.yaml
networkpolicy.networking.k8s.io/deny-ingress created
驗(yàn)證結(jié)果,如下,dev命名空間下的pod不能訪問pro命名空間下的所有pod,dev命名空間的pod可以相互訪問:
驗(yàn)證結(jié)果
案例3
允許其他命名空間pod訪問指定應(yīng)用 現(xiàn)在有這樣一個(gè)需求,允許其他命名空間訪問pro命名空間指定pod,pod標(biāo)簽app=web。先給pro-web pod 添加上標(biāo)簽,如下:
root@k8s-master:/home/yaml# kubectl label pods pro-web app=web -n pro
pod/pro-web labeled
root@k8s-master:/home/yaml# kubectl get pod -n pro --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pro-busybox 1/1 Running 0 16m run=pro-busybox
pro-db 1/1 Running 0 27m run=pro-db
pro-web 1/1 Running 0 36m app=web,run=pro-web
創(chuàng)建網(wǎng)絡(luò)策略,網(wǎng)絡(luò)策略內(nèi)容如下,創(chuàng)建之前把之前測試的網(wǎng)絡(luò)測試刪除。
apiVersion:networking.k8s.io/v1
kind:NetworkPolicy
metadata:
name:allow-all-nmespace
namespace:pro
spec:
podSelector:
matchLabels:
app:web#pro名稱空間下的有app=web的標(biāo)簽
policyTypes:
-Ingress
ingress:
-from:
-namespaceSelector:{}#匹配所有命名空間的pod
root@k8s-master:/home/yaml# kubectl delete -f deny-ingress.yaml
networkpolicy.networking.k8s.io "deny-ingress" deleted
root@k8s-master:/home/yaml# kubectl apply -f allow-all-namespace.yml
networkpolicy.networking.k8s.io/allow-all-nmespace created
即所有名稱空間的pod都可以訪問pro名稱空間下的app=web的pod,和K8s默認(rèn)一樣,沒意義。但和案列1搭配即可實(shí)現(xiàn)一個(gè)可訪問,一個(gè)不可訪問。單獨(dú)此規(guī)則,和K8S默認(rèn)一樣的,如下:
結(jié)合案例1拒絕命名空間所以pod入,出站流量規(guī)則,如下:
root@k8s-master:/home/yaml# cat deny-all.yml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: pro
spec:
podSelector: {} #匹配本命名空間所有pod
policyTypes:
- Ingress
- Egress
root@k8s-master:/home/yaml# kubectl apply -f deny-all.yml
networkpolicy.networking.k8s.io/deny-all created
root@k8s-master:/home/yaml# kubectl exec dev-busybox -n dev ping 10.244.36.72
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
^C
root@k8s-master:/home/yaml# kubectl exec dev-busybox -n dev ping 10.244.36.69
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING 10.244.36.69 (10.244.36.69): 56 data bytes
64 bytes from 10.244.36.69: seq=0 ttl=63 time=0.372 ms
64 bytes from 10.244.36.69: seq=1 ttl=63 time=0.369 ms
CKA真題
(1) 題目1:
真題
切換 k8s 集群環(huán)境:kubectl config use-context hk8s
Task:
在現(xiàn)有的 namespace internal 中創(chuàng)建一個(gè)名為 allow-port-from-namespace 的新 NetworkPolicy。
確保新的 NetworkPolicy 允許 namespace 中的 Pods 連接到 namespace internal 中的Pods 的 9000 端口。
進(jìn)一步確保新的NetworkPolicy:
- 不允許對沒有在監(jiān)聽端口 9000 的 Pods 的訪問
- 不允許不來自namespace internal的pods的訪問
kubectlconfiguse-contexthk8s
# 編寫一個(gè) yaml 文件,注意先輸入 ":set paste",防止復(fù)制時(shí) yaml 文件空格錯(cuò)序
apiVersion:networking.k8s.io/v1
kind:NetworkPolicy
metadata:
name:allow-port-from-namespace
namespace:internal
spec:
podSelector:{}
policyTypes:
-Ingress
ingress:
-from:
-podSelector:{}
ports:
-protocol:TCP
port:9000
# 創(chuàng)建網(wǎng)絡(luò)策略資源
kubectlapply-fnetworkpolicy.yaml
(2) 題目2
[candidate@node-1] $ kubectl config use-context hk8s
Task:
在現(xiàn)有的 namespace my-app 中創(chuàng)建一個(gè)名為 allow-port-from-namespace 的新 NetworkPolicy。
確保新的 NetworkPolicy 允許 namespace echo 中的 Pods 連接到 namespace my-app 中的 Pods 的 9000 端口。
進(jìn)一步確保新的 NetworkPolicy:
- 不允許對沒有在監(jiān)聽 端口 9000 的 Pods 的訪問
- 不允許非來自 namespace echo 中的 Pods 的訪問
kubectlconfiguse-contexthk8s
# 編寫一個(gè) yaml 文件,注意先輸入 ":set paste",防止復(fù)制時(shí) yaml 文件空格錯(cuò)序
apiVersion:networking.k8s.io/v1
kind:NetworkPolicy
metadata:
name:allow-port-from-namespace
namespace:my-app
spec:
podSelector:{}
policyTypes:
-Ingress
ingress:
-from:
-namespaceSelector:
matchLables:
app:echo
ports:
-protocol:TCP
port:9000
# 創(chuàng)建網(wǎng)絡(luò)策略資源
kubectlapply-fnetworkpolicy.yaml
參考資料:
[1]NetworkPolicy: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#networkpolicy-v1-networking-k8s-io