1. 程式人生 > 其它 >一文搞懂Kubernetes網路策略(中)

一文搞懂Kubernetes網路策略(中)

技術標籤:KubernetesDCOSkubernetesdocker

從CNCF基金會的成立,到Kubernetes社群蓬勃發展,歷經6載,17年異軍突起,在mesos、swarm等專案角逐中,拔得頭籌,繼而一統容器編排,其成功的關鍵原因可概括為以下幾點:

  • 專案領導者們的堅守與遠見
  • 社群的良好的運作與社群文化
  • 社群與企業落地的正反饋

今天zouyee為大家帶來《一文搞懂Kubernetes網路策略(中)》,其中《kuberneter排程由淺入深:框架》正在編寫中,敬請期待,當前涉及版本均為1.20.+

三、應用場景
3.1 一般場景
a. 禁止訪問指定服務
kubectl run web --image=nginx --labels app=web --expose --port 80
# 未有策略限制時,可以訪問
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- http://web
<!DOCTYPE html>
<html>
<head>

建立網路策略

# cat web-deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-deny-all
spec:
  podSelector:
    matchLabels:
      app: web
  ingress: []
  
$ kubectl apply -f web-deny-all.yaml
networkpolicy "web-deny-all" created

訪問測試

$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web
wget: download timed out

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-Z51BXeZ7-1610540947696)(https://github.com/feiskyer/kubernetes-handbook/raw/master/concepts/images/15022447799137.jpg)]

b. 限制訪問指定服務
kubectl run apiserver --image=nginx --labels app=bookstore,role=api --expose --port 80

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-8zb81ipb-1610540947700)(https://github.com/feiskyer/kubernetes-handbook/raw/master/concepts/images/15022448622429.jpg)]

建立網路策略

# cat api-allow.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow
spec:
  podSelector:
    matchLabels:
      app: bookstore
      role: api
  ingress:
  - from:
      - podSelector:
          matchLabels:
            app: bookstore
# kubectl apply -f api-allow.yaml
networkpolicy "api-allow" created

訪問測試

建立不加label的pod,預期結果,訪問被限制
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://apiserver
wget: download timed out
/ # exit
建立帶app=bookstore標籤的pod,預期結果,訪問被限制
$ kubectl run busybox --rm -ti --image=busybox --labels app=bookstore,role=frontend /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://apiserver
<!DOCTYPE html>
<html><head>
/ # exit
c. 放通訪問限制
kubectl run apiserver --image=nginx --labels app=bookstore,role=api --expose --port 80

應用a中的網路策略,限制所有流量

# cat web-deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-deny-all
spec:
  podSelector:
    matchLabels:
      app: web
  ingress: []
  
$ kubectl apply -f web-deny-all.yaml
networkpolicy "web-deny-all" created

建立放通通網路策略

# cat web-deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-all
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - {}
  
$ kubectl apply -f web-allow-all.yaml
networkpolicy "web-allow-all" created
# 需要注意deny跟allow的細微差別就是[]與{},其中{}代表
- from:
    podSelector: {}
    namespaceSelector: {}
3.2 namespace限制
a. 禁止 namespace 中非白名單流量

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-37ZH9o67-1610540947701)(https://github.com/feiskyer/kubernetes-handbook/raw/master/concepts/images/15022451724392.gif)]

建立網路策略

# cat default-deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny-all
  namespace: default
spec:
  podSelector: {}
  ingress: []
# kubectl apply -f default-deny-all.yaml

說明:

  • namespace: default 該策略部署於default

  • podSelector{}指匹配所有pod,因而該策略對default名稱空間的所有pod都有效

  • ingress未指定,因而對於所有進入流量都禁止

b. 禁止其他 namespace 流量
kubectl create namespace secondary
kubectl run web --namespace secondary --image=nginx \
    --labels=app=web --expose --port 80

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-pg0T7LVz-1610540947704)(https://github.com/feiskyer/kubernetes-handbook/raw/master/concepts/images/15022452203435.gif)]

建立網路配置

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: secondary
  name: web-deny-other-namespaces
spec:
  podSelector:
    matchLabels:
  ingress:
  - from:
    - podSelector: {}

訪問測試

# default名稱空間訪問
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web.secondary
wget: download timed out
/ # exit
# secondary名稱空間訪問
$ kubectl run busybox --rm -ti --image=busybox --namespace=secondary /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web.secondary
<!DOCTYPE html>
<html>
c. 執行所有namespace流量
kubectl run web --image=nginx --labels app=web --expose --port 80

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-jU76Cogk-1610540947705)(https://github.com/ahmetb/kubernetes-network-policy-recipes/raw/master/img/5.gif)]

建立網路策略

# cat web-allow-all-namespaces.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: default
  name: web-allow-all-namespaces
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - namespaceSelector: {}
# kubectl apply -f web-allow-all-namespaces.yaml
# kubectl create namespace secondary

說明:

  • app: web網路策略應用到該標籤pod
  • namespaceSelector: {}匹配所有名稱空間

訪問測試

# kubectl run busybox --rm -ti --image=busybox --namespace=secondary /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web.secondary
<!DOCTYPE html>
<html>
c. 指定 namespace 訪問服務
# kubectl run web --image=nginx \
    --labels=app=web --expose --port 80
# kubectl create namespace dev
# kubectl label namespace/dev purpose=testing
# kubectl create namespace prod
# kubectl label namespace/prod purpose=production

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-MpE9ybpr-1610540947706)(https://github.com/feiskyer/kubernetes-handbook/raw/master/concepts/images/15022453441751.gif)]

建立網路策略

# cat web-allow-prod.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-prod
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          purpose: production
# kubectl apply -f web-allow-prod.yaml
d. 允許其他namespace的指定pod的流量

⚠️ Kubernetes 1.11後支援podSelectornamespaceSelector的運算子操作,同時需要網路外掛支援

# kubectl run web --image=nginx \
    --labels=app=web --expose --port 80
# kubectl create namespace other
# kubectl create namespace other

建立網路策略

# cat web-allow-all-ns-monitoring.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-all-ns-monitoring
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
    - from:
      - namespaceSelector:     # 選擇namespaces中帶有team=operations標籤的pod
          matchLabels:
            team: operations  
        podSelector:           # 選擇帶有type=monitoring標籤的pod
          matchLabels:
            type: monitoring
# kubectl apply -f web-allow-all-ns-monitoring.yaml

訪問測試

kubectl run busybox --rm -ti --image=busybox  /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web.default
wget: download timed out

(訪問限制)
/ # exit

# kubectl run busybox --rm -ti --image=busybox --labels type=monitoring /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web.default
wget: download timed out

(訪問限制)

# kubectl run busybox --rm -ti --image=busybox --namespace=other /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web.default
wget: download timed out

(訪問限制)

# kubectl run busybox --rm -ti --image=busybox --namespace=other  --labels type=monitoring /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://web.default
<!DOCTYPE html>
<html>
<head>
...
(允許訪問)
3.3 允許外網訪問服務
kubectl run web --image=nginx --labels=app=web --port 80
kubectl expose pod/web --type=LoadBalancer
kubectl get svc web
NAME   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
web    LoadBalancer   10.233.54.206   <pending>     80:32548/TCP   40s
直至EXTERNAL-IP分配IP為止

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-Dn1GgTua-1610540947707)(https://github.com/feiskyer/kubernetes-handbook/raw/master/concepts/images/15022454444461.gif)]

建立網路策略

# cat web-allow-external.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-external
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - ports:
    - port: 80
    from: []
# kubectl apply -f web-allow-external.yaml
3.5 高階功能
a. 允許應用固定埠流量
# kubectl run busybox -ti --image=busybox --labels=app=apiserver /bin/sh
If you don't see a command prompt, try pressing enter.
# nohup python3 -m http.server 8001 &
# nohup python3 -m http.server 5001 &
# exit
# kubectl create service clusterip apiserver \
    --tcp 8001:8000 \
    --tcp 5001:5000

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-ZccFMn4h-1610540947708)(https://github.com/ahmetb/kubernetes-network-policy-recipes/raw/master/img/9.gif)]

建立網路策略

# cat api-allow-5000.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow-5000
spec:
  podSelector:
    matchLabels:
      app: apiserver
  ingress:
  - ports:
    - port: 5000
    from:
    - podSelector:
        matchLabels:
          role: monitoring
# kubectl apply -f api-allow-5000.yml

訪問測試

# 啟動pod未攜帶指定label時,訪問受限
# kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://apiserver:8001
wget: download timed out

/ # wget -qO- --timeout=2 http://apiserver:5001/metrics
wget: download timed out

# 啟動pod攜帶指定label時,訪問不受限
$ kubectl run busybox --rm -ti --image=busybox --labels=role=monitoring /bin/sh
/ # wget -qO- --timeout=2 http://apiserver:8001
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
...

/ # wget -qO- --timeout=2 http://apiserver:5001/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
...
b. 多標籤限制

說明:Network Policy定義一組微服務訪問某一應用,如下述示例中,一組微服務共享redis服務

kubectl run db --image=redis:4 --port 6379 --expose \
    --labels app=bookstore,role=db

以下服務共享redis服務

servicelabels
searchapp=bookstore role=search
apiapp=bookstore role=api
catalogapp=inventory role=web

建立網路策略

# cat redis-allow-services.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: redis-allow-services
spec:
  podSelector:
    matchLabels:
      app: bookstore
      role: db
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: bookstore
          role: search
    - podSelector:
        matchLabels:
          app: bookstore
          role: api
    - podSelector:
        matchLabels:
          app: inventory
          role: web
# kubectl apply -f redis-allow-services.yaml

訪問測試

$ kubectl run busybox --rm -ti --image=curl --labels=app=inventory,role=web /bin/sh

/ # nc -v -w 2 db 6379
db (10.233.27.143:6379) open

(works)

$ kubectl run busybox --rm -ti --image=curl --labels=app=other /bin/sh

/ # nc -v -w 2 db 6379
nc: db (10.233.27.143:6379): Operation timed out

(訪問受限)
3.6 控制出口流量
a. 禁止應用的出口流量
kubectl run web --image=nginx --labels app=web --expose --port 80

建立網路策略

# cat foo-deny-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: foo-deny-egress
spec:
  podSelector:
    matchLabels:
      app: foo
  policyTypes:
  - Egress
  egress: []
# kubectl apply -f foo-deny-egress.yaml

說明:

  • policyTypes: ["egress"] 該策略型別為出口流量
  • egress: [] 策略為空說明出口流量全部禁止
b. 禁止名稱空間非白名單流量

建立網路策略

# cat default-deny-all-egress.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: default-deny-all-egress
  namespace: default
spec:
  policyTypes:
  - Egress
  podSelector: {}
  egress: []
# kubectl apply -f default-deny-all-egress.yaml

說明:

  • podSelector為空,說明匹配所有pod
  • egress為空陣列,說明禁止所有符合podSelector的出口流量

後續相關內容,請檢視公眾號:DCOS