阿里雲容器計算服務ACS基於Kubernetes網路原則(Network Policy)提供策略層級的網路控制。如果您希望在IP地址或者連接埠層面控制網路流量,您可以為叢集中特定應用使用網路原則。本文介紹如何使用ACS叢集的網路原則及常用的使用情境。
適用範圍
僅支援計算類型為通用型和效能型的CPU Pod。
僅支援用於IPv4,不支援IPv6。
注意事項
如需通過控制台的方式使用網路原則功能,請到配額平台提交申請。
如果通過命令列方式使用網路原則功能,無需申請成為白名單使用者。
NetworkPolicy規則允許通過LabelSelector選擇Namespace或者Pod。但當Pod中的NetworkPolicy數量增大時,不僅會使規則生效時間延長,而且大量的NetworkPolicy規則也會對您的叢集管理、問題排查帶來困擾,因此建議您叢集內的NetworkPolicy數量小於40個。
步驟一:開啟網路原則
安裝組件Poseidon。
登入容器計算服務控制台,在左側導覽列選擇集群列表。
在集群列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇运维管理 > 组件管理。
在組件管理頁面,單擊網路頁簽,在Poseidon組件所在卡片的右下方,單擊安裝。
在安裝組件 Poseidon頁面,選中啟用 NetworkPolicy,然後單擊確認。

組件安裝成功後,會在卡片右上方出現已安裝字樣。
在Pod annotation配置啟用NetworkPolicy。
對需要使用NetworkPolicy的容器,必須配置下面annotation中的註解
network.alibabacloud.com/enable-network-policy-agent: "true",樣本如下:apiVersion: v1 kind: Pod metadata: annotations: network.alibabacloud.com/enable-network-policy-agent: "true" name: example namespace: default spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: example
步驟二:建立可以被其他Pod正常訪問的Nginx測試應用
控制台
在集群列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇工作负载 > 无状态。
在无状态頁面,單擊使用鏡像建立。
在建立設定精靈頁面中,建立一個名稱為nginx的應用,並通過Service將其公開。配置完成後,單擊建立。
本樣本的Nginx應用僅需配置以下配置項,其他配置項選擇預設配置。關於更多配置說明,請參見建立無狀態工作負載Deployment。
頁面
配置項
說明
樣本值
應用基本資料
應用程式名稱
自訂名稱。
nginx
副本數量
按需選擇。
1
容器配置
鏡像名稱
單擊選擇鏡像,選擇所需的鏡像並單擊確定。
本例選擇官方Nginx鏡像,可以在搜尋頁簽中,選擇製品中心,然後在文字框中輸入nginx進行搜尋,並選擇對應的鏡像版本。
進階配置
服務(Service)
在服務(Service)右側,單擊建立設定服務配置項。
名稱:nginx
類型:
負載平衡
公網訪問
建立SLB
連接埠映射:
名稱:nginx
服務連接埠:80
容器連接埠:80
協議:TCP
再次在無狀態頁面,單擊使用鏡像建立。在建立設定精靈頁面中,建立用於測試訪問名稱為busybox的用戶端應用,用於測試訪問上一步中建立的名為nginx的Service。
本樣本的busybox用戶端應用僅需配置以下配置項,其他配置項選擇預設配置。關於更多配置說明,請參見使用鏡像建立無狀態Deployment應用。
頁面
配置項
說明
樣本值
應用基本資料
應用程式名稱
自訂名稱。
busybox
副本數量
按需取值。
1
容器配置
鏡像名稱
直接輸入鏡像地址。
本例選擇直接輸入鏡像地址
registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2容器啟動項
無
選中stdin和tty
驗證busybox用戶端應用是否可以訪問nginx Service。
在無狀態頁面,找到並單擊busybox名稱。
在容器組頁簽下的busybox-{hash值}容器組右側,單擊終端。
在busybox的命令列終端中執行
wget nginx測試訪問Nginx。說明當出現200的返回資訊時,說明您可以在busybox中訪問nginx Service。
kubectl
建立一個Nginx的應用,並通過名稱為nginx的Service與其通訊。
建立Nginx應用:
kubectl run nginx --image=nginx預期輸出:
pod/nginx created查看Pod是否啟動:
kubectl get pod預期輸出:
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 45s建立名為nginx的Service:
kubectl expose pod nginx --port=80預期輸出:
service/nginx exposed查看Service:
kubectl get service預期輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 172.XX.XX.1 <none> 443/TCP 30m nginx ClusterIP 172.XX.XX.48 <none> 80/TCP 12s建立名稱為busybox的Pod,訪問名為nginx的Service。
kubectl run busybox --rm -ti --image=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /bin/sh預期輸出:
If you don't see a command prompt, try pressing enter. / # / #擷取Nginx:
If you don't see a command prompt, try pressing enter. / # / # wget nginx # wget nginx需要輸入到此處。預期輸出:
Connecting to nginx (172.XX.XX.48:80) saving to 'index.html' index.html 100% |****************************************************************************************************************************************************| 612 0:00:00 ETA 'index.html' saved
步驟三:使用網路原則
以下幾種情境均支援使用網路原則,您可以按需選擇。
情境一:通過網路原則限制服務只能被帶有特定標籤的應用訪問
控制台
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
在網路原則頁面上方,選擇放置網路原則的命名空間,本樣本選擇default,然後在頁面右上方,單擊建立,在建立面板中配置網路原則。
配置項
說明
樣本值
名稱
自訂網路原則的名稱。
access-nginx
Pod選取器
單擊+ 選擇工作負載添加標籤,設定使用網路原則的Pod。
說明如果Pod選取器設定為空白,則對命名空間下所有Pod生效。
本文樣本設定如下:
設定類型為:無狀態
設定工作負載為:nginx
設定標籤為:app=nginx
來源
每個網路原則可包含一個來源(ingress規則)的白名單列表。 每個規則都允許同時匹配來源規則和特定連接埠部分的流量。
規則:
podSelector:此選取器將在與網路原則同命名空間中選擇特定的 Pod,並將其允許作為入站流量來源。
namespaceSelector:此選取器將選擇特定的命名空間,並將所有Pod 用作其入站流量來源。
ipBlock:此選取器將選擇特定的IP CIDR範圍以用作入站流量來源。
連接埠:支援TCP和UDP協議。
說明如果不添加任何規則,表示不允許訪問任何Pod與選擇的Pod進行訪問。
如果叢集啟用IPvlan,您無法通過ipBlock來限制Pod網段流量,您需要使用podSelector。
本樣本不添加任何來源規則。
去向
每個網路原則可包含一個egress規則的白名單列表。每個規則都允許匹配去向規則和特定連接埠部分的流量。
規則:
podSelector:此選取器將在與網路原則同命名空間中選擇特定的Pod,並將其允許作為出站流量目的地。
namespaceSelector:此選取器將選擇特定的命名空間,並將所有Pod用作其出站流量目的地。
ipBlock:此選取器將選擇特定的IP CIDR範圍作為出站流量目的地。
連接埠:支援TCP和UDP協議。
說明如果叢集啟用IPvlan,您無法通過ipBlock來限制Pod網段流量,您需要使用podSelector。
本樣本不添加任何去向規則。
單擊下一步,然後單擊確定。
在busybox命令列終端執行
wget nginx命令,測試與nginx Service的通訊。具體操作,請參見步驟5。說明因為網路原則沒有允許busybox訪問,所以訪問會逾時。

