日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Kubernetes網(wǎng)絡(luò)策略,這一篇就夠了

Kubernetes網(wǎng)絡(luò)策略,這一篇就夠了

作者:容器碼頭 2020-05-14 16:35:21

云計(jì)算 目前許多組織都在采用Kubernetes來(lái)運(yùn)行他們的應(yīng)用程序。以至于有些人將Kubernetes稱(chēng)為新的數(shù)據(jù)中心操作系統(tǒng)。因此,組織開(kāi)始將Kubernetes(通??s寫(xiě)為k8s)視為關(guān)鍵任務(wù)平臺(tái),它需要包括網(wǎng)絡(luò)安全在內(nèi)的成熟業(yè)務(wù)流程。

 目前許多組織都在采用Kubernetes來(lái)運(yùn)行他們的應(yīng)用程序。以至于有些人將Kubernetes稱(chēng)為新的數(shù)據(jù)中心操作系統(tǒng)。因此,組織開(kāi)始將Kubernetes(通??s寫(xiě)為k8s)視為關(guān)鍵任務(wù)平臺(tái),它需要包括網(wǎng)絡(luò)安全在內(nèi)的成熟業(yè)務(wù)流程。

負(fù)責(zé)保護(hù)這個(gè)新平臺(tái)的網(wǎng)絡(luò)安全團(tuán)隊(duì)可能發(fā)現(xiàn)它出奇的不同。例如,默認(rèn)的Kubernetes策略是允許任何連接。

本文提供了一些關(guān)于Kubernetes網(wǎng)絡(luò)策略工作原理的簡(jiǎn)介,它們?nèi)绾闻c傳統(tǒng)防火墻策略進(jìn)行比較以及一些可以幫助你保護(hù)Kubernetes應(yīng)用程序的陷阱和最佳實(shí)踐。

Kubernetes網(wǎng)絡(luò)策略

Kubernetes提供了一種稱(chēng)為網(wǎng)絡(luò)策略的機(jī)制,可用于對(duì)部署在平臺(tái)上的應(yīng)用程序?qū)嵤┑?層分隔。網(wǎng)絡(luò)策略缺乏現(xiàn)代防火墻的高級(jí)功能,如第7層控制和威脅檢測(cè),但是它們確實(shí)提供了基本的網(wǎng)絡(luò)安全,這是一個(gè)很好的起點(diǎn)。

網(wǎng)絡(luò)策略控制Pod的通信

Kubernetes的工作負(fù)載在pod中運(yùn)行,pod由一個(gè)或多個(gè)部署在一起的容器組成。Kubernetes為每個(gè)pod分配一個(gè)IP地址,這個(gè)地址可以從其他所有pod路由,甚至可以跨底層服務(wù)器。Kubernets網(wǎng)絡(luò)策略指定pod組的訪(fǎng)問(wèn)權(quán)限,類(lèi)似于云服務(wù)中的安全組用于控制對(duì)虛擬機(jī)實(shí)例的訪(fǎng)問(wèn)。

編寫(xiě)網(wǎng)絡(luò)策略

與其他Kubernetes資源一樣,網(wǎng)絡(luò)策略可以使用一種稱(chēng)為YAML的語(yǔ)言定義。下面是一個(gè)簡(jiǎn)單的例子,它允許從負(fù)載均衡到postgres的訪(fǎng)問(wèn)。 

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.postgres 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: postgres 
  10.   ingress: 
  11.   - from: 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: balance 
  15.   policyTypes: 
  16.   - Ingress 

  

為了編寫(xiě)你自己的網(wǎng)絡(luò)策略,你需要對(duì)yaml有基本的了解。Yaml基于縮進(jìn)(使用的是空格,而不是tab)。縮進(jìn)項(xiàng)屬于其上方最接近的縮進(jìn)項(xiàng)。連字符(破折號(hào))開(kāi)始一個(gè)新的列表項(xiàng)。所有其他項(xiàng)都是映射條目。你可以在網(wǎng)上找到大量關(guān)于yaml的信息。

編寫(xiě)完策略的YAML文件后,使用kubectl創(chuàng)建策略: 

  
 
 
 
  1. kubectl create -f policy.yaml 

網(wǎng)絡(luò)策略定義

網(wǎng)絡(luò)策略定義由四個(gè)元素組成:

podSelector:將受此策略約束的pod(策略目標(biāo))。必填

policyType:指定哪些類(lèi)型的策略包含在這個(gè)策略中,ingress或egress。該項(xiàng)是可選的,但建議總是明確的指定它??蛇x

