Kubernetes網絡策略Network Policy提供基于策略的網絡控制。如果您希望在IP地址或者端口層面控制網絡流量,您可以為集群中特定應用使用網絡策略。本文介紹如何使用ACK Serverless集群的網絡策略及常見的使用場景。
前提條件
已創建ACK托管集群或ACK專有集群,具體操作,請參見創建Kubernetes托管版集群、創建Kubernetes專有版集群。
重要ACK集群Pro版和ACK Serverless集群Network Policy的實現由不同組件承載。
在ACK集群Pro版(非ECI實例)中,Network Policy的實現由Terway插件負責。詳細信息,請參見在ACK中開啟網絡策略。
在ACK Serverless集群、ACK集群Pro版的ECI實例中,Network Policy的實現由Poseidon組件負責。詳細信息將在本文進行介紹。
需要將ACK Virtual Node組件升級至v2.10.0及以上版本。具體操作,請參見管理組件。
注意事項
Network Policy功能僅支持在ACK Serverless集群Pro版、ACK集群Pro版使用。
暫不支持IPv6地址的網絡策略。
暫不支持NetworkPolicy中EndPort配置。
NetworkPolicy規則允許通過LabelSelector選擇Namespace或者Pod。但當Pod中的NetworkPolicy數量增大時,不僅會使規則生效時間延長,而且大量的NetworkPolicy規則也會對您的集群管理、問題排查帶來困擾,因此建議您集群內的NetworkPolicy數量小于40個。
步驟一:開啟網絡策略
如需在ACK Serverless集群Pro版中使用Network Policy功能,需按照如下步驟進行操作。
安裝組件Poseidon。
登錄容器服務管理控制臺,在左側導航欄選擇集群。
在集群列表頁面,單擊目標集群名稱,然后在左側導航欄,選擇 。
在組件管理頁面,單擊網絡頁簽,在Poseidon組件所在卡片的右下方,單擊安裝。
在安裝組件 Poseidon頁面,選中為ECI 實例啟用 NetworkPolicy,然后單擊確認。
組件安裝成功后,會在卡片右上角出現已安裝字樣。
步驟二:創建可以被其他Pod正常訪問的nginx測試應用
通過控制臺操作
登錄容器服務管理控制臺,在左側導航欄選擇集群。
在集群列表頁面,單擊目標集群名稱,然后在左側導航欄,選擇 。
在無狀態頁面,單擊使用鏡像創建。在創建配置向導頁面中,創建一個名稱為nginx的應用,并通過Service將其公開。配置完成后,單擊創建。
本示例的nginx應用僅需配置以下配置項,其他配置項選擇默認配置。關于更多配置說明,請參見使用鏡像創建無狀態Deployment應用。
頁面
配置項
說明
示例值
應用基本信息
應用名稱
自定義名稱。
nginx
副本數量
按需選擇。
1
容器配置
鏡像名稱
單擊選擇鏡像,選擇所需的鏡像并單擊確定。
本例選擇官方Nginx鏡像,可以在搜索頁簽中,選擇Docker官方鏡像,然后在文本框中輸入nginx進行搜索。
高級配置
服務(Service)
在服務(Service)右側,單擊創建設置服務配置項。
名稱:nginx
類型:
負載均衡
公網訪問
新建SLB
端口映射:
名稱:nginx
服務端口:80
容器端口:80
協議:TCP
再次在無狀態頁面,單擊使用鏡像創建。在創建配置向導頁面中,創建用于測試訪問名稱為busybox的客戶端應用,用于測試訪問上一步中創建的名為nginx的Service。
本示例的busybox客戶端應用僅需配置以下配置項,其他配置項選擇默認配置。關于更多配置說明,請參見使用鏡像創建無狀態Deployment應用。。
頁面
配置項
說明
示例值
應用基本信息
應用名稱
自定義名稱。
busybox
副本數量
按需取值。
1
容器啟動項
鏡像名稱
單擊選擇鏡像,選擇所需的鏡像并單擊確定。
本例選擇官方busybox鏡像,可以在搜索頁簽中,選擇Docker官方鏡像,然后在文本框中輸busybox進行搜索。
容器啟動項
無
選中stdin和tty
驗證busybox客戶端應用是否可以訪問nginx Service。
在無狀態頁面,找到并單擊busybox名稱。
在容器組頁簽下的busybox-{hash值}容器組右側,單擊終端。
在busybox的命令行終端中執行
wget nginx
測試訪問nginx。當出現以上信息時,說明您可以在busybox中訪問nginx Service。
通過命令行操作
執行以下命令,創建一個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=busybox /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
步驟三:使用網絡策略
以下幾種場景均支持使用網絡策略,您可以按需選擇。
場景一:通過網絡策略限制服務只能被帶有特定標簽的應用訪問
使用以下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=busybox /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=busybox /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的應用創建阿里云SLB服務,指定
type=LoadBalancer
來向外網用戶暴露nginx服務。vim nginx-service.yaml
nginx-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=busybox /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域名解析到的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.yaml
busybox-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=busybox /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公網訪問權限
此操作有可能影響線上正在訪問公網的服務,建議在一個空的命名空間中進行以下操作。
執行以下命令,創建一個測試的命名空間來驗證限制的能力。
創建一個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 busybox busybox-intranet
ping 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 busybox busybox-internet
ping 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可以訪問公網。