修改網路原則為允許busybox的應用訪問。
在網路原則列表中,找到access-nginx網路原則並在其右側,單擊編輯。
添加來源規則。
在來源右側,單擊+添加,並繼續以下操作:
在規則右側,單擊+添加。添加podSelector的訪問,規則設定如下:
配置項
樣本值
選取器
podSelector
類型
無狀態
工作負載
busybox
標籤
app=busybox
在連接埠右側,單擊+添加。連接埠設定如下:
配置項
樣本值
協議
TCP
連接埠
80
單擊下一步,然後單擊確定。
執行
wget -O /dev/null nginx命令,測試修改網路原則後busybox與nginx的通訊。說明網路原則增加busybox應用的規則後,busybox可以正常訪問Nginx。

kubectl
使用以下YAML模板並執行命令
vim policy.yaml,建立名為policy.yaml檔案。vim policy.yaml以下為YAML檔案內容。
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: access-nginx spec: podSelector: matchLabels: run: nginx ingress: - from: - podSelector: matchLabels: access: "true"根據上述的policy.yaml檔案建立網路原則。
kubectl apply -f policy.yaml預期輸出:
networkpolicy.networking.k8s.io/access-nginx created當沒有定義訪問標籤時,測試訪問名為nginx的Service,請求會逾時,無法訪問。
kubectl run busybox --rm -ti --image=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /bin/sh測試訪問名為nginx的Service:
wget nginx預期輸出:
Connecting to nginx (172.19.XX.XX:80) wget: can't connect to remote host (172.19.XX.XX): Connection timed out定義訪問標籤。
kubectl run busybox --rm -ti --labels="access=true" --image=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /bin/sh測試訪問nginx Service:
wget nginx預期輸出:
Connecting to nginx (172.21.XX.XX:80) saving to 'index.html' index.html 100% |****************************************************************************************************************************************************| 612 0:00:00 ETA 'index.html' saved串連nginx的進度為100%時,說明請求成功,可以正常訪問nginx服務。
情境二:通過網路原則限制可訪問公網服務的來源IP網段
控制台
為nginx Service設定網路原則。相關配置,請參見通過網路原則限制服務只能被帶有特定標籤的應用訪問。
在服務列表中的外部端點列下,查看步驟二:建立可以被其他Pod正常訪問的Nginx測試應用中nginx Service的公網訪問地址(47.xxx.xx.x),並在瀏覽器中訪問該地址。
說明由於已為nginx添加網路原則,預設訪問nginx失敗。
通過網路原則增加允許訪問的網段來允許用戶端訪問。
擷取原生IP地址。
在網路原則列表中,找到access-nginx網路原則並在其右側,單擊編輯,然後在編輯面板中修改規則。
在來源右側,單擊+添加,並繼續以下操作:
在規則右側,單擊+添加。規則中增加原生IP地址的訪問:
配置項
樣本值
選取器
ipBlock
cidr
<原生IP地址>/32
例如42.xx.xx.xx/32
在規則右側,單擊+添加。規則中增加阿里雲SLB的健全狀態檢查網段的訪問:
配置項
樣本值
選取器
ipBlock
cidr
100.0.0.0/8
在連接埠右側,單擊+添加。連接埠設定如下:
配置項
樣本值
協議
TCP
連接埠
80