ingress:允許傳入目標(biāo)pod的流量。可選

egress:允許從目標(biāo)pod傳出的流量??蛇x

下面這個(gè)例子是從Kubernetes官網(wǎng)上改編的(將“role”改為了“app”),它指定了四個(gè)元素: 

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: test-network-policy 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: db 
  10.   policyTypes: 
  11.   - Ingress 
  12.   - Egress 
  13.   ingress: 
  14.   - from: 
  15.     - ipBlock: 
  16.         cidr: 172.17.0.0/16 
  17.         except: 
  18.         - 172.17.1.0/24 
  19.     - namespaceSelector: 
  20.         matchLabels: 
  21.           project: myproject 
  22.     - podSelector: 
  23.         matchLabels: 
  24.           role: frontend 
  25.     ports: 
  26.     - protocol: TCP 
  27.       port: 6379 
  28.   egress: 
  29.   - to: 
  30.     - ipBlock: 
  31.         cidr: 10.0.0.0/24 
  32.     ports: 
  33.     - protocol: TCP 
  34.       port: 5978 

 

 注意,你不必包含所有四個(gè)元素。podSelector是必填的,其余三個(gè)是可選的。

如果你忽略了policyType,則推斷如下:

  • 策略總是被認(rèn)為指定了一個(gè)ingress定義。如果你沒(méi)有明確的定義它,它將被視為“不允許流量“。
  • egress將由是否存在egress元素誘導(dǎo)。

為了避免錯(cuò)誤,建議總是顯式的指定policyType。

如果沒(méi)有提供ingress或egress的定義,并且根據(jù)上面的邏輯假定它們存在,策略將認(rèn)為它們是“不允許流量”。

默認(rèn)策略是允許

當(dāng)沒(méi)有定義任何策略時(shí),Kubernetes允許所有通信。所有pod都可以相互自由通信。從安全角度來(lái)看,這聽(tīng)起來(lái)可能有悖常理,但請(qǐng)記住,Kubernetes是由希望應(yīng)用程序進(jìn)行通信的開(kāi)發(fā)人員設(shè)計(jì)的。網(wǎng)絡(luò)策略是作為后來(lái)的增強(qiáng)功能添加的。

命名空間

命名空間是Kubernetes的多租戶(hù)機(jī)制,旨在將命名空間環(huán)境相互隔離,但是,命名空間的通信在默認(rèn)情況下仍然是被允許的。

與大多數(shù)Kubernetes實(shí)體一樣,網(wǎng)絡(luò)策略也位于特定的命名空間中。元數(shù)據(jù)頭部告訴Kubernetes策略屬于哪個(gè)命名空間: 

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: test-network-policy 
  5.   namespace: my-namespace 
  6. spec: 
  7. ... 

如果你沒(méi)有明確指定元數(shù)據(jù)的命名空間,它將應(yīng)用于kubectl提供的命名空間(默認(rèn)是namespace=default)。 

  
 
 
 
  1. kubectl apply -n my-namespace -f namespace.yaml 

建議顯式指定命名空間,除非你正在編寫(xiě)的策略要統(tǒng)一應(yīng)用在多個(gè)命名空間中。

策略中的podSelector元素將從策略所屬的命名空間中選擇pod(它不能從另一個(gè)命名空間選擇pod)。

ingress和egress元素中的podSelector也會(huì)選擇相同命名空間中的pod,除非你將它們和namespaceSelector一起使用。

策略命名約定

策略的名稱(chēng)在命名空間中是唯一的。一個(gè)命名空間中不能有兩個(gè)同名的策略,但是不同的命名空間可以有同名的策略。當(dāng)你想要在多個(gè)命名空間重復(fù)應(yīng)用某個(gè)策略時(shí),這非常方便。

我喜歡的策略命名方法之一是將命名空間與pod組合起來(lái),例如: 

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.postgres 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: postgres 
  10.   ingress: 
  11.   - from: 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: admin 
  15.   policyTypes: 
  16.   - Ingress 

 

標(biāo)簽

Kubernetes對(duì)象,如pod和namespace,可以附加用戶(hù)自定義標(biāo)簽。Kubernetes網(wǎng)絡(luò)策略依賴(lài)于標(biāo)簽來(lái)選擇它們應(yīng)用于的pod:

  
 
 
 
  1. podSelector: 
  2.   matchLabels: 
  3.     role: db 

或者它們應(yīng)用于的命名空間。下面的例子中選擇匹配標(biāo)簽的命名空間中的所有pod:

  
 
 
 
  1. namespaceSelector: 
  2.   matchLabels: 
  3.     project: myproject 