單擊下一步,然後單擊確定。
在服務列表中的外部端點列下,單擊外部端點的IP,訪問nginx外部端點(47.xxx.xx.x:80)。
說明增加網路原則後用戶端可以通過公網SLB訪問nginx。
kubectl
為上述名為nginx的應用建立阿里雲SLB服務,指定
type=LoadBalancer來向外網使用者暴露nginx服務。vim nginx-service.yamlnginx-service.yaml檔案模板如下。
# 將以下YAML內容粘貼至nginx-service.yaml中。 apiVersion: v1 kind: Service metadata: labels: run: nginx name: nginx-slb spec: externalTrafficPolicy: Local ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer根據上述的nginx-service.yaml檔案建立網路原則。
kubectl apply -f nginx-service.yaml預期輸出:
service/nginx-slb created查看應用是否對外暴露Nginx服務:
kubectl get service nginx-slb預期輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-slb LoadBalancer 172.19.xx.xxx 47.110.xxx.xxx 80:32240/TCP 8m訪問剛剛建立的SLB的IP地址47.110.xxx.xxx,訪問失敗。
wget 47.110.xxx.xxx預期輸出:
--2018-11-21 11:46:05-- http://47.110.xx.xxx/ Connecting to 47.110.XX.XX:80... failed: Connection refused.說明訪問失敗的原因是:
配置的nginx Service只能被帶有特定標籤即
access=true的應用訪問。訪問SLB的IP地址,是從外部存取Kubernetes,與通過網路原則限制服務只能被帶有特定標籤的應用訪問不同。
解決方案:修改網路原則,增加允許訪問的來源IP位址區段。
查看本地的IP地址。
curl myip.ipip.net預期輸出:
當前IP:10.0.x.x來自於:中國 北京 北京 # 此處僅為樣本,具體請以實際裝置為準。修改已經建立的policy.yaml檔案。
vim policy.yaml將policy.yaml檔案修改為如下內容:
# 以下為YAML檔案內容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: access-nginx spec: podSelector: matchLabels: run: nginx ingress: - from: - podSelector: matchLabels: access: "true" - ipBlock: cidr: 100.64.0.0/10 - ipBlock: cidr: 10.0.0.1/24 # 本地IP地址,此處僅為樣本,具體請以實際裝置為準。根據policy.yaml檔案建立網路原則。
kubectl apply -f policy.yaml預期輸出:
networkpolicy.networking.k8s.io/access-nginx unchanged說明有些網路的出口有多個IP地址,這裡請使用/24的位址範圍。
SLB健全狀態檢查地址在
100.64.0.0/10位址區段內,因此請務必配置100.64.0.0/10。
建立Nginx服務。
kubectl run busybox --rm -ti --labels="access=true" --image=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /bin/sh訪問Nginx服務:
wget 47.110.XX.XX預期輸出:
Connecting to 47.110.XX.XX (47.110.XX.XX:80) index.html 100% |***********************************************************| 612 0:00:00 ETA串連進度顯示100%時,說明成功訪問Nginx服務。
情境三:通過網路原則限制一個Pod只能訪問指定地址
控制台
本文以www.aliyun.com和registry.aliyuncs.com為例,說明通過設定網路原則一個Pod只能訪問registry.aliyuncs.com。
通過Ping命令查詢registry.aliyuncs.com地址綁定的IP地址(120.55.XXX.XXX)。