需要注意的一點(diǎn)是:如果你使用namespaceSelector,請(qǐng)確保所選擇的命名空間確實(shí)具有所使用的標(biāo)簽。請(qǐng)記住,像default和kube-system這樣的內(nèi)置命名空間沒(méi)有現(xiàn)成的標(biāo)簽。你可以像這樣給命名空間添加一個(gè)標(biāo)簽:

  
 
 
 
  1. kubectl label namespace default namespace=default 

元數(shù)據(jù)中的namespace是命名空間的實(shí)際名稱(chēng),而不是標(biāo)簽:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: test-network-policy 
  5.   namespace: default 
  6. spec: 
  7. ... 

源和終點(diǎn)

防火墻策略由具有源和終點(diǎn)的規(guī)則組成。Kubernetes網(wǎng)絡(luò)策略是為目標(biāo)(應(yīng)用策略的一組pod)定義的,然后為目標(biāo)指定傳入或傳出流量。再次使用相同的例子,你可以看到策略目標(biāo)——默認(rèn)命名空間中所有具有標(biāo)簽為“db:app”的pod:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: test-network-policy 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: db 
  10.   policyTypes: 
  11.   - Ingress 
  12.   - Egress 
  13.   ingress: 
  14.   - from: 
  15.     - ipBlock: 
  16.         cidr: 172.17.0.0/16 
  17.         except: 
  18.         - 172.17.1.0/24 
  19.     - namespaceSelector: 
  20.         matchLabels: 
  21.           project: myproject 
  22.     - podSelector: 
  23.         matchLabels: 
  24.           role: frontend 
  25.     ports: 
  26.     - protocol: TCP 
  27.       port: 6379 
  28.   egress: 
  29.   - to: 
  30.     - ipBlock: 
  31.         cidr: 10.0.0.0/24 
  32.     ports: 
  33.     - protocol: TCP 
  34.       port: 5978 

 

 

該策略中的ingress項(xiàng)允許到目標(biāo)pod的傳入流量。因此,ingress被解釋為“源”,目標(biāo)被解釋為各自的“終點(diǎn)”。同樣,egress被解釋為“終點(diǎn)”,目標(biāo)是各自的“源”。

Egress和DNS

當(dāng)執(zhí)行egress時(shí),必須小心不要阻止DNS,Kubernetes使用DNS將service的名稱(chēng)解釋為其IP地址。否則,這個(gè)策略將不起作用,因?yàn)槟銢](méi)有允許balance執(zhí)行DNS查找:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.balance 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: balance 
  10.   egress: 
  11.   - to: 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: postgres 
  15.   policyTypes: 
  16.   - Egress 

 

要解決它,你必須允許訪(fǎng)問(wèn)DNS服務(wù):

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.balance 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: balance 
  10.   egress: 
  11.   - to: 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: postgres 
  15.   - to: 
  16.     ports: 
  17.     - protocol: UDP 
  18.       port: 53 
  19.   policyTypes: 
  20.   - Egress 

 

“to”元素為空,它隱式選擇了所有命名空間中的所有pod,從而允許balance通過(guò)Kubernetes的DNS服務(wù)執(zhí)行DNS查找,DNS服務(wù)通常位于kube-system命名空間中。

雖然這是有效的,但它過(guò)于寬松和不安全——它允許在集群外部進(jìn)行DNS查找。

你可以分階段鎖定它:

1.通過(guò)添加一個(gè)namespaceSelector只允許在集群內(nèi)進(jìn)行DNS查找:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.balance 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: balance 
  10.   egress: 
  11.   - to: 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: postgres 
  15.   - to: 
  16.     - namespaceSelector: {} 
  17.     ports: 
  18.     - protocol: UDP 
  19.       port: 53 
  20.   policyTypes: 
  21.   - Egress 

 

2.只允許DNS在kube-system命名空間中

為此,你需要為kube-system命名空間添加一個(gè)標(biāo)簽:

  
 
 
 
  1. kubectl label namespace kube-system namespace=kube-system 

然后用namespaceSelector在策略中指定它:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.balance 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: balance 
  10.   egress: 
  11.   - to: 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: postgres 
  15.   - to: 
  16.     - namespaceSelector: 
  17.         matchLabels: 
  18.           namespace: kube-system 
  19.     ports: 
  20.     - protocol: UDP 
  21.       port: 53 
  22.   policyTypes: 
  23.   - Egress 

 