在網路原則中建立規則限制busybox應用只能訪問registry.aliyuncs.com。
在網路原則頁面右上方,單擊建立,然後在建立面板中配置網路原則規則。
設定類型為:無狀態
設定工作負載為:busybox
設定標籤為:app=busybox
選取器:ipBlock
cidr:120.55.XXX.XXX/32
在規則右側,單擊+添加,添加命名空間選取器為全部的規則。
在連接埠右側,單擊+添加。添加UDP 53的規則用來保障應用可以解析DNS。
規則:
選取器:namespaceSelector
命名空間:全部
連接埠:
協議:UDP
連接埠:53
單擊下一步,然後單擊確定。
在busybox終端分別訪問www.aliyun.com和registry.aliyuncs.com。
nc -vz -w 1 www.aliyunc.com 443nc -vz -w 1 registry.aliyuncs.com 443增加網路原則後,busybox應用只能訪問registry.aliyuncs.com而無法訪問其他地址。

關於具體的參數描述,請參見通過網路原則限制服務只能被帶有特定標籤的應用訪問。樣本配置如下。
配置項
說明
樣本值
名稱
自訂網路原則的名稱。
busybox-policy
Pod選取器
單擊+ 選擇工作負載添加標籤,設定使用網路原則的Pod。
說明如果Pod選取器設定為空白,則對命名空間下所有Pod生效。
本文樣本設定如下:
去向
在去向右側,單擊+添加,然後在規則右側,單擊+添加。
添加ipBlock為前面擷取的registry.aliyuncs.com的解析的IP地址(120.55.XXX.XXX)/32的規則。

在去向右側,單擊+添加,添加命名空間選取器為全部命名空間的UDP 53連接埠的訪問的規則,用來保障應用可以解析DNS。

kubectl
擷取www.aliyun.com網域名稱解析到的IP地址清單。
dig +short www.aliyun.com預期輸出:
www-jp-de-intl-adns.aliyun.com. www-jp-de-intl-adns.aliyun.com.gds.alibabadns.com. v6wagbridge.aliyun.com. v6wagbridge.aliyun.com.gds.alibabadns.com. 106.XX.XX.21 140.XX.XX.4 140.XX.XX.13 140.XX.XX.3建立busybox-policy檔案。
vim busybox-policy.yamlbusybox-policy檔案模板如下:
# 以下為YAML檔案內容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: busybox-policy spec: podSelector: matchLabels: run: busybox egress: - to: - ipBlock: cidr: 106.XX.XX.21/32 - ipBlock: cidr: 140.XX.XX.4/32 - ipBlock: cidr: 140.XX.XX.13/32 - ipBlock: cidr: 140.XX.XX.3/32 - to: - ipBlock: cidr: 0.0.0.0/0 - namespaceSelector: {} ports: - protocol: UDP port: 53說明在busybox-policy檔案中,配置了去向規則(Egress),限制應用的對外訪問。在這裡需配置允許UDP請求,否則無法做DNS解析。
根據busybox-policy檔案建立網路原則。
kubectl apply -f busybox-policy.yaml預期輸出:
networkpolicy.networking.k8s.io/busybox-policy created建立busybox。
kubectl run busybox --rm -ti --image=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 /bin/sh訪問www.aliyun.com之外的網站,例如,www.taobao.com:
wget www.taobao.com預期輸出:
Connecting to www.taobao.com (64.13.XX.XX:80) wget: can't connect to remote host (64.13.XX.XX): Connection timed out出現can't connect to remote host時,說明訪問服務失敗。
訪問www.aliyun.com。
wget www.aliyun.com預期輸出:
Connecting to www.aliyun.com (140.205.XX.XX:80) Connecting to www.aliyun.com (140.205.XX.XX:443) wget: note: TLS certificate validation not implemented index.html 100% |***********************************************************| 462k 0:00:00 ETA進行顯示100%,說明成功訪問服務。
情境四:通過網路原則控制命名空間下Pod公網存取權限
此操作有可能影響線上正在訪問公網的服務,建議在一個空的命名空間中進行以下操作。
控制台
在網路原則頁面右上方,單擊建立,然後在建立面板中配置網路原則規則。
關於具體的參數描述及操作,請參見通過網路原則限制服務只能被帶有特定標籤的應用訪問。樣本配置如下。
配置項
樣本值
名稱
deny-public-net
Pod選取器
設定類型為全部。
來源
添加以下兩條規則:
設定namespaceSelector的全部允許的規則。
設定ipBlock的全部允許的規則。