3.偏執(zhí)狂可能想更進(jìn)一步,將DNS限制為kube-system命名空間中特定的DNS服務(wù)。請(qǐng)參考下面的“通過(guò)命名空間和pod過(guò)濾”章節(jié)。

另一種選擇是在命名空間級(jí)別允許DNS,這樣就不需要為每個(gè)服務(wù)指定它了:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.dns 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: {} 
  8.   egress: 
  9.   - to: 
  10.     - namespaceSelector: {} 
  11.     ports: 
  12.     - protocol: UDP 
  13.       port: 53 
  14.   policyTypes: 
  15.   - Egress 

空的podSelector選擇該命名空間中的所有pod。

第一個(gè)匹配和規(guī)則順序

防火墻管理員知道對(duì)數(shù)據(jù)包采取的操作(允許或拒絕)由與其匹配的第一個(gè)規(guī)則決定。但是在Kubernetes中,策略的順序并不重要。默認(rèn)的行為是,當(dāng)沒(méi)有定義策略時(shí),允許所有通信,因此所有pod之間可以彼此通信。一旦定義了策略,每個(gè)至少被一個(gè)策略選擇的pod,將根據(jù)選擇它的策略的并集(邏輯或)進(jìn)行隔離:

沒(méi)有被任何策略選中的pod繼續(xù)保持開(kāi)放。你可以通過(guò)定義cleanup規(guī)則來(lái)改變這個(gè)行為。

Cleanup規(guī)則(拒絕)

防火墻策略通常通過(guò)any-any-any-deny規(guī)則來(lái)丟棄所有非顯式允許的流量。Kubernetes沒(méi)有拒絕操作,但是你可以使用一個(gè)常規(guī)的規(guī)則來(lái)實(shí)現(xiàn)相同的效果,該策略指定policyTypes=Ingress,但是省略了實(shí)際ingress的定義,這被解釋為“不允許進(jìn)入”。

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: deny-all 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: {} 
  8.   policyTypes: 
  9.   - Ingress 

 

該策略選擇命名空間中的所有pod作為源,未定義ingress——這意味著不允許流量進(jìn)入。

類(lèi)似的,你可以拒絕來(lái)自一個(gè)命名空間的所有出站流量:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: deny-all-egress 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: {} 
  8.   policyTypes: 
  9.   - Egress 

 

請(qǐng)記住,任何其他允許訪(fǎng)問(wèn)命名空間中pod的策略都將優(yōu)先于此拒絕策略——相當(dāng)于防火墻中將允許策略添加到拒絕策略之上。

Any-Any-Any-Allow

通過(guò)使用一個(gè)空的ingress元素修改上面的deny-all策略,可以創(chuàng)建一個(gè)allow-all策略:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: allow-all 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: {} 
  8.   ingress:  
  9.   - {} 
  10.   policyTypes: 
  11.   - Ingress 

 

這允許所有命名空間中的所有pod(和IP)到默認(rèn)命名空間中的任何pod的通信。這是默認(rèn)行為,因此通常不需要這么做。但是,為了查找問(wèn)題,暫時(shí)覆蓋所有其他規(guī)則可能很有用。

你可以縮小此范圍,僅允許訪(fǎng)問(wèn)默認(rèn)命名空間中的一組特定的pod:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: allow-all-to-balance 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: balance 
  10.   ingress:  
  11.   - {} 
  12.   policyTypes: 
  13.   - Ingress 

 

下面的策略允許任何入站和出站流量(包括訪(fǎng)問(wèn)集群外的任何IP):

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: allow-all 
  5. spec: 
  6.   podSelector: {} 
  7.   ingress: 
  8.   - {} 
  9.   egress: 
  10.   - {} 
  11.   policyTypes: 
  12.   - Ingress 
  13.   - Egress 

 

 

組合多個(gè)策略

策略在三個(gè)級(jí)別上使用邏輯或進(jìn)行組合。每個(gè)pod根據(jù)應(yīng)用于它的所有策略的并集決定是否允許通信。

1.在“from”和“to”項(xiàng)中,你可以定義三種類(lèi)型的項(xiàng),他們通過(guò)“或”進(jìn)行組合:

  • namespaceSelector——選擇一整個(gè)命名空間
  • podSelector——選擇pod
  • ipBlock——選擇一個(gè)子網(wǎng)

你可以在from/to下定義任意數(shù)量的項(xiàng)(即使是相同類(lèi)型也可以定義多條),它們將通過(guò)邏輯或組合在一起:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.postgres 
  5.   namespace: default 
  6. spec: 
  7.   ingress: 
  8.   - from: 
  9.     - podSelector: 
  10.         matchLabels: 
  11.           app: indexer 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: admin 
  15.   podSelector: 
  16.     matchLabels: 
  17.       app: postgres 
  18.   policyTypes: 
  19.   - Ingress 

 

2.在一個(gè)策略中,ingress策略可以有多個(gè)“from”項(xiàng),它們通過(guò)邏輯或組合在一起。同樣,egress策略可以有多個(gè)“to”項(xiàng),它們也通過(guò)邏輯或組合在一起:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.postgres 
  5.   namespace: default 
  6. spec: 
  7.   ingress: 
  8.   - from: 
  9.     - podSelector: 
  10.         matchLabels: 
  11.           app: indexer 
  12.   - from: 
  13.     - podSelector: 
  14.         matchLabels: 
  15.           app: admin 
  16.   podSelector: 
  17.     matchLabels: 
  18.       app: postgres 
  19.   policyTypes: 
  20.   - Ingress 

 

3.多個(gè)策略也通過(guò)邏輯或組合在一起。

但是當(dāng)組合策略時(shí),這里有一些限制:Kubernetes只能組合policyType(ingress或egress)不同的策略,多個(gè)策略都指定ingress(或egress)將會(huì)互相覆蓋。

命名空間之間的通信

默認(rèn)情況下,命名空間間的通信是允許的。你可以使用deny-all策略來(lái)改變它,以阻止從或者到該命名空間的通信。

如果你阻止了對(duì)某個(gè)命名空間的訪(fǎng)問(wèn),可以使用namespaceSelector允許來(lái)自一個(gè)特定的命名空間的訪(fǎng)問(wèn)。

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: database.postgres 
  5.   namespace: database 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: postgres 
  10.   ingress: 
  11.   - from: 
  12.     - namespaceSelector: 
  13.         matchLabels: 
  14.           namespace: default 
  15.   policyTypes: 
  16.   - Ingress 

 

這允許default命名空間中的所有pod訪(fǎng)問(wèn)database命名空間中的postgres pod。但是,如果只想允許default命名空間中特定的pod訪(fǎng)問(wèn)postgres該怎么辦呢?

通過(guò)namespace和pod聯(lián)合過(guò)濾

Kubernetes 1.11及以上允許你將namespaceSelector和podSelector通過(guò)邏輯與組合在一起:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: database.postgres 
  5.   namespace: database 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: postgres 
  10.   ingress: 
  11.   - from: 
  12.     - namespaceSelector: 
  13.         matchLabels: 
  14.           namespace: default 
  15.       podSelector: 
  16.         matchLabels: 
  17.           app: admin 
  18.   policyTypes: 
  19.   - Ingress 

 

為什么這被解釋為“與”,而不是“或”呢?

請(qǐng)注意,podSelector不是以破折號(hào)開(kāi)頭的,在yaml中這意味著,podSelector與前面的namespaceSelector屬于同一個(gè)列表項(xiàng),因此它們通過(guò)邏輯與進(jìn)行組合。如果你在podSelector前面添加一個(gè)破折號(hào),將創(chuàng)建一個(gè)新的列表項(xiàng),這將與前面的namespaceSelector通過(guò)邏輯或組合。要在所有命名空間中選擇具有特定標(biāo)簽的pod,可以指定一個(gè)空的namespaceSelector:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: database.postgres 
  5.   namespace: database 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: postgres 
  10.   ingress: 
  11.   - from: 
  12.     - namespaceSelector: {} 
  13.       podSelector: 
  14.         matchLabels: 
  15.           app: admin 
  16.   policyTypes: 
  17.   - Ingress 

 

多個(gè)標(biāo)簽通過(guò)邏輯與組合

具有多個(gè)對(duì)象(主機(jī)、網(wǎng)絡(luò)、組...)的防火墻規(guī)則被解釋為邏輯或。例如,如果數(shù)據(jù)包的源匹配HOST_1或HOST_2,則應(yīng)用此規(guī)則:

與之相反的是,在Kubernetes中,podSelector和namespaceSelector中的多個(gè)標(biāo)簽通過(guò)邏輯與進(jìn)行組合。例如,這將選擇同時(shí)具有標(biāo)簽role=db和version=v2的pod:

  
 
 
 
  1. podSelector: 
  2.   matchLabels: 
  3.     role: db 
  4.     version: v2 

相同的邏輯適用所有類(lèi)型的選擇器:策略目標(biāo)的選擇器、pod的選擇器、命名空間的選擇器。