去向
添加只允許訪問內網的規則:
設定namespaceSelector的全部允許的規則,允許Pod訪問內網的所有Pod。
設定ipBlock的三條內網網段的規則,包括以下三個內網網段:
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
說明不可同時在一條ipBlock規則中添加多個網段。

單擊下一步,然後單擊確定。
在叢集詳情的基本資料頁簽,擷取內網IP和連接埠。

在busybox終端執行以下命令,分別測試Pod的公網存取權限和內網存取權限。
nc -vz -w 1 www.aliyunc.com 443nc -vz -w 1 10.xx.xx.xx:<IP連接埠> # 此處的IP地址為您的內網地址。說明Pod只能訪問內網的地址而無法訪問公網的地址。

kubectl
建立一個測試的命名空間來驗證限制的能力。
建立一個test-np的命名空間。
kubectl create ns test-np預期輸出:
namespace/test-np created為這個命名空間設定預設的只允許主動訪問私網的網路原則規則。
vim default-deny.yaml以下為default-deny.yaml檔案的樣本模板:
# 以下為YAML檔案內容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: namespace: test-np name: deny-public-net spec: podSelector: {} ingress: - from: - ipBlock: cidr: 0.0.0.0/0 egress: - to: - ipBlock: cidr: 192.168.0.0/16 - ipBlock: cidr: 172.16.0.0/12 - ipBlock: cidr: 10.0.0.0/8查看default-deny.yaml檔案是否已建立成功。
kubectl apply -f default-deny.yaml預期輸出:
networkpolicy.networking.k8s.io/deny-public-net created查看網路原則:
kubectl get networkpolicy -n test-np預期輸出:
NAME POD-SELECTOR AGE deny-public-net <none> 1m為特殊標籤的Pod設定允許訪問公網。
vim allow-specify-label.yaml樣本標籤設定為
public-network=true。# 以下為YAML檔案內容。 kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-public-network-for-labels namespace: test-np spec: podSelector: matchLabels: public-network: "true" ingress: - from: - ipBlock: cidr: 0.0.0.0/0 egress: - to: - ipBlock: cidr: 0.0.0.0/0 - namespaceSelector: matchLabels: ns: kube-system執行如下命令,建立網路原則:
kubectl apply -f allow-specify-label.yaml預期輸出:
networkpolicy.networking.k8s.io/allow-public-network-for-labels created查看網路原則:
kubectl get networkpolicy -n test-np預期輸出:
NAME POD-SELECTOR AGE allow-public-network-for-labels public-network=true 1m deny-public-net <none> 3m驗證無特殊標籤的Pod不能訪問公網。
kubectl run -it --namespace test-np --rm --image=registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 busybox-intranetping aliyun.com預期輸出:
PING aliyun.com (106.11.2xx.xxx): 56 data bytes ^C --- aliyun.com ping statistics --- 9 packets transmitted, 0 packets received, 100% packet loss顯示0 packets received時,說明訪問失敗。
說明訪問失敗的原因是:由於通過deny-public-net的網路原則規則限制了test-np的這個命名空間下的Pod的預設的公網訪問,所以它下面啟動的預設標籤的Pod無法訪問公網。
驗證帶有public-network=true的Pod可以訪問服務。
kubectl run -it --namespace test-np --labels public-network=true --rm --image registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 busybox-internetping aliyun.com預期輸出:
PING aliyun.com (106.11.1xx.xx): 56 data bytes 64 bytes from 106.11.1xx.xx: seq=0 ttl=47 time=4.235 ms 64 bytes from 106.11.1xx.xx: seq=1 ttl=47 time=4.200 ms 64 bytes from 106.11.1xx.xx: seq=2 ttl=47 time=4.182 ms ^C --- aliyun.com ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 4.182/4.205/4.235 ms顯示0% packet loss時,說明成功訪問服務。
說明可以正常訪問的原因是:由於在allow-public-network-for-labels的網路原則的規則中允許了帶有public-network=true的Pod的公網訪問,所以在帶有這個Label的busybox-internet的Pod可以訪問公網。