子網(wǎng)和IP地址(ipBlock)

防火墻使用vlan、ip和子網(wǎng)來(lái)分割網(wǎng)絡(luò)。在Kubernetes中,pod的IP是自動(dòng)分配的,并且可能經(jīng)常變動(dòng),因此網(wǎng)絡(luò)策略使用標(biāo)簽來(lái)選擇pod和命名空間。子網(wǎng)(ipBlock)用于ingress或egress連接(南北向)。例如,下面這個(gè)策略允許default命名空間中的所有pod訪(fǎng)問(wèn)谷歌的DNS服務(wù):

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: egress-dns 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: {} 
  8.   policyTypes: 
  9.   - Egress 
  10.   egress: 
  11.   - to: 
  12.     - ipBlock: 
  13.         cidr: 8.8.8.8/32 
  14.     ports: 
  15.     - protocol: UDP 
  16.       port: 53 

 

本例中空的podSelector表示“選擇該命名空間中的所有pod”。該策略只允許訪(fǎng)問(wèn)8.8.8.8,這意味著它拒絕訪(fǎng)問(wèn)其他任何IP。因此,實(shí)際上,你已經(jīng)阻止了對(duì)Kubernetes內(nèi)部DNS服務(wù)的訪(fǎng)問(wèn)。如果你仍然想允許它,需要顯式的指定它。

通常ipBlock和podSelector是互斥的,因?yàn)橥ǔD阍趇pBlock中不使用內(nèi)部pod IP。如果你使用內(nèi)部pod IP指定ipBlock,它實(shí)際上將允許與具有這些ip的pod進(jìn)行通信。但是在實(shí)踐中并不知道該用哪些IP,這就是為什么不應(yīng)該用IP來(lái)選擇pod。

下面這個(gè)策略中包含所有IP,并允許訪(fǎng)問(wèn)所有其它pod:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: egress-any 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: {} 
  8.   policyTypes: 
  9.   - Egress 
  10.   egress: 
  11.   - to: 
  12.     - ipBlock: 
  13.         cidr: 0.0.0.0/0 

 

你可以通過(guò)排除內(nèi)部IP來(lái)只允許訪(fǎng)問(wèn)外部IP。例如,如果pod的子網(wǎng)是10.16.0.0/14:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: egress-any 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: {} 
  8.   policyTypes: 
  9.   - Egress 
  10.   egress: 
  11.   - to: 
  12.     - ipBlock: 
  13.         cidr: 0.0.0.0/0 
  14.         except: 
  15.         - 10.16.0.0/14 

 

 

端口和協(xié)議

pod通常只監(jiān)聽(tīng)一個(gè)端口,這意味著你可以簡(jiǎn)單的在策略中省略端口,默認(rèn)允許任何端口。但是最好將策略設(shè)置為受限的,顯式的指定端口:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.postgres 
  5.   namespace: default 
  6. spec: 
  7.   ingress: 
  8.   - from: 
  9.     - podSelector: 
  10.         matchLabels: 
  11.           app: indexer 
  12.     - podSelector: 
  13.         matchLabels: 
  14.           app: admin 
  15.     ports: 
  16.       - port: 443 
  17.         protocol: TCP 
  18.       - port: 80 
  19.         protocol: TCP 
  20.   podSelector: 
  21.     matchLabels: 
  22.       app: postgres 
  23.   policyTypes: 
  24.   - Ingress 

 

請(qǐng)注意,端口應(yīng)用于它們所在的“to”或“from”子句中的所有項(xiàng)。如果你想為不同的項(xiàng)指定不同的端口,你可以將ingress或egress拆分為多個(gè)“to”或“from”,每個(gè)都有自己的端口:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.postgres 
  5.   namespace: default 
  6. spec: 
  7.   ingress: 
  8.   - from: 
  9.     - podSelector: 
  10.         matchLabels: 
  11.           app: indexer 
  12.     ports: 
  13.      - port: 443 
  14.        protocol: TCP 
  15.   - from: 
  16.     - podSelector: 
  17.         matchLabels: 
  18.           app: admin 
  19.     ports: 
  20.      - port: 80 
  21.        protocol: TCP 
  22.   podSelector: 
  23.     matchLabels: 
  24.       app: postgres 
  25.   policyTypes: 
  26.   - Ingress 

 

端口的默認(rèn)行為:

  • 如果完全省略端口,則表示所有端口和所有協(xié)議
  • 如果省略協(xié)議,則默認(rèn)為T(mén)CP
  • 如果省略端口,則默認(rèn)為所有端口

最佳實(shí)踐:不要依賴(lài)默認(rèn)行為,顯式的指明。

注意你必須使用pod的端口,而不是service的端口。

策略是為pod定義的還是為service定義的?

當(dāng)一個(gè)pod訪(fǎng)問(wèn)Kubernetes中另一個(gè)pod時(shí),它通常要通過(guò)service,service是一個(gè)虛擬的負(fù)載均衡器,它將流量轉(zhuǎn)發(fā)到實(shí)現(xiàn)該服務(wù)的pod上。你可能會(huì)以為網(wǎng)絡(luò)策略是控制對(duì)service的訪(fǎng)問(wèn)的,但事實(shí)并非如此。Kubernetes網(wǎng)絡(luò)策略是應(yīng)用于pod的端口,而非service的端口。

例如,如果一個(gè)service監(jiān)聽(tīng)80端口,但是它將流量轉(zhuǎn)發(fā)到監(jiān)聽(tīng)8080端口的pod上,你需要在網(wǎng)絡(luò)策略中指定8080端口。

這種設(shè)計(jì)不是最優(yōu)的,因?yàn)楫?dāng)有人更改服務(wù)的內(nèi)部工作方式時(shí)(如pod正在監(jiān)聽(tīng)的端口),你需要更新網(wǎng)絡(luò)策略。

顯然,有一種解決方案可以解決這個(gè)問(wèn)題,即使用命名端口,而不是硬編碼的數(shù)字端口:

  
 
 
 
  1. apiVersion: networking.k8s.io/v1 
  2. kind: NetworkPolicy 
  3. metadata: 
  4.   name: default.allow-hello 
  5.   namespace: default 
  6. spec: 
  7.   podSelector: 
  8.     matchLabels: 
  9.       app: hello 
  10.   policyTypes: 
  11.   - Ingress 
  12.   ingress: 
  13.   - from: 
  14.     - podSelector: 
  15.         matchLabels: 
  16.           run: curl 
  17.     ports: 
  18.     - port: my-http 

你需要在pod的定義中指定這個(gè)端口的名字:

  
 
 
 
  1. apiVersion: extensions/v1beta1 
  2. kind: Deployment 
  3. metadata: 
  4.   labels: 
  5.     app: hello 
  6.   name: hello 
  7. spec: 
  8.   selector: 
  9.     matchLabels: 
  10.       app: hello 
  11.   template: 
  12.     metadata: 
  13.       labels: 
  14.         app: hello 
  15.     spec: 
  16.       containers: 
  17.       - image: gcr.io/hello-minikube-zero-install/hello-node 
  18.         imagePullPolicy: Always 
  19.         name: hello-node 
  20.         ports: 
  21.         - containerPort: 8080 
  22.           name: my-http 

這樣就將網(wǎng)絡(luò)策略和pod解耦了。

Ingress

術(shù)語(yǔ)“ingress”在Kubernetes中有兩種含義:

  1. ingress網(wǎng)絡(luò)策略允許你控制其他pod或外部IP對(duì)pod的訪(fǎng)問(wèn)
  2. Kubergess的ingress是一種配置外部負(fù)載均衡器路由流量到集群內(nèi)部的方式

你可以編寫(xiě)一個(gè)k8s網(wǎng)絡(luò)策略限制來(lái)自Kubernetes ingress的訪(fǎng)問(wèn),但在大多數(shù)情況下這不是很有用,因?yàn)樗豢刂曝?fù)載均衡器的內(nèi)部IP。為了控制可以訪(fǎng)問(wèn)集群的外部子網(wǎng),你需要在外部實(shí)施點(diǎn)(如負(fù)載均衡本身或負(fù)載均衡前面的防火墻)配置訪(fǎng)問(wèn)控制。

需要同時(shí)定義ingress和egress么?

簡(jiǎn)單的回答是肯定的——為了允許pod A訪(fǎng)問(wèn)pod B,你需要允許pod A通過(guò)egress策略創(chuàng)建出站連接,并允許pod B通過(guò)ingress策略接受入站連接。

然而,實(shí)際上,你可能對(duì)兩個(gè)方向中的一個(gè)使用默認(rèn)的允許策略。

如果源pod被一個(gè)或多個(gè)egress策略選中,則將根據(jù)策略聯(lián)合對(duì)其進(jìn)行限制,在這種情況下你需要明確允許它連接到目標(biāo)pod。如果pod不被任何策略選中,則它默認(rèn)允許所有的出站流量。

同樣,被一個(gè)或多個(gè)ingress策略選中的目標(biāo)pod,也會(huì)受到策略的聯(lián)合限制,在這種情況下你必須明確允許它接受來(lái)自源pod的流量。如果pod沒(méi)有被任何策略選中,則它默認(rèn)允許所有入站流量。

hostNetwork陷阱

Kubernetes通常在自己的隔離網(wǎng)絡(luò)中運(yùn)行pod,然而,你可以指定Kubernetes在主機(jī)上運(yùn)行pod:

  
 
 
 
  1. hostNetwork: true 

這樣會(huì)完全繞開(kāi)網(wǎng)路策略,pod像主機(jī)上運(yùn)行的其他任何進(jìn)程一樣進(jìn)行通信。

流量日志

Kubernetes網(wǎng)絡(luò)策略不能生成流量日志。這很難知道策略是不是像預(yù)期一樣工作。這也是安全分析方面的主要限制。

控制到外部服務(wù)的流量

Kubernetes網(wǎng)絡(luò)策略不允許你為egress指定完全限定的域名(DNS)。當(dāng)試圖控制到無(wú)固定IP的外部站點(diǎn)(如aws.com)的流量時(shí),這是一個(gè)限制。

策略驗(yàn)證

防火墻將警告甚至拒絕接受無(wú)效的策略。Kubernetes也做了一些驗(yàn)證。當(dāng)使用kubectl定義網(wǎng)絡(luò)策略時(shí),Kubernetes可能會(huì)告訴你策略無(wú)效并且拒絕接受。在其它情況下,Kubernetes將接受策略并修改它缺失的細(xì)節(jié),你可以通過(guò)以下命令查看它:

kubernetes get networkpolicy  -o yaml

請(qǐng)注意,Kubernetes的驗(yàn)證不是無(wú)懈可擊的,它可能允許策略中出現(xiàn)某些類(lèi)型的錯(cuò)誤。

執(zhí)行

Kubernetes本身并不執(zhí)行網(wǎng)絡(luò)策略,它只是一個(gè)API網(wǎng)關(guān),它將執(zhí)行的艱巨工作傳遞給一個(gè)稱(chēng)為容器網(wǎng)絡(luò)接口(CNI)的底層系統(tǒng)。在沒(méi)有合適CNI的Kubernetes集群中定義策略就像在沒(méi)有安裝防火墻的服務(wù)器上定義防火墻規(guī)則一樣。你必須確保擁有具有安全功能的CNI,或者,對(duì)于托管的Kubernetes平臺(tái),你需要顯式的啟用將為你安裝CNI的網(wǎng)絡(luò)策略。

請(qǐng)注意,如果CNI不支持,你定義了一個(gè)網(wǎng)絡(luò)策略,Kubernetes不會(huì)向你告警。

有狀態(tài)還是無(wú)狀態(tài)?

目前所有的Kubernetes CNI都是有狀態(tài)的,這使得pod能在它發(fā)起的TCP連接上接收應(yīng)答,而不必為應(yīng)答打開(kāi)高端口。我不知道有沒(méi)有Kubernetes標(biāo)準(zhǔn)保證狀態(tài)性。

高級(jí)安全策略管理

以下是一些針對(duì)Kubernetes實(shí)施更高級(jí)的網(wǎng)絡(luò)策略的方法:

  1. 服務(wù)網(wǎng)格設(shè)計(jì)模式使用sidecar在服務(wù)級(jí)別提供更高級(jí)的遙測(cè)和流量控制。有關(guān)示例,請(qǐng)參考Istio。
  2. 一些CNI提供商已經(jīng)將他們的工具擴(kuò)展到了Kubernetes網(wǎng)絡(luò)策略之外。
  3. Tufin Orca——用于實(shí)現(xiàn)Kubernetes網(wǎng)絡(luò)策略的可視化和自動(dòng)化。

總結(jié)

Kubernetes網(wǎng)絡(luò)策略為集群劃分提供了一種很好的方法,但是它們不直觀(guān)并且有許多注意的地方。我相信,由于這種復(fù)雜性,一定有許多集群在他們的策略中存在“bug”。可能的解決方案是自動(dòng)化策略定義或其他分割方法。同時(shí),希望本文對(duì)澄清和解決你可能遇到的問(wèn)題有所幫助。


本文標(biāo)題:Kubernetes網(wǎng)絡(luò)策略,這一篇就夠了
分享鏈接:http://www.5511xx.com/article/dhogoog.html